00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "spring.h"
00020 #include "types.h"
00021
00022 #include <algorithm>
00023 #include <cmath>
00024
00025 namespace StepCore {
00026
00027 STEPCORE_META_OBJECT(Spring, "Massless spring which can be connected to bodies", 0,
00028 STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Force),
00029 STEPCORE_PROPERTY_RW(double, restLength, "m", "Rest length", restLength, setRestLength)
00030 STEPCORE_PROPERTY_R_D(double, length, "m", "Current length", length)
00031 STEPCORE_PROPERTY_RW(double, stiffness, "N/m", "Stiffness", stiffness, setStiffness)
00032 STEPCORE_PROPERTY_RW(double, damping, "N s/m", "Damping", damping, setDamping)
00033 STEPCORE_PROPERTY_RW(Object*, body1, STEPCORE_UNITS_NULL, "Body1", body1, setBody1)
00034 STEPCORE_PROPERTY_RW(Object*, body2, STEPCORE_UNITS_NULL, "Body2", body2, setBody2)
00035 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition1, "m",
00036 "Local position 1", localPosition1, setLocalPosition1)
00037 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition2, "m",
00038 "Local position 2", localPosition2, setLocalPosition2)
00039 STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position1, "m", "Position1", position1)
00040 STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position2, "m", "Position2", position2)
00041 STEPCORE_PROPERTY_R_D(double, force, "N", "Spring tension force", force)
00042 )
00043
00044 STEPCORE_META_OBJECT(SpringErrors, "Errors class for Spring", 0,
00045 STEPCORE_SUPER_CLASS(ObjectErrors),
00046 STEPCORE_PROPERTY_RW(double, restLengthVariance, "m",
00047 "Rest length variance", restLengthVariance, setRestLengthVariance)
00048 STEPCORE_PROPERTY_R_D(double, lengthVariance, "m",
00049 "Current length variance", lengthVariance)
00050 STEPCORE_PROPERTY_RW(double, stiffnessVariance, "N/m",
00051 "Stiffness variance", stiffnessVariance, setStiffnessVariance)
00052 STEPCORE_PROPERTY_RW(double, dampingVariance, "N/m",
00053 "Damping variance", dampingVariance, setDampingVariance)
00054 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition1Variance, "m",
00055 "Local position 1 variance", localPosition1Variance, setLocalPosition1Variance)
00056 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition2Variance, "m",
00057 "Local position 2 variance", localPosition2Variance, setLocalPosition2Variance)
00058 STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position1Variance, "m",
00059 "Position1 variance", position1Variance)
00060 STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position2Variance, "m",
00061 "Position2 variance", position2Variance)
00062 STEPCORE_PROPERTY_R_D(double, forceVariance, "N",
00063 "Spring tension force variance", forceVariance)
00064 )
00065
00066 Spring* SpringErrors::spring() const
00067 {
00068 return static_cast<Spring*>(owner());
00069 }
00070
00071 Spring::Spring(double restLength, double stiffness, double damping, Item* body1, Item* body2)
00072 : _restLength(restLength),
00073 _stiffness(stiffness), _damping(damping),
00074 _localPosition1(0), _localPosition2(0)
00075 {
00076 setColor(0xff00ff00);
00077 setBody1(body1);
00078 setBody2(body2);
00079 }
00080
00081 void Spring::calcForce(bool calcVariances)
00082 {
00083 if(!_body1 && !_body2) return;
00084
00085 Vector2d position1 = this->position1();
00086 Vector2d position2 = this->position2();
00087 Vector2d r = position2 - position1;
00088 Vector2d v = velocity2() - velocity1();
00089
00090 double l = r.norm();
00091 if(l == 0) return;
00092
00093 double dl = l - _restLength;
00094 double vr = v.innerProduct(r);
00095 Vector2d force = (_stiffness*dl + _damping*vr/l) / l * r;
00096
00097 if(_p1) _p1->applyForce(force);
00098 else if(_r1) _r1->applyForce(force, position1);
00099
00100 force.invert();
00101 if(_p2) _p2->applyForce(force);
00102 else if(_r2) _r2->applyForce(force, position2);
00103
00104 if(calcVariances) {
00105 SpringErrors* se = springErrors();
00106
00107 Vector2d rV = se->position2Variance() + se->position1Variance();
00108 Vector2d vV = se->velocity2Variance() + se->velocity1Variance();
00109
00110 Vector2d forceV = (se->_restLengthVariance * square(_stiffness) +
00111 se->_stiffnessVariance * square(dl) +
00112 se->_dampingVariance * square(vr/l) +
00113 vV.innerProduct( (_damping/l*r).cSquare() )
00114 )/square(l)*r.cSquare();
00115
00116 forceV[0] += rV[0] * square(_stiffness*( 1 - _restLength/l*(1 - square(r[0]/l)) ) +
00117 _damping/(l*l)*( v[0]*r[0] + vr - 2*vr*square(r[0]/l) )) +
00118 rV[1] * square(_stiffness*_restLength*r[0]*r[1]/(l*l*l) +
00119 _damping/(l*l)*( v[1]*r[0] - 2*vr*r[0]*r[1]/(l*l) ));
00120 forceV[1] += rV[1] * square(_stiffness*( 1 - _restLength/l*(1 - square(r[1]/l)) ) +
00121 _damping/(l*l)*( v[1]*r[1] + vr - 2*vr*square(r[1]/l) )) +
00122 rV[0] * square(_stiffness*_restLength*r[0]*r[1]/(l*l*l) +
00123 _damping/(l*l)*( v[0]*r[1] - 2*vr*r[0]*r[1]/(l*l) ));
00124
00125
00126 if(_p1) _p1->particleErrors()->applyForceVariance(forceV);
00127 else if(_r1) _r1->rigidBodyErrors()->applyForceVariance(force, position1,
00128 forceV, se->position1Variance() );
00129
00130 if(_p2) _p2->particleErrors()->applyForceVariance(forceV);
00131 else if(_r2) _r2->rigidBodyErrors()->applyForceVariance(force, position2,
00132 forceV, se->position2Variance() );
00133 }
00134 }
00135
00136 void Spring::setBody1(Object* body1)
00137 {
00138 if(body1) {
00139 if(body1->metaObject()->inherits<Particle>()) {
00140 _body1 = body1;
00141 _p1 = static_cast<Particle*>(body1);
00142 _r1 = NULL;
00143 return;
00144 } else if(body1->metaObject()->inherits<RigidBody>()) {
00145 _body1 = body1;
00146 _p1 = NULL;
00147 _r1 = static_cast<RigidBody*>(body1);
00148 return;
00149 }
00150 }
00151 _body1 = NULL;
00152 _p1 = NULL;
00153 _r1 = NULL;
00154 }
00155
00156 void Spring::setBody2(Object* body2)
00157 {
00158 if(body2) {
00159 if(body2->metaObject()->inherits<Particle>()) {
00160 _body2 = body2;
00161 _p2 = static_cast<Particle*>(body2);
00162 _r2 = NULL;
00163 return;
00164 } else if(body2->metaObject()->inherits<RigidBody>()) {
00165 _body2 = body2;
00166 _p2 = NULL;
00167 _r2 = static_cast<RigidBody*>(body2);
00168 return;
00169 }
00170 }
00171 _body2 = NULL;
00172 _p2 = NULL;
00173 _r2 = NULL;
00174 }
00175
00176 Vector2d Spring::position1() const
00177 {
00178 if(_p1) return _p1->position() + _localPosition1;
00179 else if(_r1) return _r1->pointLocalToWorld(_localPosition1);
00180 else return _localPosition1;
00181 }
00182
00183 Vector2d SpringErrors::position1Variance() const
00184 {
00185 if(spring()->_p1)
00186 return spring()->_p1->particleErrors()->positionVariance() + _localPosition1Variance;
00187
00188
00189
00190 #ifdef __GNUC__
00191 #warning variance calculation for spring connected to rigidbody is not finished !
00192 #warning consider unification of some part of Particle and RigidBody
00193 #endif
00194 else return _localPosition1Variance;
00195 }
00196
00197 Vector2d Spring::position2() const
00198 {
00199 if(_p2) return _p2->position() + _localPosition2;
00200 else if(_r2) return _r2->pointLocalToWorld(_localPosition2);
00201 else return _localPosition2;
00202 }
00203
00204 Vector2d SpringErrors::position2Variance() const
00205 {
00206 if(spring()->_p2)
00207 return spring()->_p2->particleErrors()->positionVariance() + _localPosition2Variance;
00208
00209
00210
00211 else return _localPosition2Variance;
00212 }
00213
00214 double SpringErrors::lengthVariance() const
00215 {
00216 Vector2d r = spring()->position2() - spring()->position1();
00217 Vector2d rV = position2Variance() + position1Variance();
00218 return (r[0]*r[0]*rV[0] + r[1]*r[1]*rV[1])/r.norm2();
00219 }
00220
00221 Vector2d Spring::velocity1() const
00222 {
00223 if(_p1) return _p1->velocity();
00224 else if(_r1) return _r1->velocityLocal(_localPosition1);
00225 else return Vector2d(0);
00226 }
00227
00228 Vector2d SpringErrors::velocity1Variance() const
00229 {
00230 if(spring()->_p1)
00231 return spring()->_p1->particleErrors()->velocityVariance();
00232
00233
00234
00235 else return Vector2d(0);
00236 }
00237
00238 Vector2d Spring::velocity2() const
00239 {
00240 if(_p2) return _p2->velocity();
00241 else if(_r2) return _r2->velocityLocal(_localPosition2);
00242 else return Vector2d(0);
00243 }
00244
00245 Vector2d SpringErrors::velocity2Variance() const
00246 {
00247 if(spring()->_p2)
00248 return spring()->_p2->particleErrors()->velocityVariance();
00249
00250
00251
00252 else return Vector2d(0);
00253 }
00254
00255 double Spring::force() const
00256 {
00257 Vector2d r = position2() - position1();
00258 Vector2d v = velocity2() - velocity1();
00259 double l = r.norm();
00260 return _stiffness * (l - _restLength) +
00261 _damping * v.innerProduct(r)/l;
00262 }
00263
00264 double SpringErrors::forceVariance() const
00265 {
00266 Spring* s = spring();
00267 Vector2d r = s->position2() - s->position1();
00268 Vector2d v = s->velocity2() - s->velocity1();
00269 Vector2d rV = position2Variance() + position1Variance();
00270 Vector2d vV = velocity2Variance() + velocity1Variance();
00271 double l = r.norm();
00272 double dl = l - s->restLength();
00273
00274 return square(dl) * _stiffnessVariance +
00275 square(s->stiffness()) * _restLengthVariance +
00276 square(v.innerProduct(r)/l) * _dampingVariance +
00277 (s->damping()/l*r).cSquare().innerProduct(vV) +
00278 (( s->stiffness() - s->damping()*v.innerProduct(r) / (l*l) ) / l * r +
00279 s->damping() / l * v).cSquare().innerProduct(rV);
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 #if 0
00292 void Spring::setWorld(World* world)
00293 {
00294 if(world == NULL) {
00295 setBody1(NULL);
00296 setBody2(NULL);
00297 } else if(this->world() != NULL) {
00298 #ifdef __GNUC__
00299 #warning Use map instead of search-by-name here !
00300 #endif
00301 if(_body1 != NULL) setBody1(world->item(body1()->name()));
00302 if(_body2 != NULL) setBody2(world->item(body2()->name()));
00303 }
00304 Item::setWorld(world);
00305 }
00306 #endif
00307
00308 }
00309