source: flair-src/trunk/lib/FlairSimulator/src/Model_impl.cpp@ 10

Last change on this file since 10 was 10, checked in by Sanahuja Guillaume, 8 years ago

lic

File size: 9.7 KB
Line 
1// %flair:license{
2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
4// %flair:license}
5// created: 2013/03/25
6// filename: Model_impl.cpp
7//
8// author: Guillaume Sanahuja
9// Copyright Heudiasyc UMR UTC/CNRS 7253
10//
11// version: $Id: $
12//
13// purpose: classe definissant un modele a simuler
14//
15/*********************************************************************/
16
17#include "Model.h"
18#include "Model_impl.h"
19#include "Simulator.h"
20#include "TabWidget.h"
21#include "Tab.h"
22#include "DoubleSpinBox.h"
23#include "Vector3DSpinBox.h"
24#include "SpinBox.h"
25#include "CheckBox.h"
26#include "cvmatrix.h"
27#include "Euler.h"
28#include <math.h>
29
30#ifdef GL
31#include "ConditionVariable.h"
32#include "Gui.h"
33#include "Gui_impl.h"
34#include <ISceneManager.h>
35#include <ISceneNodeAnimatorCollisionResponse.h>
36#include <IMetaTriangleSelector.h>
37#include <IVideoDriver.h>
38#include <ICameraSceneNode.h>
39#include "AnimPoursuite.h"
40using namespace irr;
41using namespace video;
42using namespace scene;
43using namespace core;
44using namespace io;
45#endif
46
47using namespace flair::core;
48using namespace flair::gui;
49using namespace flair::simulator;
50
51#ifdef GL
52Model_impl::Model_impl(Model* self,std::string name,ISceneManager* scenemanager,vrpn_Connection_IP* vrpn)
53 : ISceneNode(scenemanager->getRootSceneNode(), scenemanager, -1),Thread(self,name,50),vrpn_Tracker( name.c_str(), vrpn )
54
55#else
56Model_impl::Model_impl(Model* self,std::string name,vrpn_Connection_IP* vrpn)
57 : Thread(self,name,50),vrpn_Tracker( name.c_str(), vrpn )
58#endif
59{
60 this->self=self;
61
62#ifdef GL
63 //for sync with gui
64 cond=new ConditionVariable(this,name);
65 sync_count=0;
66
67 //collisions
68 collision_mutex=new Mutex(this);
69 collision_occured=false;
70
71 //selector for collisions
72 selector = getSceneManager()->createTriangleSelectorFromBoundingBox(this);
73 setTriangleSelector(selector);
74 meta_selector = getSceneManager()->createMetaTriangleSelector();
75
76 anim = getSceneManager()->createCollisionResponseAnimator(meta_selector, this,vector3df(1,1,1),vector3df(0,0,0), vector3df(0,0,0));
77 addAnimator(anim);
78
79 //camera
80 camera =getSceneManager()->addCameraSceneNode();
81 camera->setAspectRatio(getGui()->getAspectRatio());//on force a cause du view port
82 camera->setUpVector(vector3df(0,0,1));
83
84 animator=new AnimPoursuite(this);
85 camera->addAnimator(animator);
86 camera->setFarValue(8000);
87
88 position_init=false;
89#endif
90
91 //init user interface
92 Tab* tab=new Tab(getSimulator()->GetTabWidget(),ObjectName());
93 tabwidget=new TabWidget(tab->NewRow(),"tabs");
94 Tab* sampl=new Tab(tabwidget,"sampling");
95 dT=new DoubleSpinBox(sampl->NewRow(),"Tech (s):",0.001,1,0.001,3);
96 Tab* layout=new Tab(tabwidget,"optitrack");
97 enable_opti=new CheckBox(layout->NewRow(),"enabled");
98 Tab* init=new Tab(tabwidget,"init");
99 pos_init=new Vector3DSpinBox(init->NewRow(),"position",-50,50,1);
100 yaw_init=new SpinBox(init->NewRow(),"yaw (deg):",-180,180,10);
101
102 //modele
103 states_mutex=new Mutex(this);
104 self->state[0].Pos=pos_init->Value();
105 self->state[0].Vel.x=0;
106 self->state[0].Vel.y=0;
107 self->state[0].Vel.z=0;
108 self->state[0].Quat=ComputeInitRotation(Quaternion(1,0,0,0));
109 self->state[0].W.x=0;
110 self->state[0].W.y=0;
111 self->state[0].W.z=0;
112
113 self->state[-1]=self->state[0];
114 self->state[-2]=self->state[0];
115
116 cvmatrix_descriptor* desc=new cvmatrix_descriptor(13,1);
117 desc->SetElementName(0,0,"q0");
118 desc->SetElementName(1,0,"q1");
119 desc->SetElementName(2,0,"q2");
120 desc->SetElementName(3,0,"q3");
121 desc->SetElementName(4,0,"x");
122 desc->SetElementName(5,0,"y");
123 desc->SetElementName(6,0,"z");
124 desc->SetElementName(7,0,"wx");
125 desc->SetElementName(8,0,"wy");
126 desc->SetElementName(9,0,"wz");
127 desc->SetElementName(10,0,"vx");
128 desc->SetElementName(11,0,"vy");
129 desc->SetElementName(12,0,"vz");
130 output=new cvmatrix(this,desc,floatType,"state");
131
132 self->AddDataToLog(output);
133}
134
135Model_impl::~Model_impl()
136{
137 SafeStop();
138 Join();
139#ifdef GL
140 remove();//remove ISceneNode
141#endif
142}
143
144Quaternion Model_impl::ComputeInitRotation(Quaternion quat_in) {
145 Quaternion yaw_rot_quat;
146 Euler yaw_rot_euler(0,0,Euler::ToRadian(yaw_init->Value()));
147 yaw_rot_euler.ToQuaternion(yaw_rot_quat);
148 return yaw_rot_quat*quat_in;
149}
150
151void Model_impl::mainloop(void)
152{
153 if(enable_opti->Value()==false) return;
154 vrpn_gettimeofday(&_timestamp, NULL);
155 vrpn_Tracker::timestamp = _timestamp;
156
157 //change to vrpn reference
158 states_mutex->GetMutex();
159 Quaternion quat=getSimulator()->ToVRPNReference(self->state[0].Quat);
160 Vector3D position=getSimulator()->ToVRPNReference(self->state[0].Pos);
161 states_mutex->ReleaseMutex();
162
163 pos[0]=position.x;
164 pos[1]=position.y;
165 pos[2]=position.z;
166 //warning: d_quat is defined as (qx,qy,qz,qw), which is different from flair::core::Quaternion
167 d_quat[0] = quat.q1;
168 d_quat[1] = quat.q2;
169 d_quat[2] = quat.q3;
170 d_quat[3] = quat.q0;
171
172 char msgbuf[1000];
173
174 d_sensor = 0;
175
176 int len = vrpn_Tracker::encode_to(msgbuf);
177
178 if (d_connection->pack_message(len, _timestamp, position_m_id, d_sender_id, msgbuf, vrpn_CONNECTION_LOW_LATENCY))
179 {
180 fprintf(stderr,"can't write message: tossing\n");
181 }
182
183 server_mainloop();
184}
185
186#ifdef GL
187ITriangleSelector* Model_impl::TriangleSelector(void)
188{
189 return selector;
190}
191
192IMetaTriangleSelector* Model_impl::MetaTriangleSelector(void)
193{
194 return meta_selector;
195}
196
197void Model_impl::UpdatePos(void)
198{
199 vector3df nodePosition;
200 Quaternion nodeOrientation;
201 Euler euler;
202
203 states_mutex->GetMutex();
204 nodePosition=ToIrrlichtCoordinates(self->state[0].Pos);
205 nodeOrientation=ToIrrlichtOrientation(self->state[0].Quat);
206 states_mutex->ReleaseMutex();
207
208 setPosition(nodePosition);
209
210 nodeOrientation.ToEuler(euler);
211 ISceneNode::setRotation(Euler::ToDegree(1)*vector3df(euler.roll,euler.pitch,euler.yaw));
212
213 if(position_init==false)
214 {
215 anim->setTargetNode(this); // a faire pour se teleporter sans les collisions
216 position_init=true;
217 }
218
219 self->AnimateModel();
220}
221
222void Model_impl::CheckCollision(void)
223{
224 //TODO: setEllipsoidRadius should be called in Model::setScale
225 //but we need to call recalculateBoundingBox
226 anim->setEllipsoidRadius(getTransformedBoundingBox().getExtent());
227
228 if(anim->collisionOccurred()==true)
229 {
230 vector3df pos;
231 vector3df pos_rel;
232 vector3df nodePosition;
233 pos= anim->getCollisionPoint();
234 nodePosition=getPosition();
235 pos_rel=pos-nodePosition;
236 //printf("collision %f %f %f\n",pos.X,pos.Y,pos.Z);
237 //printf("drone %f %f %f\n",nodePosition.X,nodePosition.Y,nodePosition.Z);
238 //printf("rel %f %f %f\n",pos_rel.X,pos_rel.Z,pos_rel.Y);
239
240 collision_mutex->GetMutex();
241 collision_occured=true;
242 collision_point=ToSimulatorCoordinates(nodePosition);
243 collision_mutex->ReleaseMutex();
244 }
245}
246
247void Model_impl::CollisionHandler(void)
248{
249 collision_mutex->GetMutex();
250 if(collision_occured==true)
251 {
252 collision_occured=false;
253 states_mutex->GetMutex();
254 self->state[0].Pos=collision_point;
255 self->state[-1].Pos=self->state[0].Pos;
256 self->state[-2].Pos=self->state[0].Pos;
257 states_mutex->ReleaseMutex();
258 }
259 collision_mutex->ReleaseMutex();
260}
261
262void Model_impl::OnRegisterSceneNode(void)
263{
264 if (IsVisible)
265 SceneManager->registerNodeForRendering(this);
266
267 ISceneNode::OnRegisterSceneNode();
268}
269
270void Model_impl::render(void)
271{
272 IVideoDriver* driver = SceneManager->getVideoDriver();
273 driver->setTransform(ETS_WORLD, AbsoluteTransformation);
274}
275
276//le premier arrive attend l'autre
277void Model_impl::SynchronizationPoint()
278{
279 cond->GetMutex();
280 sync_count++;
281
282 if (sync_count < 2)
283 {
284 cond->CondWait();
285 }
286 else
287 {
288 cond->CondSignal();
289 }
290
291 cond->ReleaseMutex();
292}
293#endif //GL
294
295void Model_impl::Run(void)
296{
297 // Ask Xenomai to warn us upon switches to secondary mode.
298 WarnUponSwitches(true);
299
300#ifdef GL
301 //synchronize with gui
302 SynchronizationPoint();
303#endif
304
305 SetPeriodMS(dT->Value()*1000.);
306
307 while(!ToBeStopped())
308 {
309 if(dT->ValueChanged()) SetPeriodMS(dT->Value()*1000.);
310 WaitPeriod();
311
312#ifdef GL
313 CollisionHandler();
314#endif
315 states_mutex->GetMutex();
316 self->CalcModel();
317
318 output->GetMutex();
319 output->SetValueNoMutex(0,0,self->state[0].Quat.q0);
320 output->SetValueNoMutex(1,0,self->state[0].Quat.q1);
321 output->SetValueNoMutex(2,0,self->state[0].Quat.q2);
322 output->SetValueNoMutex(3,0,self->state[0].Quat.q3);
323 output->SetValueNoMutex(4,0,self->state[0].Pos.x);
324 output->SetValueNoMutex(5,0,self->state[0].Pos.y);
325 output->SetValueNoMutex(6,0,self->state[0].Pos.z);
326 output->SetValueNoMutex(7,0,self->state[0].W.x);
327 output->SetValueNoMutex(8,0,self->state[0].W.y);
328 output->SetValueNoMutex(9,0,self->state[0].W.z);
329 output->SetValueNoMutex(10,0,self->state[0].Vel.x);
330 output->SetValueNoMutex(11,0,self->state[0].Vel.y);
331 output->SetValueNoMutex(12,0,self->state[0].Vel.z);
332 output->ReleaseMutex();
333 output->SetDataTime(GetTime());
334
335 self->state.Update();
336
337 if(pos_init->ValueChanged() || yaw_init->ValueChanged())
338 {
339 self->state[-1].Quat=ComputeInitRotation(Quaternion(1,0,0,0));
340 self->state[-2].Quat=ComputeInitRotation(Quaternion(1,0,0,0));
341 self->state[-1].Pos=pos_init->Value();
342 self->state[-2].Pos=self->state[-1].Pos;
343#ifdef GL
344 position_init=false;
345#endif
346 }
347
348 states_mutex->ReleaseMutex();
349
350 self->ProcessUpdate(output);
351
352 }
353
354 WarnUponSwitches(false);
355}
Note: See TracBrowser for help on using the repository browser.