source: flair-src/trunk/lib/FlairSimulator/src/X8.cpp @ 339

Last change on this file since 339 was 339, checked in by Sanahuja Guillaume, 2 years ago

allow all blade rotations

File size: 15.9 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:    2014/04/03
6//  filename:   X8.cpp
7//
8//  author:     Majd Saied, Guillaume Sanahuja
9//              Copyright Heudiasyc UMR UTC/CNRS 7253
10//
11//  version:    $Id: $
12//
13//  purpose:    classe definissant un X8
14//
15/*********************************************************************/
16
17#include "X8.h"
18#include <SimuBldc.h>
19#include <TabWidget.h>
20#include <Tab.h>
21#include <DoubleSpinBox.h>
[214]22#include <SpinBox.h>
[8]23#include <GroupBox.h>
24#include <math.h>
25#ifdef GL
26#include <ISceneManager.h>
27#include "Blade.h"
28#include "MeshSceneNode.h"
29#include "Gui.h"
30#include <Mutex.h>
31#endif
32
[15]33#define K_MOT 0.4f    // blade animation
34#define G (float)9.81 // gravity ( N/(m/s²) )
[8]35
36#ifdef GL
37using namespace irr::video;
38using namespace irr::scene;
39using namespace irr::core;
40#endif
41using namespace flair::core;
42using namespace flair::gui;
43using namespace flair::actuator;
44
[15]45namespace flair {
46namespace simulator {
[8]47
[158]48X8::X8(std::string name, uint32_t modelId): Model( name,modelId) {
[15]49  Tab *setup_tab = new Tab(GetTabWidget(), "model");
50  m = new DoubleSpinBox(setup_tab->NewRow(), "mass (kg):", 0, 20, 0.1);
51  arm_length = new DoubleSpinBox(setup_tab->LastRowLastCol(), "arm length (m):",
52                                 0, 2, 0.1);
53  l_cg = new DoubleSpinBox(
54      setup_tab->LastRowLastCol(), "position G (m):", -0.5, 0.5,
55      0.02); // position du centre de gravité/centre de poussé
56  k_mot =
57      new DoubleSpinBox(setup_tab->NewRow(), "k_mot:", 0, 1, 0.001,
58                        3); // vitesse rotation² (unité arbitraire) -> force (N)
59  c_mot = new DoubleSpinBox(
60      setup_tab->LastRowLastCol(), "c_mot:", 0, 1, 0.001,
61      3); // vitesse rotation moteur -> couple (N.m/unité arbitraire)
62  f_air_vert = new DoubleSpinBox(setup_tab->NewRow(), "f_air_vert:", 0, 10,
63                                 1); // frottements air depl. vertical, aussi
64                                     // utilisé pour les rotations ( N/(m/s) )
65                                     // (du aux helices en rotation)
66  f_air_lat =
67      new DoubleSpinBox(setup_tab->LastRowLastCol(), "f_air_lat:", 0, 10,
68                        1); // frottements air deplacements lateraux ( N/(m/s) )
69  j_roll = new DoubleSpinBox(setup_tab->NewRow(), "j_roll:", 0, 1, 0.001,
70                             5); // moment d'inertie d'un axe (N.m.s²/rad)
71  j_pitch =
72      new DoubleSpinBox(setup_tab->LastRowLastCol(), "j_pitch:", 0, 1, 0.001,
73                        5); // moment d'inertie d'un axe (N.m.s²/rad)
74  j_yaw = new DoubleSpinBox(setup_tab->LastRowLastCol(), "j_yaw:", 0, 1, 0.001,
75                            5); // moment d'inertie d'un axe (N.m.s²/rad)
76  j_r = new DoubleSpinBox(setup_tab->NewRow(), "j_r:", 0, 1,
77                          0.001); // moment des helices (N.m.s²/rad)
78  sigma = new DoubleSpinBox(
79      setup_tab->LastRowLastCol(), "sigma:", 0, 1,
80      0.1); // coefficient de perte d efficacite aerodynamique (sans unite)
81  S = new DoubleSpinBox(
82      setup_tab->LastRowLastCol(), "S:", 1, 2,
83      0.1); // coefficient de forme des helices 1<S=1+Ss/Sprop<2 (sans unite)
[214]84     
85  motorTimeout = new SpinBox(setup_tab->NewRow(), "motor timeout:","ms", 0, 1000, 100,100);
[8]86
[158]87  motors = new SimuBldc(this, name, 8, modelId,0);
[157]88 
89  SetIsReady(true);
[8]90}
91
[15]92void X8::Draw() {
[8]93#ifdef GL
94
[15]95  // create unite (1m=100cm) UAV; scale will be adapted according to arm_length
96  // parameter
97  // note that the frame used is irrlicht one:
98  // left handed, North East Up
[8]99
[15]100  const IGeometryCreator *geo;
101  geo = getGui()->getSceneManager()->getGeometryCreator();
[8]102
[15]103  // cylinders are aligned with y axis
[158]104  IMesh *red_arm = geo->createCylinderMesh(2.5, 100, 16, SColor(0, 255, 0, 0));
105  IMesh *black_arm = geo->createCylinderMesh(2.5, 100, 16, SColor(0, 128, 128, 128));
106  IMesh *motor = geo->createCylinderMesh(7.5, 15, 16); //,SColor(0, 128, 128, 128));
[15]107  // geo->drop();
[8]108
[15]109  ITexture *texture = getGui()->getTexture("carbone.jpg");
[158]110  MeshSceneNode *fl_arm = new MeshSceneNode(this, red_arm, vector3df(0, 0, 0),
[15]111                             vector3df(0, 0, -135));
[158]112  MeshSceneNode *fr_arm = new MeshSceneNode(this, red_arm, vector3df(0, 0, 0),
[15]113                             vector3df(0, 0, -45));
[158]114  MeshSceneNode *rl_arm = new MeshSceneNode(this, black_arm, vector3df(0, 0, 0),
[15]115                             vector3df(0, 0, 135), texture);
[158]116  MeshSceneNode *rr_arm = new MeshSceneNode(this, black_arm, vector3df(0, 0, 0),
[15]117                             vector3df(0, 0, 45), texture);
[8]118
[15]119  texture = getGui()->getTexture("metal047.jpg");
[158]120  MeshSceneNode *tfl_motor = new MeshSceneNode(this, motor, vector3df(70.71, -70.71, 2.5),
[15]121                                vector3df(90, 0, 0), texture);
[158]122  MeshSceneNode *tfr_motor = new MeshSceneNode(this, motor, vector3df(70.71, 70.71, 2.5),
[15]123                                vector3df(90, 0, 0), texture);
[158]124  MeshSceneNode *trl_motor = new MeshSceneNode(this, motor, vector3df(-70.71, -70.71, 2.5),
[15]125                                vector3df(90, 0, 0), texture);
[158]126  MeshSceneNode *trr_motor = new MeshSceneNode(this, motor, vector3df(-70.71, 70.71, 2.5),
[15]127                                vector3df(90, 0, 0), texture);
[8]128
[158]129  MeshSceneNode *bfl_motor = new MeshSceneNode(this, motor, vector3df(70.71, -70.71, -17.5),
[15]130                                vector3df(90, 0, 0), texture);
[158]131  MeshSceneNode *bfr_motor = new MeshSceneNode(this, motor, vector3df(70.71, 70.71, -17.5),
[15]132                                vector3df(90, 0, 0), texture);
[158]133  MeshSceneNode *brl_motor = new MeshSceneNode(this, motor, vector3df(-70.71, -70.71, -17.5),
[15]134                                vector3df(90, 0, 0), texture);
[158]135  MeshSceneNode *brr_motor = new MeshSceneNode(this, motor, vector3df(-70.71, 70.71, -17.5),
[15]136                                vector3df(90, 0, 0), texture);
[8]137
[15]138  tfl_blade = new Blade(this, vector3df(70.71, -70.71, 17.5));
[339]139  tfr_blade = new Blade(this, vector3df(70.71, 70.71, 17.5), vector3df(0, 0, 0), true);
140  trl_blade = new Blade(this, vector3df(-70.71, -70.71, 17.5), vector3df(0, 0, 0), true);
[15]141  trr_blade = new Blade(this, vector3df(-70.71, 70.71, 17.5));
[8]142
[15]143  bfl_blade = new Blade(this, vector3df(70.71, -70.71, -17.5));
[339]144  bfr_blade = new Blade(this, vector3df(70.71, 70.71, -17.5), vector3df(0, 0, 0), true);
145  brl_blade = new Blade(this, vector3df(-70.71, -70.71, -17.5),  vector3df(0, 0, 0),true);
[15]146  brr_blade = new Blade(this, vector3df(-70.71, 70.71, -17.5));
[8]147
[15]148  motor_speed_mutex = new Mutex(this);
149  for (int i = 0; i < 8; i++)
150    motor_speed[i] = 0;
151  ExtraDraw();
152#endif
[8]153}
154
[15]155X8::~X8() {
156  // les objets irrlicht seront automatiquement detruits (moteurs, helices,
157  // pales) par parenté
[8]158}
159
160#ifdef GL
[15]161void X8::AnimateModel(void) {
162  motor_speed_mutex->GetMutex();
[339]163  tfl_blade->SetRotationSpeed(K_MOT * vector3df(0, 0,motor_speed[0]));
164  tfr_blade->SetRotationSpeed(-K_MOT * vector3df(0, 0,motor_speed[1]));
165  trl_blade->SetRotationSpeed(-K_MOT * vector3df(0, 0,motor_speed[2]));
166  trr_blade->SetRotationSpeed(K_MOT * vector3df(0, 0,motor_speed[3]));
[8]167
[339]168  bfl_blade->SetRotationSpeed(-K_MOT * vector3df(0, 0,motor_speed[4]));
169  bfr_blade->SetRotationSpeed(K_MOT * vector3df(0, 0,motor_speed[5]));
170  brl_blade->SetRotationSpeed(K_MOT * vector3df(0, 0,motor_speed[6]));
171  brr_blade->SetRotationSpeed(-K_MOT * vector3df(0, 0,motor_speed[7]));
[15]172  motor_speed_mutex->ReleaseMutex();
[8]173
[15]174  // adapt UAV size
175  if (arm_length->ValueChanged() == true) {
176    setScale(arm_length->Value());
177  }
[8]178}
179
[15]180size_t X8::dbtSize(void) const {
181  return 6 * sizeof(float) + 4 * sizeof(float); // 6ddl+4helices
[8]182}
183
[15]184void X8::WritedbtBuf(
185    char *dbtbuf) { /*
186                       float *buf=(float*)dbtbuf;
187                       vector3df vect=getPosition();
188                       memcpy(buf,&vect.X,sizeof(float));
189                       buf++;
190                       memcpy(buf,&vect.Y,sizeof(float));
191                       buf++;
192                       memcpy(buf,&vect.Z,sizeof(float));
193                       buf++;
194                       vect=getRotation();
195                       memcpy(buf,&vect.X,sizeof(float));
196                       buf++;
197                       memcpy(buf,&vect.Y,sizeof(float));
198                       buf++;
199                       memcpy(buf,&vect.Z,sizeof(float));
200                       buf++;
201                       memcpy(buf,&motors,sizeof(rtsimu_motors));*/
[8]202}
203
[15]204void X8::ReaddbtBuf(
205    char *dbtbuf) { /*
206                       float *buf=(float*)dbtbuf;
207                       vector3df vect;
208                       memcpy(&vect.X,buf,sizeof(float));
209                       buf++;
210                       memcpy(&vect.Y,buf,sizeof(float));
211                       buf++;
212                       memcpy(&vect.Z,buf,sizeof(float));
213                       buf++;
214                       setPosition(vect);
215                       memcpy(&vect.X,buf,sizeof(float));
216                       buf++;
217                       memcpy(&vect.Y,buf,sizeof(float));
218                       buf++;
219                       memcpy(&vect.Z,buf,sizeof(float));
220                       buf++;
221                       ((ISceneNode*)(this))->setRotation(vect);
222                       memcpy(&motors,buf,sizeof(rtsimu_motors));
223                       AnimateModele();*/
[8]224}
[15]225#endif // GL
[8]226
[15]227// states are computed on fixed frame NED
228// x north
229// y east
230// z down
231void X8::CalcModel(void) {
232  float tfl_speed, tfr_speed, trl_speed, trr_speed;
233  float bfl_speed, bfr_speed, brl_speed, brr_speed;
234  float u_roll, u_pitch, u_yaw, u_thrust;
235  float omega;
[214]236  Time motorTime;
[8]237#ifdef GL
[15]238  motor_speed_mutex->GetMutex();
239#endif // GL
[214]240  motors->GetSpeeds(motor_speed,&motorTime);
241  if((GetTime()-motorTime)/1000000>motorTimeout->Value()) {
242    for(int i=0;i<8;i++) {
243      if(motor_speed[i]!=0) {
244         //Printf("timout\n");
245        for(int i=0;i<8;i++) motor_speed[i]=0;
246        break;
247      }
248    }
249  }
[8]250#ifdef GL
[15]251  motor_speed_mutex->ReleaseMutex();
252#endif // GL
253  tfl_speed = motor_speed[0];
254  tfr_speed = motor_speed[1];
255  trl_speed = motor_speed[2];
256  trr_speed = motor_speed[3];
257  bfl_speed = motor_speed[4];
258  bfr_speed = motor_speed[5];
259  brl_speed = motor_speed[6];
260  brr_speed = motor_speed[7];
[8]261
[15]262  omega = tfl_speed + brl_speed + trr_speed + bfr_speed - bfl_speed -
263          trl_speed - brr_speed - tfr_speed;
[8]264
[15]265  /*
266      ** ===================================================================
267      **    u roll: roll torque
268      **
269      ** ===================================================================
270      */
[8]271
[15]272  u_roll = arm_length->Value() * k_mot->Value() *
273           (sigma->Value() * tfl_speed * tfl_speed + bfl_speed * bfl_speed +
274            sigma->Value() * trl_speed * trl_speed + brl_speed * brl_speed -
275            sigma->Value() * tfr_speed * tfr_speed - bfr_speed * bfr_speed -
276            sigma->Value() * trr_speed * trr_speed - brr_speed * brr_speed) *
277           sqrtf(2) / 2;
[8]278
[15]279  /// Classical Nonlinear model of a quadrotor ( This is the w_x angular speed
280  /// of the quadri in the body frame). It is a discrete integrator
281  // state[0].W.x=(dT()/j_roll->Value())*((j_yaw->Value()-j_pitch->Value())*state[-1].W.y*state[-1].W.z-j_r->Value()*state[-1].W.y*omega
282  // + u_roll) +state[-1].W.x;//Osamah
283  state[0].W.x =
284      (dT() / j_roll->Value()) *
285          ((j_pitch->Value() - j_yaw->Value()) * state[-1].W.y * state[-1].W.z -
286           j_r->Value() * state[-1].W.y * omega + u_roll) +
287      state[-1].W.x; // Majd
[8]288
[15]289  // state[0].W.x=(dT()/j_roll->Value())*(u_roll-m->Value()*G*l_cg->Value()*sinf(state[-2].W.x)-f_air_vert->Value()*arm_length->Value()*arm_length->Value()*state[-1].W.x)+state[-1].W.x;
[8]290
[15]291  /*
292  ** ===================================================================
293  **   u pitch : pitch torque
294  **
295  ** ===================================================================
296  */
297  u_pitch = arm_length->Value() * k_mot->Value() *
298            (sigma->Value() * tfl_speed * tfl_speed + bfl_speed * bfl_speed +
299             sigma->Value() * tfr_speed * tfr_speed + bfr_speed * bfr_speed -
300             sigma->Value() * trl_speed * trl_speed - brl_speed * brl_speed -
301             sigma->Value() * trr_speed * trr_speed - brr_speed * brr_speed) *
302            sqrtf(2) / 2;
[8]303
[15]304  /// Classical Nonlinear model of a quadrotor ( This is the w_y angular speed
305  /// of the quadri in the body frame). It is a discrete integrator
306  // state[0].W.y=(dT()/j_pitch->Value())*((j_roll->Value()-j_yaw->Value())*state[-1].W.x*state[-1].W.z-j_r->Value()*state[-1].W.x*omega
307  // + u_pitch)+state[-1].W.y;//Osamah
308  state[0].W.y =
309      (dT() / j_pitch->Value()) *
310          ((j_yaw->Value() - j_roll->Value()) * state[-1].W.x * state[-1].W.z -
311           j_r->Value() * state[-1].W.x * omega + u_pitch) +
312      state[-1].W.y; // Majd
[8]313
[15]314  // state[0].W.y=(dT()/j_pitch->Value())*(u_pitch-m->Value()*G*l_cg->Value()*sinf(state[-2].W.y)-f_air_vert->Value()*arm_length->Value()*arm_length->Value()*state[-1].W.y)+state[-1].W.y;
[8]315
[15]316  /*
317  ** ===================================================================
318  **    u yaw : yaw torque
319  **
320  ** ===================================================================
321  */
322  u_yaw = c_mot->Value() * (tfl_speed * tfl_speed - bfl_speed * bfl_speed +
323                            trr_speed * trr_speed - brr_speed * brr_speed -
324                            tfr_speed * tfr_speed + bfr_speed * bfr_speed -
325                            trl_speed * trl_speed + brl_speed * brl_speed);
[8]326
[15]327  /// Classical Nonlinear model of a quadrotor ( This is the w_z angular speed
328  /// of the quadri in the body frame). It is a discrete integrator
329  // state[0].W.z=(dT()/j_yaw->Value())* u_yaw +state[-1].W.z;//Osamah
330  state[0].W.z =
331      (dT() / j_yaw->Value()) * ((j_roll->Value() - j_pitch->Value()) *
332                                     state[-1].W.x * state[-1].W.y +
333                                 u_yaw) +
334      state[-1].W.z; // Majd
[8]335
[15]336  // state[0].W.z=(dT()/j_yaw->Value())*(u_yaw-f_air_lat->Value()*state[-1].W.z)+state[-1].W.z;
[8]337
[15]338  // compute quaternion from W
339  // Quaternion derivative: dQ = 0.5*(Q*Qw)
340  Quaternion dQ = state[-1].Quat.GetDerivative(state[0].W);
[8]341
[15]342  // Quaternion integration
343  state[0].Quat = state[-1].Quat + dQ * dT();
344  state[0].Quat.Normalize();
[8]345
[15]346  // Calculation of the thrust from the reference speed of motors
347  u_thrust =
348      k_mot->Value() * S->Value() *
349      (sigma->Value() * tfl_speed * tfl_speed +
350       sigma->Value() * tfr_speed * tfr_speed +
351       sigma->Value() * trl_speed * trl_speed +
352       sigma->Value() * trr_speed * trr_speed + bfl_speed * bfl_speed +
353       bfr_speed * bfr_speed + brl_speed * brl_speed + brr_speed * brr_speed);
[167]354  Vector3D<double> vect(0, 0, -u_thrust);
[15]355  vect.Rotate(state[0].Quat);
[8]356
[15]357  /*
358      ** ===================================================================
359      **     x double integrator
360      **
361      ** ===================================================================
362      */
363  state[0].Pos.x =
364      (dT() * dT() / m->Value()) *
365          (vect.x -
366           f_air_lat->Value() * (state[-1].Pos.x - state[-2].Pos.x) / dT()) +
367      2 * state[-1].Pos.x - state[-2].Pos.x;
368  state[0].Vel.x = (state[0].Pos.x - state[-1].Pos.x) / dT();
[8]369
[15]370  /*
371      ** ===================================================================
372      **     y double integrator
373      **
374      ** ===================================================================
375      */
376  state[0].Pos.y =
377      (dT() * dT() / m->Value()) *
378          (vect.y -
379           f_air_lat->Value() * (state[-1].Pos.y - state[-2].Pos.y) / dT()) +
380      2 * state[-1].Pos.y - state[-2].Pos.y;
381  state[0].Vel.y = (state[0].Pos.y - state[-1].Pos.y) / dT();
[8]382
[15]383  /*
384  ** ===================================================================
385  **     z double integrator
386  **
387  ** ===================================================================
388  */
389  state[0].Pos.z =
390      (dT() * dT() / m->Value()) *
391          (vect.z +
392           f_air_vert->Value() * (state[-1].Pos.z - state[-2].Pos.z) / dT() +
393           m->Value() * G) +
394      2 * state[-1].Pos.z - state[-2].Pos.z;
395  state[0].Vel.z = (state[0].Pos.z - state[-1].Pos.z) / dT();
[8]396
397#ifndef GL
[15]398  if (state[0].Pos.z < 0)
399    state[0].Pos.z = 0;
[8]400#endif
401}
402
403} // end namespace simulator
404} // end namespace flair
Note: See TracBrowser for help on using the repository browser.