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