]> git.mxchange.org Git - flightgear.git/blob - src/FDM/YASim/Hook.cpp
Fix stall widths for the "auxilliary" (reverse flow) stalls so they
[flightgear.git] / src / FDM / YASim / Hook.cpp
1 #include "Math.hpp"
2 #include "BodyEnvironment.hpp"
3 #include "Ground.hpp"
4 #include "RigidBody.hpp"
5
6 #include "Hook.hpp"
7 namespace yasim {
8
9 static const float YASIM_PI2 = 3.14159265358979323846/2;
10
11 Hook::Hook()
12 {
13     int i;
14     for(i=0; i<3; i++)
15         _pos[i] = _force[i] = 0;
16     for(i=0; i<2; i++)
17         _global_ground[i] = 0;
18     _global_ground[2] = 1;
19     _global_ground[3] = -1e5;
20     _length = 0.0;
21     _down_ang = 0.0;
22     _up_ang = 0.0;
23     _extension = 0.0;
24     _frac = 0.0;
25     _has_wire = false;
26 }
27
28 void Hook::setPosition(float* position)
29 {
30     int i;
31     for(i=0; i<3; i++) _pos[i] = position[i];
32 }
33
34 void Hook::setLength(float length)
35 {
36     _length = length;
37 }
38
39 void Hook::setDownAngle(float ang)
40 {
41     _down_ang = ang;
42 }
43
44 void Hook::setUpAngle(float ang)
45 {
46     _up_ang = ang;
47 }
48
49 void Hook::setExtension(float extension)
50 {
51     _extension = extension;
52 }
53
54 void Hook::setGlobalGround(double *global_ground)
55 {
56     int i;
57     for(i=0; i<4; i++) _global_ground[i] = global_ground[i];
58 }
59
60 void Hook::getPosition(float* out)
61 {
62     int i;
63     for(i=0; i<3; i++) out[i] = _pos[i];
64 }
65
66 float Hook::getLength(void)
67 {
68     return _length;
69 }
70
71 float Hook::getDownAngle(void)
72 {
73     return _down_ang;
74 }
75
76 float Hook::getUpAngle(void)
77 {
78     return _up_ang;
79 }
80
81 float Hook::getExtension(void)
82 {
83     return _extension;
84 }
85
86 void Hook::getForce(float* force, float* off)
87 {
88     Math::set3(_force, force);
89     Math::set3(_pos, off);
90 }
91
92 float Hook::getCompressFraction()
93 {
94     return _frac;
95 }
96
97 void Hook::getTipPosition(float* out)
98 {
99     // The hook tip in local coordinates.
100     float ang = _frac*(_down_ang - _up_ang) + _up_ang;
101     float pos_tip[3] = { _length*Math::cos(ang), 0.0, _length*Math::sin(ang) };
102     Math::sub3(_pos, pos_tip, out);
103 }
104
105 void Hook::getTipGlobalPosition(State* s, double* out)
106 {
107     // The hook tip in local coordinates.
108     float pos_tip[3];
109     getTipPosition(pos_tip);
110     // The hook tip in global coordinates.
111     s->posLocalToGlobal(pos_tip, out);
112 }
113
114 void Hook::calcForce(Ground* g_cb, RigidBody* body, State* s, float* lv, float* lrot)
115 {
116     // Init the return values
117     int i;
118     for(i=0; i<3; i++) _force[i] = 0;
119
120     // Don't bother if it's fully retracted
121     if(_extension <= 0)
122         return;
123
124     // For the first guess, the position fraction is equal to the
125     // extension value.
126     _frac = _extension;
127
128     // The ground plane transformed to the local frame.
129     float ground[4];
130     s->planeGlobalToLocal(_global_ground, ground);
131
132     // The hook tip in local coordinates.
133     float ltip[3];
134     getTipPosition(ltip);
135
136
137     // Correct the extension value for no intersection.
138     
139     // Check if the tip will intersect the ground or not. That is, compute
140     // the distance of the tip to the ground plane.
141     float tipdist = ground[3] - Math::dot3(ltip, ground);
142     if(0 <= tipdist) {
143         _frac = _extension;
144     } else {
145         // Compute the distance of the hooks mount point from the ground plane.
146         float mountdist = ground[3] - Math::dot3(_pos, ground);
147
148         // Compute the distance of the hooks mount point from the ground plane
149         // in the x-z plane. It holds:
150         //  mountdist = mountdist_xz*cos(angle(normal_yz, e_z))
151         // thus
152         float mountdist_xz = _length;
153         if (ground[2] != 0) {
154             float nrm_yz = Math::sqrt(ground[1]*ground[1]+ground[2]*ground[2]);
155             mountdist_xz = -mountdist*nrm_yz/ground[2];
156         }
157
158         if (mountdist_xz < _length) {
159             float ang = Math::asin(mountdist_xz/_length)
160               + Math::atan2(ground[2], ground[0]) + YASIM_PI2;
161             _frac = (ang - _up_ang)/(_down_ang - _up_ang);
162         } else {
163             _frac = _extension;
164         }
165     }
166
167     double hook_area[4][3];
168     // The hook mount in global coordinates.
169     s->posLocalToGlobal(_pos, hook_area[1]);
170
171     // Recompute the hook tip in global coordinates.
172     getTipGlobalPosition(s, hook_area[0]);
173
174     // The old positions.
175     hook_area[2][0] = _old_mount[0];
176     hook_area[2][1] = _old_mount[1];
177     hook_area[2][2] = _old_mount[2];
178     hook_area[3][0] = _old_tip[0];
179     hook_area[3][1] = _old_tip[1];
180     hook_area[3][2] = _old_tip[2];
181
182
183     // Check if we caught a wire.
184     // Returns true if we caught one.
185     if (!_has_wire && g_cb->caughtWire(hook_area))
186         _has_wire = true;
187
188
189     // save actual position as old position ...
190     _old_mount[0] = hook_area[1][0];
191     _old_mount[1] = hook_area[1][1];
192     _old_mount[2] = hook_area[1][2];
193     _old_tip[0] = hook_area[0][0];
194     _old_tip[1] = hook_area[0][1];
195     _old_tip[2] = hook_area[0][2];
196
197     if (!_has_wire)
198         return;
199
200     // Get the wire endpoints and their velocities wrt the earth.
201     double dpos[2][3];
202     float wire_vel[2][3];
203     g_cb->getWire(dpos, wire_vel);
204
205     // Transform those to the local coordinate system
206     float wire_lpos[2][3];
207     s->posGlobalToLocal(dpos[0], wire_lpos[0]);
208     s->posGlobalToLocal(dpos[1], wire_lpos[1]);
209     s->velGlobalToLocal(wire_vel[0], wire_vel[0]);
210     s->velGlobalToLocal(wire_vel[1], wire_vel[1]);
211
212     // Compute the velocity of the hooks mount point in the local frame.
213     float mount_vel[3];
214     body->pointVelocity(_pos, lrot, mount_vel);
215     Math::add3(lv, mount_vel, mount_vel);
216
217     // The velocity of the hook mount point wrt the earth in
218     // the local frame.
219     float v_wrt_we[2][3];
220     Math::sub3(mount_vel, wire_vel[0], v_wrt_we[0]);
221     Math::sub3(mount_vel, wire_vel[1], v_wrt_we[1]);
222
223     float f[2][3];
224     // The vector from the wire ends to the hook mount point.
225     Math::sub3(_pos, wire_lpos[0], f[0]);
226     Math::sub3(_pos, wire_lpos[1], f[1]);
227
228     // We only need the direction.
229     float mf0 = Math::mag3(f[0]);
230     float mf1 = Math::mag3(f[1]);
231     Math::mul3(1.0/mf0, f[0], f[0]);
232     Math::mul3(1.0/mf1, f[1], f[1]);
233
234     // The velocity of the wire wrt the wire ends at the wire
235     // mount points.
236     float v0 = Math::dot3(v_wrt_we[0], f[0]);
237     float v1 = Math::dot3(v_wrt_we[1], f[1]);
238
239     // We assume that the wire slips through the hook. So the velocity
240     // will be equal at both sides. So take the mean of both.
241     float v = 0.5*(v0+v1);
242
243     // Release wire when we reach zero velocity.
244     if (v <= 0.0) {
245       _has_wire = false;
246       g_cb->releaseWire();
247       return;
248     }
249
250     // The trick is to multiply with the current mass of the aircraft.
251     // That way we control the acceleration and not the force. This is
252     // the implicit calibration of the wires for aircrafts of
253     // different mass.
254     float mass = body->getTotalMass();
255   
256     // The local force is the vector sum of the force on each wire.
257     // The force is computed with some constant tension on the wires
258     // (80000N) plus a velocity dependent component.
259     Math::add3(f[0], f[1], _force);
260     Math::mul3(-mass*( 1.0 + ((mf0+mf1)/70) + 0.2*v ), _force, _force);
261   
262     // Now in the body coordinate system, eliminate the Y coord part
263     // of the hook force. Physically this means that the wire will just
264     // slip through the hook instead of applying a side force.
265     _force[1] = 0.0;
266 }
267
268 }; // namespace yasim
269