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

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

add timestamp to simucamera producer

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