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

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

sources reformatted with flair-format-dir script

File size: 9.5 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,
53                       ISceneManager *scenemanager, vrpn_Connection_IP *vrpn)
54    : ISceneNode(scenemanager->getRootSceneNode(), scenemanager, -1),
55      Thread(self, name, 50), vrpn_Tracker(name.c_str(), vrpn)
56
57#else
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
61{
62  this->self = self;
63
64#ifdef GL
65  // for sync with gui
66  cond = new ConditionVariable(this, name);
67  sync_count = 0;
68
69  // collisions
70  collision_mutex = new Mutex(this);
71  collision_occured = false;
72
73  // selector for collisions
74  selector = getSceneManager()->createTriangleSelectorFromBoundingBox(this);
75  setTriangleSelector(selector);
76  meta_selector = getSceneManager()->createMetaTriangleSelector();
77
78  anim = getSceneManager()->createCollisionResponseAnimator(
79      meta_selector, this, vector3df(1, 1, 1), vector3df(0, 0, 0),
80      vector3df(0, 0, 0));
81  addAnimator(anim);
82
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));
88
89  animator = new AnimPoursuite(this);
90  camera->addAnimator(animator);
91  camera->setFarValue(8000);
92
93  position_init = false;
94#endif
95
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);
106
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;
117
118  self->state[-1] = self->state[0];
119  self->state[-2] = self->state[0];
120
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");
136
137  self->AddDataToLog(output);
138}
139
140Model_impl::~Model_impl() {
141  SafeStop();
142  Join();
143#ifdef GL
144  remove(); // remove ISceneNode
145#endif
146}
147
148Quaternion Model_impl::ComputeInitRotation(Quaternion quat_in) {
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;
153}
154
155void Model_impl::mainloop(void) {
156  if (enable_opti->Value() == false)
157    return;
158  vrpn_gettimeofday(&_timestamp, NULL);
159  vrpn_Tracker::timestamp = _timestamp;
160
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();
166
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;
176
177  char msgbuf[1000];
178
179  d_sensor = 0;
180
181  int len = vrpn_Tracker::encode_to(msgbuf);
182
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  }
187
188  server_mainloop();
189}
190
191#ifdef GL
192ITriangleSelector *Model_impl::TriangleSelector(void) { return selector; }
193
194IMetaTriangleSelector *Model_impl::MetaTriangleSelector(void) {
195  return meta_selector;
196}
197
198void Model_impl::UpdatePos(void) {
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) *
212                          vector3df(euler.roll, euler.pitch, euler.yaw));
213
214  if (position_init == false) {
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  // TODO: setEllipsoidRadius should be called in Model::setScale
224  // but we need to call recalculateBoundingBox
225  anim->setEllipsoidRadius(getTransformedBoundingBox().getExtent());
226
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);
237
238    collision_mutex->GetMutex();
239    collision_occured = true;
240    collision_point = ToSimulatorCoordinates(nodePosition);
241    collision_mutex->ReleaseMutex();
242  }
243}
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();
256}
257
258void Model_impl::OnRegisterSceneNode(void) {
259  if (IsVisible)
260    SceneManager->registerNodeForRendering(this);
261
262  ISceneNode::OnRegisterSceneNode();
263}
264
265void Model_impl::render(void) {
266  IVideoDriver *driver = SceneManager->getVideoDriver();
267  driver->setTransform(ETS_WORLD, AbsoluteTransformation);
268}
269
270// le premier arrive attend l'autre
271void Model_impl::SynchronizationPoint() {
272  cond->GetMutex();
273  sync_count++;
274
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
289#ifdef GL
290  // synchronize with gui
291  SynchronizationPoint();
292#endif
293
294  SetPeriodMS(dT->Value() * 1000.);
295
296  while (!ToBeStopped()) {
297    if (dT->ValueChanged())
298      SetPeriodMS(dT->Value() * 1000.);
299    WaitPeriod();
300
301#ifdef GL
302    CollisionHandler();
303#endif
304    states_mutex->GetMutex();
305    self->CalcModel();
306
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());
323
324    self->state.Update();
325
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;
331#ifdef GL
332      position_init = false;
333#endif
334    }
335
336    states_mutex->ReleaseMutex();
337
338    self->ProcessUpdate(output);
339  }
340
341  WarnUponSwitches(false);
342}
Note: See TracBrowser for help on using the repository browser.