]> git.mxchange.org Git - flightgear.git/blob - src/FDM/YASim/Launchbar.cpp
Port over remaining Point3D usage to the more type and unit safe SG* classes.
[flightgear.git] / src / FDM / YASim / Launchbar.cpp
1 #include "Math.hpp"
2 #include "BodyEnvironment.hpp"
3 #include "Ground.hpp"
4 #include "RigidBody.hpp"
5
6 #include "Launchbar.hpp"
7
8 namespace yasim {
9
10   static const float YASIM_PI2 = 3.14159265358979323846f/2;
11   static const float YASIM_PI = 3.14159265358979323846f;
12   static const float RAD2DEG = 180/YASIM_PI;
13
14 Launchbar::Launchbar()
15 {
16     int i;
17     for(i=0; i<3; i++)
18       _launchbar_mount[i] = _holdback_mount[i] = _launchbar_force[i]
19               = _holdback_force[i] = 0;
20     for(i=0; i<2; i++)
21         _global_ground[i] = 0;
22     _global_ground[2] = 1;
23     _global_ground[3] = -1e5;
24     _length = 0.0;
25     _holdback_length = 2.0;
26     _down_ang = 0.0;
27     _up_ang = 0.0;
28     _ang = 0.0;
29     _extension = 0.0;
30     _frac = _h_frac =0.0;
31     _launch_cmd = false;
32     _pos_on_cat = 0.0;
33     _state = Unmounted;
34     _strop = false;
35 }
36
37 void Launchbar::setLaunchbarMount(float* position)
38 {
39     int i;
40     for(i=0; i<3; i++) _launchbar_mount[i] = position[i];
41 }
42
43 void Launchbar::setHoldbackMount(float* position)
44 {
45     int i;
46     for(i=0; i<3; i++) _holdback_mount[i] = position[i];
47 }
48
49 void Launchbar::setLength(float length)
50 {
51     _length = length;
52 }
53
54   void Launchbar::setHoldbackLength(float length)
55   {
56     _holdback_length = length;
57   }
58
59 void Launchbar::setDownAngle(float ang)
60 {
61     _down_ang = ang;
62 }
63
64 void Launchbar::setUpAngle(float ang)
65 {
66     _up_ang = ang;
67 }
68
69 void Launchbar::setExtension(float extension)
70 {
71     _extension = extension;
72 }
73
74 void Launchbar::setLaunchCmd(bool cmd)
75 {
76     _launch_cmd = cmd;
77 }
78
79 void Launchbar::setGlobalGround(double *global_ground)
80 {
81     int i;
82     for(i=0; i<4; i++) _global_ground[i] = global_ground[i];
83 }
84
85 void Launchbar::getLaunchbarMount(float* out)
86 {
87     int i;
88     for(i=0; i<3; i++) out[i] = _launchbar_mount[i];
89 }
90
91   float Launchbar::getLaunchbarPos(int i)
92   {
93     return _launchbar_mount[i];
94   }
95
96 void Launchbar::getHoldbackMount(float* out)
97 {
98     int i;
99     for(i=0; i<3; i++) out[i] = _holdback_mount[i];
100 }
101
102   float Launchbar::getHoldbackPos(int j)
103   {
104     return _holdback_mount[j];
105   }
106
107   float Launchbar::getHoldbackLength(void)
108   {
109     return _holdback_length;
110   }
111
112 float Launchbar::getLength(void)
113 {
114     return _length;
115 }
116
117 float Launchbar::getDownAngle(void)
118 {
119     return _down_ang;
120 }
121
122 float Launchbar::getUpAngle(void)
123 {
124     return _up_ang;
125 }
126
127   float Launchbar::getAngle(void)
128   {
129     return _ang;
130   }
131
132   float Launchbar::getHoldbackAngle(void)
133   {
134     return _h_ang;
135   }
136 float Launchbar::getExtension(void)
137 {
138     return _extension;
139 }
140
141   void Launchbar::getForce(float* force1, float* off1,
142     float* force2, float* off2)
143   {
144     Math::set3(_launchbar_force, force1);
145     Math::set3(_launchbar_mount, off1);
146     Math::set3(_holdback_force, force2);
147     Math::set3(_holdback_mount, off2);
148   }
149
150   const char* Launchbar::getState(void)
151   {
152     switch (_state) {
153     case Arrested:
154       return "Engaged";
155     case Launch:
156       return "Launching";
157     case Completed:
158       return "Completed";
159     default:
160       return "Disengaged"; 
161     }
162   }   
163
164   bool Launchbar::getStrop(void)
165 {
166     return _strop;
167 }
168
169 float Launchbar::getCompressFraction()
170 {
171     return _frac;
172 }
173
174   float Launchbar::getHoldbackCompressFraction()
175   {
176     return _h_frac;
177   }
178
179 void Launchbar::getTipPosition(float* out)
180 {
181     // The launchbar tip in local coordinates.
182
183     _ang = _frac*(_down_ang - _up_ang ) + _up_ang ;
184     float ptip[3] = { _length*Math::cos(_ang), 0, -_length*Math::sin(_ang) };
185     Math::add3(_launchbar_mount, ptip, out);
186   }
187
188   float Launchbar::getTipPos(int i)
189   {
190     float pos_tip[3];
191     getTipPosition(pos_tip);
192     return pos_tip[i];
193   }    
194
195   void Launchbar::getHoldbackTipPosition(float* out)
196   {
197     // The holdback tip in local coordinates.
198     _h_ang = _h_frac*(_down_ang - _up_ang) + _up_ang;
199     float htip[3] = { -_length*Math::cos(_h_ang), 0, -_length*Math::sin(_h_ang) };
200     Math::add3(_holdback_mount, htip, out);
201   }
202
203   float Launchbar::getHoldbackTipPos(int i)
204   {
205     float pos_tip[3];
206     getHoldbackTipPosition(pos_tip);
207     return pos_tip[i];
208 }
209
210
211 void Launchbar::getTipGlobalPosition(State* s, double* out)
212 {
213     // The launchbar tip in local coordinates.
214     float pos_tip[3];
215     getTipPosition(pos_tip);
216     // The launchbar tip in global coordinates.
217     s->posLocalToGlobal(pos_tip, out);
218 }
219
220 float Launchbar::getPercentPosOnCat(float* lpos, float off, float lends[2][3])
221 {
222     // Compute the forward direction of the cat.
223     float lforward[3];
224     Math::sub3(lends[1], lends[0], lforward);
225     float ltopos[3];
226     Math::sub3(lpos, lends[0], ltopos);
227     float fwlen = Math::mag3(lforward);
228     
229     return (Math::dot3(ltopos, lforward)/fwlen + off)/fwlen;
230 }
231
232 void Launchbar::getPosOnCat(float perc, float* lpos, float* lvel,
233                             float lends[2][3], float lendvels[2][3])
234 {
235     if (perc < 0.0)
236         perc = 0.0;
237     if (1.0 < perc)
238         perc = 1.0;
239
240     // Compute the forward direction of the cat.
241     float lforward[3];
242     Math::sub3(lends[1], lends[0], lforward);
243     Math::mul3(perc, lforward, lpos);
244     Math::add3(lends[0], lpos, lpos);
245     
246     float tmp[3];
247     Math::mul3(perc, lendvels[0], lvel);
248     Math::mul3(1.0f-perc, lendvels[1], tmp);
249     Math::add3(tmp, lvel, lvel);
250 }
251
252 void Launchbar::calcForce(Ground *g_cb, RigidBody* body, State* s, float* lv, float* lrot)
253 {
254     // Init the return values
255     int i;
256     for(i=0; i<3; i++) _launchbar_force[i] = 0;
257     for(i=0; i<3; i++) _holdback_force[i] = 0;
258
259     if (_state != Unmounted)
260       _extension = 1;
261
262     // Don't bother if it's fully retracted
263     if(_extension <= 0)
264         return;
265
266     // For the first guess, the position fraction is equal to the
267     // extension value.
268     _frac = _h_frac = _extension;
269
270     // The ground plane transformed to the local frame.
271     float ground[4];
272     s->planeGlobalToLocal(_global_ground, ground);
273
274     // The launchbar tip in local coordinates.
275     float ltip[3];
276     getTipPosition(ltip);
277
278         // Correct the extension value for no intersection.
279
280     // Check if the tip will intersect the ground or not. That is, compute
281     // the distance of the tip to the ground plane.
282     float tipdist = ground[3] - Math::dot3(ltip, ground);
283     if(0 <= tipdist) {
284       _frac = _extension;
285     } else {
286       // Compute the distance of the launchbar mount point from the
287       // ground plane.
288       float mountdist = ground[3] - Math::dot3(_launchbar_mount, ground);
289
290       // Compute the distance of the launchbar mount point from the
291       // ground plane in the x-z plane. It holds:
292       // mountdist = mountdist_xz*cos(angle(normal_yz, e_z))
293       // thus
294       float mountdist_xz = _length;
295       if (ground[2] != 0) {
296         float nrm_yz = Math::sqrt(ground[1]*ground[1]+ground[2]*ground[2]);
297         mountdist_xz = -mountdist*nrm_yz/ground[2];
298       }
299
300       if (mountdist_xz < _length) { 
301         // the launchbar points forward, so we need to change the signs here
302         float ang = -Math::asin(mountdist_xz/_length)
303           + Math::atan2(ground[2], ground[0]) + YASIM_PI2;
304         ang = -ang;
305             _frac = (ang - _up_ang)/(_down_ang - _up_ang);
306       } else {
307             _frac = _extension;
308     }
309     }
310
311     // Now do it again for the holdback
312
313     // The holdback tip in local coordinates.
314     float htip[3];
315     getHoldbackTipPosition(htip);
316
317     // Check if the tip will intersect the ground or not. That is, compute
318     // the distance of the tip to the ground plane.
319     float h_tipdist = ground[3] - Math::dot3(htip, ground);
320     if (0 <= h_tipdist) {
321       _h_frac = _extension;
322     } else {
323       // Compute the distance of the holdback mount point from the ground
324       // plane.
325       float h_mountdist = ground[3] - Math::dot3(_holdback_mount, ground);
326
327       // Compute the distance of the holdback mount point from the ground
328       // plane in the x-z plane. It holds:
329       //  mountdist = mountdist_xz*cos(angle(normal_yz, e_z))
330       // thus
331       float h_mountdist_xz = _holdback_length;
332       if (ground[2] != 0) {
333         float nrm_yz = Math::sqrt(ground[1]*ground[1]+ground[2]*ground[2]);
334         h_mountdist_xz = -h_mountdist*nrm_yz/ground[2];
335       }
336
337       if (h_mountdist_xz < _holdback_length) {
338         float h_ang = Math::asin(h_mountdist_xz/_holdback_length)
339           + Math::atan2(ground[2], ground[0]) + YASIM_PI2;
340         _h_frac = (h_ang - _up_ang)/(_down_ang - _up_ang);
341       } else {
342         _h_frac = _extension;
343       }
344     }
345
346     float llb_mount[3];
347     getTipPosition(llb_mount);
348
349     // The launchbar tip in global coordinates.
350     double launchbar_pos[3];
351     s->posLocalToGlobal(llb_mount, launchbar_pos);
352
353     double end[2][3]; float vel[2][3];
354     float dist = g_cb->getCatapult(launchbar_pos, end, vel);
355     // Work around a problem of flightgear returning totally screwed up
356     // scenery when switching views.
357     if (1e3 < dist)
358         return;
359
360     // Compute the positions of the catapult start and endpoints in the
361     // local coordinate system
362     float lend[2][3];
363     s->posGlobalToLocal(end[0], lend[0]);
364     s->posGlobalToLocal(end[1], lend[1]);
365     
366     // Transform the velocities of the endpoints to the
367     // local coordinate sytem.
368     float lvel[2][3];
369     s->velGlobalToLocal(vel[0], lvel[0]);
370     s->velGlobalToLocal(vel[1], lvel[1]);
371
372     // Compute the position of the launchbar tip relative to the cat.
373     float tip_pos_on_cat = getPercentPosOnCat(llb_mount, 0.0, lend);
374     float llbtip[3], lvlbtip[3];
375     getPosOnCat(tip_pos_on_cat, llbtip, lvlbtip, lend, lvel);
376
377     // Compute the direction from the launchbar mount at the gear
378     // to the lauchbar mount on the cat.
379     float llbdir[3];
380     Math::sub3(llbtip, _launchbar_mount, llbdir);
381     float lblen = Math::mag3(llbdir);
382     Math::mul3(1.0f/lblen, llbdir, llbdir);
383
384     // Check if we are near enough to the cat.
385     if (_state == Unmounted && dist < 0.6) {
386       // coarse approximation for the velocity of the launchbar.
387         // Might be sufficient because arresting at the cat makes only
388         // sense when the aircraft does not rotate much.
389         float lv_mount[3];
390         float tmp[3];
391         float lrot[3], lv[3];
392         Math::vmul33(s->orient, s->rot, lrot);
393         Math::vmul33(s->orient, s->v, lv);
394         body->pointVelocity(llb_mount, lrot, tmp);
395         Math::sub3(tmp, lvlbtip, lv_mount);
396         Math::add3(lv, lv_mount, lv_mount);
397
398         // We cannot arrest at the cat if we move too fast wrt the cat.
399         if (0.2 < Math::mag3(lv_mount))
400             return;
401
402         // Compute the position of the holdback mount relative to the cat.
403         double dd[2][3]; float fd[2][3]; double ghldbkpos[3];
404         s->posLocalToGlobal(_holdback_mount, ghldbkpos);
405         float hbdist = g_cb->getCatapult(ghldbkpos, dd, fd);
406
407       // don't let the calculation go -ve here
408       if (_holdback_length*_holdback_length - hbdist*hbdist < 0)
409         return;
410       float offset = -Math::sqrt(_holdback_length*_holdback_length
411         - hbdist*hbdist);
412       _pos_on_cat = getPercentPosOnCat(_holdback_mount, offset, lend);
413
414         // We cannot arrest if we are not at the start of the cat.
415       if (_pos_on_cat < 0.0 || 0.4 < _pos_on_cat)
416             return;
417
418         // Now we are arrested at the cat.
419         // The force is applied at the next step.
420         _state = Arrested;
421         return;
422     }
423
424     // Get the actual distance from the holdback to its mountpoint
425     // on the cat. If it is longer than the holdback apply a force.
426     float lhldbk_cmount[3]; float lvhldbk_cmount[3];
427     getPosOnCat(_pos_on_cat, lhldbk_cmount, lvhldbk_cmount, lend, lvel);
428     // Compute the direction of holdback.
429     float lhldbkdir[3];
430     Math::sub3(lhldbk_cmount, _holdback_mount, lhldbkdir);
431     float hldbklen = Math::mag3(lhldbkdir);
432     Math::mul3(1/hldbklen, lhldbkdir, lhldbkdir);
433     
434     if (_state == Arrested) {
435         // Now apply a constant tension from the catapult over the launchbar.
436       Math::mul3(2.0, llbdir, _launchbar_force);
437
438         // If the distance from the holdback mount at the aircraft to the
439         // holdback mount on the cat is larger than the holdback length itself,
440         // the holdback applies a force to the gear.
441         if (_holdback_length < hldbklen) {
442         // coarse approximation for the velocity of the holdback mount
443             // at the gear.
444             // Might be sufficient because arresting at the cat makes only
445             // sense when the aircraft does not rotate much.
446             float lvhldbk_gmount[3];
447             float lrot[3], lv[3];
448             Math::vmul33(s->orient, s->rot, lrot);
449             Math::vmul33(s->orient, s->v, lv);
450             body->pointVelocity(_holdback_mount, lrot, lvhldbk_gmount);
451             Math::add3(lv, lvhldbk_gmount, lvhldbk_gmount);
452
453             // The velocity of the holdback mount at the gear wrt the
454             // holdback mount at the cat.
455             float lvhldbk[3];
456             Math::sub3(lvhldbk_gmount, lvhldbk_cmount, lvhldbk);
457
458             // The spring force the holdback will apply to the gear
459             float tmp[3];
460         Math::mul3(10.f*(hldbklen - _holdback_length), lhldbkdir,
461           _holdback_force);
462
463             // The damping force here ...
464             Math::mul3(2e0, lvhldbk, tmp);
465         Math::sub3(_holdback_force, tmp, _holdback_force);
466         }
467
468       if (_launch_cmd) {
469             _state = Launch;
470         _strop = false;
471       }
472     }
473
474     if (_state == Launch) {
475         // Now apply a constant tension from the catapult over the launchbar.
476       Math::mul3(25.0, llbdir, _launchbar_force);
477
478       if (1.0 < dist) {
479         _state = Completed;
480       }
481     }
482
483     if (_state == Completed) {
484       // Wait until the strop has cleared the deck
485       // This is a temporary fix until we come up with something better
486
487       if (_frac > 0.8) {
488             _state = Unmounted;
489         _strop = true;
490       }
491     }
492
493     // Scale by the mass. That keeps the stiffness in reasonable bounds.
494     float mass = body->getTotalMass();
495     Math::mul3(mass, _launchbar_force, _launchbar_force);
496     Math::mul3(mass, _holdback_force, _holdback_force);
497 }
498
499 }; // namespace yasim
500