6#include <simgear/debug/logstream.hxx>
9#include "BodyEnvironment.hpp"
11#include "RigidBody.hpp"
14#include <simgear/bvh/BVHMaterial.hxx>
18static const float YASIM_PI = 3.14159265358979323846;
27 float magnitude = Math::mag3( v);
29 Math::mul3( 1 / magnitude, v, out);
37GearVector::GearVector(
float v0,
float v1,
float v2)
42void GearVector::set(
float v0,
float v1,
float v2)
54 _pos[
i] = _stuck[
i] = 0;
60 _fric_spring = 0.005f;
67 _ground_frictionFactor = 1;
68 _ground_rollingFriction = 0.02;
69 _ground_loadCapacity = 1e30;
70 _ground_loadResistance = 1e30;
72 _ground_bumpiness = 0;
77 _reduceFrictionByExtension = 0;
78 _spring_factor_not_planing = 1;
81 _ignoreWhileSolving = 0;
83 _stiction_abs =
false;
86 _global_ground[
i] = _global_vel[
i] = 0;
87 _global_ground[2] = 1;
88 _global_ground[3] = -1e3;
90 Math::zero3(_ground_trans);
91 Math::identity33(_ground_rot);
93 _wheelAxle.set(0, 1, 0);
98void Gear::setCompression(
float* compression)
100 _cmpr.set( compression[0], compression[1], compression[2]);
103void Gear::setWheelAxle(
float* wheel_axle)
105 _wheelAxle.set( wheel_axle[0], wheel_axle[1], wheel_axle[2]);
106 if (_wheelAxle.magnitude == 0) {
107 _wheelAxle.unit[1] = 1;
111void Gear::setGlobalGround(
double *global_ground,
float* global_vel,
112 double globalX,
double globalY,
113 const simgear::BVHMaterial *material,
unsigned int body)
116 double frictionFactor,rollingFriction,loadCapacity,loadResistance,bumpiness;
119 for(
i=0;
i<4;
i++) _global_ground[
i] = global_ground[
i];
120 for(
i=0;
i<3;
i++) _global_vel[
i] = global_vel[
i];
123 bool is_lake = (*material).solid_is_prop();
124 bool solid = (*material).get_solid();
125 if (is_lake && solid) {
126 frictionFactor = 0.3;
127 rollingFriction = 0.05;
130 frictionFactor = (*material).get_friction_factor();
131 rollingFriction = (*material).get_rolling_friction();
132 bumpiness = (*material).get_bumpiness();
135 loadCapacity = (*material).get_load_resistance();
136 loadResistance = (*material).get_load_resistance();
137 isSolid = (*material).get_solid();
140 loadCapacity = DBL_MAX;
141 frictionFactor = 1.0;
142 rollingFriction = 0.02;
143 loadResistance = DBL_MAX;
147 _ground_frictionFactor = frictionFactor;
148 _ground_rollingFriction = rollingFriction;
149 _ground_loadCapacity = loadCapacity;
150 _ground_loadResistance = loadResistance;
151 _ground_bumpiness = bumpiness;
152 _ground_isSolid = isSolid;
158void Gear::getGlobalGround(
double* global_ground)
160 for(
int i=0;
i<4;
i++) global_ground[
i] = _global_ground[
i];
163void Gear::getForce(
float* force,
float* contact)
165 Math::set3(_force, force);
166 Math::set3(_contact, contact);
170float Gear::getBumpAltitude()
172 if (_ground_bumpiness<0.001)
return 0.0;
173 double x = _global_x*0.1;
174 double y = _global_y*0.1;
184 float h = Math::sin(x)+Math::sin(7*x)+Math::sin(8*x)+Math::sin(13*x);
185 h += Math::sin(2*y)+Math::sin(5*y)+Math::sin(9*y*x)+Math::sin(17*y);
190void Gear::integrate(
float dt)
193 if (_rollSpeed > 0) {
196 _rollSpeed -= (13.0 * dt + 1300 * _brake * dt);
197 if (_rollSpeed < 0) _rollSpeed = 0;
204 const float (&ground)[4],
205 const GearVector& compression,
206 const float (&wheel_pos)[3],
207 const GearVector (&wheel_axle),
210 std::function<
float ()> bump_fn,
211 float (&o_contact)[3],
212 float& o_compression_distance_vertical,
213 float& o_compression_norm
273 float ground_unit[3];
278 Math::set3( wheel_pos, S);
284 Math::cross3( wheel_axle.unit, ground_unit,
R);
285 Math::cross3(
R, wheel_axle.unit,
R);
290 Math::mul3( wheel_radius,
R,
R);
293 Math::add3( S,
R, S);
297 float a = Math::dot3( ground, S) - ( ground[3] - tyre_radius);
298 float bump_altitude = 0;
300 bump_altitude = bump_fn();
317 o_compression_distance_vertical = a;
323 o_compression_norm = 0;
324 float compression_distance = 0;
325 float div = Math::dot3( compression.unit, ground_unit);
329 compression_distance = -a / div;
333 if ( compression.magnitude) {
334 o_compression_norm = compression_distance / compression.magnitude;
336 if (o_compression_norm > 1) {
337 o_compression_norm = 1;
343 Math::mul3( compression_distance, compression.unit, delta);
344 Math::add3( S, delta, o_contact);
352 double s = Math::dot3( o_contact, ground) - (ground[3] - tyre_radius + bump_altitude);
353 if (fabs( s) > 0.001)
355 SG_LOG(SG_GENERAL, SG_ALERT,
"<o_contact> is not tyre_radius above ground."
356 <<
" o_contact=" << o_contact
357 <<
" ground=" << ground
358 <<
" tyre_radius=" << tyre_radius
359 <<
" bump_altitude=" << bump_altitude
368 Math::mul3( tyre_radius, ground_unit, delta);
369 Math::add3( o_contact, delta, o_contact);
377 double s = Math::dot3( o_contact, ground) - (ground[3] + bump_altitude);
378 if ( fabs( s) > 0.001)
380 SG_LOG(SG_GENERAL, SG_ALERT,
"<o_contact> is not on ground."
381 <<
" o_contact=" << o_contact
382 <<
" ground=" << ground
383 <<
" tyre_radius=" << tyre_radius
384 <<
" bump_altitude=" << bump_altitude
394 const float (&ground)[4],
395 const GearVector& compression,
396 const float (&pos)[3],
397 std::function<
float ()> bump_fn,
398 float (&o_contact)[3],
399 float& o_compression_distance_vertical,
400 float& o_compression_norm
405 float a = ground[3] - Math::dot3(pos, ground);
406 float BumpAltitude=0;
409 BumpAltitude = bump_fn();
414 o_compression_distance_vertical = 0;
415 o_compression_norm = 0;
419 o_compression_distance_vertical = -a;
426 Math::add3(compression.v, pos, tmp);
427 float b = ground[3] - Math::dot3(tmp, ground)+BumpAltitude;
431 o_compression_norm = 1;
433 o_compression_norm = a/(a-b);
434 for(
int i=0;
i<3;
i++)
435 o_contact[
i] = pos[
i] + o_compression_norm * compression.v[
i];
440void Gear::calcForce(Ground *g_cb, RigidBody* body, State *s,
float* v,
float* rot)
444 for(
i=0;
i<3;
i++) _force[
i] = _contact[
i] = 0;
455 if (!((_onWater&&!_ground_isSolid)||(_onSolid&&_ground_isSolid))) {
466 s->planeGlobalToLocal(_global_ground, ground);
475 [
this] {
return this->getBumpAltitude(); },
490 s->globalToLocal(_global_vel, glvel);
493 const float (&cmpr)[3] = _cmpr.unit;
494 const float &clen = _cmpr.magnitude;
498 body->pointVelocity(_contact, rot, cv);
499 Math::add3(cv, v, cv);
500 Math::sub3(cv, glvel, cv);
504 _frac = (_frac > 1) ? 1 : _frac;
507 float frac_with_initial_load;
508 if (_frac>0.2 || _initialLoad==0.0)
509 frac_with_initial_load = _frac+_initialLoad;
511 frac_with_initial_load = (_frac+_initialLoad)
512 *_frac*_frac*3*25-_frac*_frac*_frac*2*125;
514 float fmag = clen * _spring *
516 frac_with_initial_load
517 + _spring2 * pow( frac_with_initial_load, 2)
519 if (_speed_planing>0)
521 float v = Math::mag3(cv);
522 if (v < _speed_planing)
524 float frac = v/_speed_planing;
525 fmag = fmag*_spring_factor_not_planing*(1-frac)+fmag*frac;
532 Math::mul3(Math::dot3(ground, cv), ground, tmp);
533 float dv = Math::dot3(cmpr, tmp);
534 float damp = _damp * dv;
535 if(damp > fmag) damp = fmag;
536 if(damp < -fmag) damp = -fmag;
540 _wow = (fmag - damp) * -Math::dot3(cmpr, ground);
541 Math::mul3(-_wow, ground, _force);
552 Math::set3(ground, gup);
553 Math::mul3(-1, gup, gup);
555 float xhat[] = {1,0,0};
556 float steer[3], skid[3];
557 Math::cross3(gup, xhat, skid);
558 Math::unit3(skid, skid);
560 Math::cross3(skid, gup, steer);
564 float srot = Math::sin(_rot);
565 float crot = Math::cos(_rot);
568 steer[0] = crot*tx + srot*ty;
569 steer[1] = -srot*tx + crot*ty;
573 skid[0] = crot*tx + srot*ty;
574 skid[1] = -srot*tx + crot*ty;
577 float vsteer = Math::dot3(cv, steer);
578 float vskid = Math::dot3(cv, skid);
579 float wgt = Math::dot3(_force, gup);
582 _rollSpeed = Math::sqrt(vsteer*vsteer + vskid*vskid);
586 if(_rollSpeed > 0.05)
587 _casterAngle = Math::atan2(vskid, vsteer);
596 calcForceWithoutStiction(wgt, steer, skid, cv, _force);
600 calcForceWithStiction(g_cb, s, wgt, steer, skid, cv, _force);
604void Gear::calcForceWithStiction(Ground *g_cb, State *s,
float wgt,
float steer[3],
float skid[3],
float *cv,
float *force)
607 if(_ground_isSolid) {
609 double stuckd[3], lVel[3], aVel[3];
610 double body_xform[16];
613 g_cb->getBody(s->dt, body_xform, lVel, aVel, _body_id);
614 Math::set3(&body_xform[12], _ground_trans);
616 for (
int i = 0;
i < 3;
i++) {
617 for (
int j = 0; j < 3; j++) {
618 _ground_rot[
i*3+j] = body_xform[
i*4+j];
624 getStuckPoint(stuckd);
627 s->posGlobalToLocal(stuckd, stuckf);
628 calcFriction(stuckf, cv, steer, skid, wgt, ffric);
631 calcFrictionFluid(cv, steer, skid, wgt, ffric);
635 Math::add3(ffric, force, force);
638void Gear::calcForceWithoutStiction(
float wgt,
float steer[3],
float skid[3],
float *cv,
float *force)
642 vsteer = Math::dot3(cv, steer);
643 vskid = Math::dot3(cv, skid);
647 if(_ground_isSolid) {
648 fsteer = (_brake * _ground_frictionFactor
649 +(1-_brake)*_ground_rollingFriction
650 )*calcFriction(wgt, vsteer);
651 fskid = calcFriction(wgt, vskid)*(_ground_frictionFactor);
654 fsteer = calcFrictionFluid(wgt, vsteer)*_ground_frictionFactor;
655 fskid = 10*calcFrictionFluid(wgt, vskid)*_ground_frictionFactor;
658 if(vsteer > 0) fsteer = -fsteer;
659 if(vskid > 0) fskid = -fskid;
662 float factor = (1-_frac)*(1-_reduceFrictionByExtension)+_frac*1;
663 factor = Math::clamp(factor,0,1);
668 Math::mul3(fsteer, steer, tmp);
669 Math::add3(tmp, force, force);
671 Math::mul3(fskid, skid, tmp);
672 Math::add3(tmp, force, force);
675float Gear::calcFriction(
float wgt,
float v)
678 const float STOP = 0.1f;
679 const float iSTOP = 1.0f/STOP;
681 if(v < STOP)
return v*iSTOP * wgt * _sfric;
682 else return wgt * _dfric;
685float Gear::calcFrictionFluid(
float wgt,
float v)
688 const float STOP = 0.01f;
689 const float iSTOP = 1.0f/STOP;
691 if(v < STOP)
return v*iSTOP * wgt * _sfric;
692 else return wgt * _dfric*v*v*0.01;
697void Gear::calcFriction(
float *stuck,
float *cv,
float *steer,
float *skid
698 ,
float wgt,
float *force)
702 Math::sub3(_contact, stuck, dgear);
706 dsteer = Math::dot3(dgear, steer);
707 dskid = Math::dot3(dgear, skid);
711 vsteer = Math::dot3(cv, steer);
712 vskid = Math::dot3(cv, skid);
718 if (Math::sqrt(dskid*dskid + dsteer*dsteer*(_brake/_sfric)) > _fric_spring)
723 if (_stiction && _stiction_abs && (Math::abs(dskid) < _fric_spring))
726 bl = _sfric - _sfric * (Math::abs(dskid) / _fric_spring);
727 if (_brake > bl) _brake = bl;
734 float fric, fspring, fdamper, brake, tmp[3];
739 brake = _brake > _sfric ? 1 : _brake/_sfric;
740 fspring = Math::abs((dsteer / _fric_spring) * wgt * _sfric);
742 if ((Math::abs(dsteer) > _fric_spring) || (fspring > brake * wgt * _sfric))
745 fric = _ground_rollingFriction * wgt * _sfric;
746 fric += _brake * wgt * _sfric * _ground_frictionFactor;
747 if (vsteer > 0) fric = -fric;
751 fdamper = Math::abs(vsteer * wgt * _sfric);
752 fdamper *= ((dsteer * vsteer) > 0) ? 1 : -1;
753 fric = fspring + fdamper;
754 fric *= brake * _ground_frictionFactor
755 + (1 - brake) * _ground_rollingFriction;
756 if (dsteer > 0) fric = -fric;
758 Math::mul3(fric, steer, force);
761 fspring = Math::abs((dskid / _fric_spring) * wgt * _sfric);
762 fdamper = Math::abs(vskid * wgt * _sfric);
763 fdamper *= ((dskid * vskid) > 0) ? 1 : -1;
764 fric = _ground_frictionFactor * (fspring + fdamper);
765 if (dskid > 0) fric = -fric;
767 Math::mul3(fric, skid, tmp);
768 Math::add3(force, tmp, force);
772 if (Math::mag3(force) > wgt * _sfric * _ground_frictionFactor)
782 Math::unit3(dgear, dir);
786 brake = _brake > _dfric ? 1 : _brake/_dfric;
787 fric = wgt * _dfric * Math::abs(Math::dot3(dir, steer));
788 fric *= _ground_rollingFriction * (1 - brake)
789 + _ground_frictionFactor * brake;
790 if (vsteer > 0) fric = -fric;
791 Math::mul3(fric, steer, force);
794 fric = wgt * _dfric * _ground_frictionFactor;
796 fric *= (1 - brake) + Math::abs(Math::dot3(dir, skid)) * brake;
797 if (vskid > 0) fric = -fric;
799 Math::mul3(fric, skid, tmp);
800 Math::add3(force, tmp, force);
804 float factor = (1-_frac)*(1-_reduceFrictionByExtension)+_frac*1;
805 factor = Math::clamp(factor,0,1);
806 Math::mul3(factor, force, force);
810void Gear::calcFrictionFluid(
float *cv,
float *steer,
float *skid,
float wgt,
float *force)
813 const float STOP = 0.01f;
814 const float iSTOP = 1.0f/STOP;
816 vsteer = Math::dot3(cv, steer);
817 vskid = Math::dot3(cv, skid);
822 float v = Math::abs(vsteer);
823 if(v < STOP) fric = v*iSTOP * wgt * _sfric;
824 else fric = wgt * _dfric*v*v*0.01;
826 if (v > 0) fric = -fric;
827 Math::mul3(_ground_frictionFactor * fric, steer, force);
830 v = Math::abs(vskid);
831 if(v < STOP) fric = v*iSTOP * wgt * _sfric;
832 else fric = wgt * _dfric*v*v*0.01;
834 if (v > 0) fric = -fric;
835 Math::mul3(10 * _ground_frictionFactor * fric, skid, tmp);
836 Math::add3(force, tmp, force);
842void Gear::getStuckPoint(
double *out)
845 Math::tmul33(_ground_rot, _stuck, out);
846 out[0] += _ground_trans[0];
847 out[1] += _ground_trans[1];
848 out[2] += _ground_trans[2];
851void Gear::setStuckPoint(
double *in)
854 in[0] -= _ground_trans[0];
855 in[1] -= _ground_trans[1];
856 in[2] -= _ground_trans[2];
857 Math::vmul33(_ground_rot, in, _stuck);
860void Gear::updateStuckPoint(State* s)
866 getStuckPoint(stuckd);
869 s->posGlobalToLocal(stuckd, stuck);
873 s->planeGlobalToLocal(_global_ground, ground);
875 Math::set3(ground, gup);
876 Math::mul3(-1, gup, gup);
878 float xhat[] = {1,0,0};
879 float skid[3], steer[3];
880 Math::cross3(gup, xhat, skid);
881 Math::unit3(skid, skid);
882 Math::cross3(skid, gup, steer);
886 float srot = Math::sin(_rot);
887 float crot = Math::cos(_rot);
890 steer[0] = crot*tx + srot*ty;
891 steer[1] = -srot*tx + crot*ty;
896 skid[0] = crot*tx + srot*ty;
897 skid[1] = -srot*tx + crot*ty;
904 Math::sub3(_contact, stuck, tmp);
907 dskid = Math::dot3(tmp, skid);
908 dsteer = Math::dot3(tmp, steer);
914 float rad = (dskid / _fric_spring) * 5.0 *
DEG2RAD;
915 dskid -= Math::abs(dsteer) * Math::tan(rad);
917 Math::mul3(dskid, skid, tmp);
918 Math::sub3(_contact, tmp, stuck);
920 else if (_slipping) {
921 Math::set3(_contact, stuck);
924 if (_rolling || _slipping)
927 s->posLocalToGlobal(stuck, stuckd);
930 setStuckPoint(stuckd);
static const float maxGroundBumpAmplitude
bool gearCompressionOld(const float(&ground)[4], const GearVector &compression, const float(&pos)[3], std::function< float()> bump_fn, float(&o_contact)[3], float &o_compression_distance_vertical, float &o_compression_norm)
static const float YASIM_PI
static const float DEG2RAD
bool gearCompression(const float(&ground)[4], const GearVector &compression, const float(&wheel_pos)[3], const GearVector(&wheel_axle), float wheel_radius, float tyre_radius, std::function< float()> bump_fn, float(&o_contact)[3], float &o_compression_distance_vertical, float &o_compression_norm)
static float magnitudeUnit(const float *v, float *out)