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

Last change on this file since 383 was 375, checked in by Sanahuja Guillaume, 3 years ago

update ugv

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