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

Last change on this file since 158 was 158, checked in by Sanahuja Guillaume, 5 years ago

corrected simu/device id for sensors

File size: 9.4 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 "Simulator_impl.h"
21#include "TabWidget.h"
22#include "Tab.h"
23#include "DoubleSpinBox.h"
24#include "Vector3DSpinBox.h"
25#include "SpinBox.h"
26#include "CheckBox.h"
27#include "cvmatrix.h"
28#include "Euler.h"
29#include <math.h>
30
31#ifdef GL
32#include "ConditionVariable.h"
33#include "Gui.h"
34#include "Gui_impl.h"
35#include <ISceneManager.h>
36#include <ISceneNodeAnimatorCollisionResponse.h>
37#include <IMetaTriangleSelector.h>
38#include <IVideoDriver.h>
39#include <ICameraSceneNode.h>
40#include "FollowMeCamera.h"
41
42using namespace irr;
43using namespace video;
44using namespace scene;
45using namespace core;
46using namespace io;
47#endif
48
49using namespace flair::core;
50using namespace flair::gui;
51using namespace flair::simulator;
52
53#ifdef GL
54Model_impl::Model_impl(Model *self, std::string name,uint32_t modelId)
55 : ISceneNode(getGui()->getSceneManager()->getRootSceneNode(), getGui()->getSceneManager(), -1),
56 Thread(self, name, 50), vrpn_Tracker(name.c_str(), getSimulator()->pimpl_)
57
58#else
59Model_impl::Model_impl(Model *self, std::string name,uint32_t modelId)
60 : Thread(self, name, 50), vrpn_Tracker(name.c_str(), getSimulator()->pimpl_)
61#endif
62{
63 this->self = self;
64 this->modelId=modelId;
65
66#ifdef GL
67 // for sync with gui
68 cond = new ConditionVariable(this, name);
69 sync_count = 0;
70
71 // collisions
72 collision_mutex = new Mutex(this);
73 collision_occured = false;
74
75 // selector for collisions
76 selector = getSceneManager()->createTriangleSelectorFromBoundingBox(this);
77 setTriangleSelector(selector);
78 meta_selector = getSceneManager()->createMetaTriangleSelector();
79
80 anim = getSceneManager()->createCollisionResponseAnimator(
81 meta_selector, this, vector3df(1, 1, 1), vector3df(0, 0, 0),
82 vector3df(0, 0, 0));
83 addAnimator(anim);
84
85 // camera
86 camera = new FollowMeCamera(this,name);
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 delete desc;
132
133 self->AddDataToLog(output);
134
135 getSimulator()->pimpl_->models.push_back(self);
136}
137
138Model_impl::~Model_impl() {
139 SafeStop();
140 Join();
141#ifdef GL
142 remove(); // remove ISceneNode
143#endif
144}
145
146Quaternion Model_impl::ComputeInitRotation(Quaternion quat_in) {
147 Quaternion yaw_rot_quat;
148 Euler yaw_rot_euler(0, 0, Euler::ToRadian(yaw_init->Value()));
149 yaw_rot_euler.ToQuaternion(yaw_rot_quat);
150 return yaw_rot_quat * quat_in;
151}
152
153void Model_impl::mainloop(void) {
154 if (enable_opti->Value() == false)
155 return;
156 vrpn_gettimeofday(&_timestamp, NULL);
157 vrpn_Tracker::timestamp = _timestamp;
158
159 // change to vrpn reference
160 states_mutex->GetMutex();
161 Quaternion quat = getSimulator()->ToVRPNReference(self->state[0].Quat);
162 Vector3D position = getSimulator()->ToVRPNReference(self->state[0].Pos);
163 states_mutex->ReleaseMutex();
164
165 pos[0] = position.x;
166 pos[1] = position.y;
167 pos[2] = position.z;
168 // warning: d_quat is defined as (qx,qy,qz,qw), which is different from
169 // flair::core::Quaternion
170 d_quat[0] = quat.q1;
171 d_quat[1] = quat.q2;
172 d_quat[2] = quat.q3;
173 d_quat[3] = quat.q0;
174
175 char msgbuf[1000];
176
177 d_sensor = 0;
178
179 int len = vrpn_Tracker::encode_to(msgbuf);
180
181 if (d_connection->pack_message(len, _timestamp, position_m_id, d_sender_id,
182 msgbuf, vrpn_CONNECTION_LOW_LATENCY)) {
183 fprintf(stderr, "can't write message: tossing\n");
184 }
185
186 server_mainloop();
187}
188
189#ifdef GL
190ITriangleSelector *Model_impl::TriangleSelector(void) { return selector; }
191
192IMetaTriangleSelector *Model_impl::MetaTriangleSelector(void) {
193 return meta_selector;
194}
195
196void Model_impl::UpdatePos(void) {
197 vector3df nodePosition;
198 Quaternion nodeOrientation;
199 Euler euler;
200
201 states_mutex->GetMutex();
202 nodePosition = ToIrrlichtCoordinates(self->state[0].Pos);
203 nodeOrientation = ToIrrlichtOrientation(self->state[0].Quat);
204 states_mutex->ReleaseMutex();
205
206 setPosition(nodePosition);
207
208 nodeOrientation.ToEuler(euler);
209 ISceneNode::setRotation(Euler::ToDegree(1) * vector3df(euler.roll,euler.pitch, euler.yaw));
210
211 if (position_init == false) {
212 anim->setTargetNode(this); // a faire pour se teleporter sans les collisions
213 position_init = true;
214 }
215
216 self->AnimateModel();
217}
218
219void Model_impl::CheckCollision(void) {
220 // TODO: setEllipsoidRadius should be called in Model::setScale
221 // but we need to call recalculateBoundingBox
222 anim->setEllipsoidRadius(getTransformedBoundingBox().getExtent());
223
224 if (anim->collisionOccurred() == true) {
225 vector3df pos;
226 vector3df pos_rel;
227 vector3df nodePosition;
228 pos = anim->getCollisionPoint();
229 nodePosition = getPosition();
230 pos_rel = pos - nodePosition;
231 // printf("collision %f %f %f\n",pos.X,pos.Y,pos.Z);
232 // printf("drone %f %f %f\n",nodePosition.X,nodePosition.Y,nodePosition.Z);
233 // printf("rel %f %f %f\n",pos_rel.X,pos_rel.Z,pos_rel.Y);
234
235 collision_mutex->GetMutex();
236 collision_occured = true;
237 collision_point = ToSimulatorCoordinates(nodePosition);
238 collision_mutex->ReleaseMutex();
239 }
240}
241
242void Model_impl::CollisionHandler(void) {
243 collision_mutex->GetMutex();
244 if (collision_occured == true) {
245 collision_occured = false;
246 states_mutex->GetMutex();
247 self->state[0].Pos = collision_point;
248 self->state[-1].Pos = self->state[0].Pos;
249 self->state[-2].Pos = self->state[0].Pos;
250 states_mutex->ReleaseMutex();
251 }
252 collision_mutex->ReleaseMutex();
253}
254
255void Model_impl::OnRegisterSceneNode(void) {
256 if (IsVisible)
257 SceneManager->registerNodeForRendering(this);
258
259 ISceneNode::OnRegisterSceneNode();
260}
261
262void Model_impl::render(void) {
263 IVideoDriver *driver = SceneManager->getVideoDriver();
264 driver->setTransform(ETS_WORLD, AbsoluteTransformation);
265}
266
267// le premier arrive attend l'autre
268void Model_impl::SynchronizationPoint() {
269 cond->GetMutex();
270 sync_count++;
271
272 if (sync_count < 2) {
273 cond->CondWait();
274 } else {
275 cond->CondSignal();
276 }
277
278 cond->ReleaseMutex();
279}
280#endif // GL
281
282void Model_impl::Run(void) {
283 // Ask Xenomai to warn us upon switches to secondary mode.
284 WarnUponSwitches(true);
285
286#ifdef GL
287 // synchronize with gui
288 SynchronizationPoint();
289#endif
290
291 SetPeriodMS(dT->Value() * 1000.);
292
293 while (!ToBeStopped()) {
294 if (dT->ValueChanged())
295 SetPeriodMS(dT->Value() * 1000.);
296 WaitPeriod();
297
298#ifdef GL
299 CollisionHandler();
300#endif
301 states_mutex->GetMutex();
302 self->CalcModel();
303
304 output->GetMutex();
305 output->SetValueNoMutex(0, 0, self->state[0].Quat.q0);
306 output->SetValueNoMutex(1, 0, self->state[0].Quat.q1);
307 output->SetValueNoMutex(2, 0, self->state[0].Quat.q2);
308 output->SetValueNoMutex(3, 0, self->state[0].Quat.q3);
309 output->SetValueNoMutex(4, 0, self->state[0].Pos.x);
310 output->SetValueNoMutex(5, 0, self->state[0].Pos.y);
311 output->SetValueNoMutex(6, 0, self->state[0].Pos.z);
312 output->SetValueNoMutex(7, 0, self->state[0].W.x);
313 output->SetValueNoMutex(8, 0, self->state[0].W.y);
314 output->SetValueNoMutex(9, 0, self->state[0].W.z);
315 output->SetValueNoMutex(10, 0, self->state[0].Vel.x);
316 output->SetValueNoMutex(11, 0, self->state[0].Vel.y);
317 output->SetValueNoMutex(12, 0, self->state[0].Vel.z);
318 output->ReleaseMutex();
319 output->SetDataTime(GetTime());
320
321 self->state.Update();
322
323 if (pos_init->ValueChanged() || yaw_init->ValueChanged()) {
324 self->state[-1].Quat = ComputeInitRotation(Quaternion(1, 0, 0, 0));
325 self->state[-2].Quat = ComputeInitRotation(Quaternion(1, 0, 0, 0));
326 self->state[-1].Pos = pos_init->Value();
327 self->state[-2].Pos = self->state[-1].Pos;
328#ifdef GL
329 position_init = false;
330#endif
331 }
332
333 states_mutex->ReleaseMutex();
334
335 self->ProcessUpdate(output);
336 }
337
338 WarnUponSwitches(false);
339}
Note: See TracBrowser for help on using the repository browser.