• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

step/stepcore

spring.cc

Go to the documentation of this file.
00001 /* This file is part of StepCore library.
00002    Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
00003 
00004    StepCore library is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 2 of the License, or
00007    (at your option) any later version.
00008 
00009    StepCore library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with StepCore; if not, write to the Free Software
00016    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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; // XXX: take orientation from previous step
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         // TODO: position1() and force is corelated, we should take it into account
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     // XXX: TODO
00188     //RigidBody* _r1 = dynamic_cast<RigidBody*>(_body1);
00189     //if(_r1) return _r1->pointLocalToWorld(_localPosition1);
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     // XXX: TODO
00209     //RigidBody* _r2 = dynamic_cast<RigidBody*>(_body2);
00210     //if(_r2) return _r2->pointLocalToWorld(_localPosition2);
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     // XXX: TODO
00233     //RigidBody* _r1 = dynamic_cast<RigidBody*>(_body1);
00234     //if(_r1) return _r1->pointLocalToWorld(_localPosition1);
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     // XXX: TODO
00250     //RigidBody* _r2 = dynamic_cast<RigidBody*>(_body2);
00251     //if(_r2) return _r2->pointLocalToWorld(_localPosition2);
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     // XXX: CHECKME
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 void Spring::worldItemRemoved(Item* item)
00284 {
00285     if(item == NULL) return;
00286     else if(item == _body1) setBody1(NULL);
00287     else if(item == _body2) setBody2(NULL);
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())); //XXX
00302         if(_body2 != NULL) setBody2(world->item(body2()->name())); //XXX
00303     }
00304     Item::setWorld(world);
00305 }
00306 #endif
00307 
00308 } // namespace StepCore
00309 

step/stepcore

Skip menu "step/stepcore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal