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

Last change on this file since 18 was 15, checked in by Bayard Gildas, 8 years ago

sources reformatted with flair-format-dir script

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