2 #include "BodyEnvironment.hpp"
4 #include "RigidBody.hpp"
9 static const float YASIM_PI2 = 3.14159265358979323846/2;
15 _pos[i] = _force[i] = 0;
17 _global_ground[i] = 0;
18 _global_ground[2] = 1;
19 _global_ground[3] = -1e5;
28 void Hook::setPosition(float* position)
31 for(i=0; i<3; i++) _pos[i] = position[i];
34 void Hook::setLength(float length)
39 void Hook::setDownAngle(float ang)
44 void Hook::setUpAngle(float ang)
49 void Hook::setExtension(float extension)
51 _extension = extension;
54 void Hook::setGlobalGround(double *global_ground)
57 for(i=0; i<4; i++) _global_ground[i] = global_ground[i];
60 void Hook::getPosition(float* out)
63 for(i=0; i<3; i++) out[i] = _pos[i];
66 float Hook::getLength(void)
71 float Hook::getDownAngle(void)
76 float Hook::getUpAngle(void)
81 float Hook::getExtension(void)
86 void Hook::getForce(float* force, float* off)
88 Math::set3(_force, force);
89 Math::set3(_pos, off);
92 float Hook::getCompressFraction()
97 void Hook::getTipPosition(float* out)
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);
105 void Hook::getTipGlobalPosition(State* s, double* out)
107 // The hook tip in local coordinates.
109 getTipPosition(pos_tip);
110 // The hook tip in global coordinates.
111 s->posLocalToGlobal(pos_tip, out);
114 void Hook::calcForce(Ground* g_cb, RigidBody* body, State* s, float* lv, float* lrot)
116 // Init the return values
118 for(i=0; i<3; i++) _force[i] = 0;
120 // Don't bother if it's fully retracted
124 // For the first guess, the position fraction is equal to the
128 // The ground plane transformed to the local frame.
130 s->planeGlobalToLocal(_global_ground, ground);
132 // The hook tip in local coordinates.
134 getTipPosition(ltip);
137 // Correct the extension value for no intersection.
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);
145 // Compute the distance of the hooks mount point from the ground plane.
146 float mountdist = ground[3] - Math::dot3(_pos, ground);
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))
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];
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);
167 double hook_area[4][3];
168 // The hook mount in global coordinates.
169 s->posLocalToGlobal(_pos, hook_area[1]);
171 // Recompute the hook tip in global coordinates.
172 getTipGlobalPosition(s, hook_area[0]);
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];
183 // Check if we caught a wire.
184 // Returns true if we caught one.
185 if (!_has_wire && g_cb->caughtWire(hook_area))
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];
200 // Get the wire endpoints and their velocities wrt the earth.
202 float wire_vel[2][3];
203 g_cb->getWire(dpos, wire_vel);
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]);
212 // Compute the velocity of the hooks mount point in the local frame.
214 body->pointVelocity(_pos, lrot, mount_vel);
215 Math::add3(lv, mount_vel, mount_vel);
217 // The velocity of the hook mount point wrt the earth in
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]);
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]);
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]);
234 // The velocity of the wire wrt the wire ends at the wire
236 float v0 = Math::dot3(v_wrt_we[0], f[0]);
237 float v1 = Math::dot3(v_wrt_we[1], f[1]);
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);
243 // Release wire when we reach zero velocity.
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
254 float mass = body->getTotalMass();
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);
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.
268 }; // namespace yasim