00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "joint.h"
00020 #include "particle.h"
00021 #include "rigidbody.h"
00022 #include <cstring>
00023
00024 namespace StepCore {
00025
00026 STEPCORE_META_OBJECT(Anchor, "Anchor: fixes position of the body", 0,
00027 STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Joint),
00028 STEPCORE_PROPERTY_RW(Object*, body, STEPCORE_UNITS_NULL, "Body", body, setBody)
00029 STEPCORE_PROPERTY_RW(StepCore::Vector2d, position, "m", "Position", position, setPosition)
00030 STEPCORE_PROPERTY_RW(double, angle, "rad", "Angle", angle, setAngle))
00031
00032 STEPCORE_META_OBJECT(Pin, "Pin: fixes position of a given point on the body", 0,
00033 STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Joint),
00034 STEPCORE_PROPERTY_RW(Object*, body, STEPCORE_UNITS_NULL, "Body", body, setBody)
00035 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition, "m", "Position on the on a body", localPosition, setLocalPosition)
00036 STEPCORE_PROPERTY_RW(StepCore::Vector2d, position, "m", "Position in the world", position, setPosition))
00037
00038 STEPCORE_META_OBJECT(Stick, "Massless stick which can be connected to bodies", 0,
00039 STEPCORE_SUPER_CLASS(Item) STEPCORE_SUPER_CLASS(Joint),
00040 STEPCORE_PROPERTY_RW(double, restLength, "m", "Rest length of the stick", restLength, setRestLength)
00041 STEPCORE_PROPERTY_RW(Object*, body1, STEPCORE_UNITS_NULL, "Body1", body1, setBody1)
00042 STEPCORE_PROPERTY_RW(Object*, body2, STEPCORE_UNITS_NULL, "Body2", body2, setBody2)
00043 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition1, "m",
00044 "Local position 1", localPosition1, setLocalPosition1)
00045 STEPCORE_PROPERTY_RW(StepCore::Vector2d, localPosition2, "m",
00046 "Local position 2", localPosition2, setLocalPosition2)
00047 STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position1, "m", "Position1", position1)
00048 STEPCORE_PROPERTY_R_D(StepCore::Vector2d, position2, "m", "Position2", position2)
00049 )
00050
00051 STEPCORE_META_OBJECT(Rope, "Massless rope which can be connected to bodies", 0,
00052 STEPCORE_SUPER_CLASS(Stick),)
00053
00054 Anchor::Anchor(Object* body, const Vector2d& position, double angle)
00055 : _position(position), _angle(angle)
00056 {
00057 setBody(body);
00058 setColor(0xffff0000);
00059 }
00060
00061 void Anchor::setBody(Object* body)
00062 {
00063 if(body) {
00064 if(body->metaObject()->inherits<Particle>()) {
00065 _body = body;
00066 _p = static_cast<Particle*>(body);
00067 _r = NULL;
00068 return;
00069 } else if(body->metaObject()->inherits<RigidBody>()) {
00070 _body = body;
00071 _p = NULL;
00072 _r = static_cast<RigidBody*>(body);
00073 return;
00074 }
00075 }
00076 _body = NULL;
00077 _p = NULL;
00078 _r = NULL;
00079 }
00080
00081 int Anchor::constraintsCount()
00082 {
00083 if(_p) return 2;
00084 else if(_r) return 3;
00085 else return 0;
00086 }
00087
00088 void Anchor::getConstraintsInfo(ConstraintsInfo* info, int offset)
00089 {
00090 if(_p) {
00091 info->value[offset ] = _p->position()[0] - _position[0];
00092 info->value[offset+1] = _p->position()[1] - _position[1];
00093
00094 info->derivative[offset ] = _p->velocity()[0];
00095 info->derivative[offset+1] = _p->velocity()[1];
00096
00097 info->jacobian.row(offset).w(_p->variablesOffset()+Particle::PositionOffset, 1);
00098 info->jacobian.row(offset+1).w(_p->variablesOffset()+Particle::PositionOffset+1, 1);
00099
00100 } else if(_r) {
00101 info->value[offset ] = _r->position()[0] - _position[0];
00102 info->value[offset+1] = _r->position()[1] - _position[1];
00103 info->value[offset+2] = _r->angle() - _angle;
00104
00105 info->derivative[offset ] = _r->velocity()[0];
00106 info->derivative[offset+1] = _r->velocity()[1];
00107 info->derivative[offset+2] = _r->angularVelocity();
00108
00109 info->jacobian.row(offset).w(_r->variablesOffset()+RigidBody::PositionOffset, 1);
00110 info->jacobian.row(offset+1).w(_r->variablesOffset()+RigidBody::PositionOffset+1, 1);
00111 info->jacobian.row(offset+2).w(_r->variablesOffset()+RigidBody::AngleOffset, 1);
00112 }
00113 }
00114
00115 Pin::Pin(Object* body, const Vector2d& localPosition, const Vector2d& position)
00116 : _localPosition(localPosition), _position(position)
00117 {
00118 setBody(body);
00119 setColor(0xffff0000);
00120 }
00121
00122 void Pin::setBody(Object* body)
00123 {
00124 if(body) {
00125 if(body->metaObject()->inherits<Particle>()) {
00126 _body = body;
00127 _p = static_cast<Particle*>(body);
00128 _r = NULL;
00129 return;
00130 } else if(body->metaObject()->inherits<RigidBody>()) {
00131 _body = body;
00132 _p = NULL;
00133 _r = static_cast<RigidBody*>(body);
00134 return;
00135 }
00136 }
00137 _body = NULL;
00138 _p = NULL;
00139 _r = NULL;
00140 }
00141
00142 int Pin::constraintsCount()
00143 {
00144 if(_p) {
00145 if(_localPosition.norm2() != 0) return 1;
00146 else return 2;
00147 } else if(_r) return 2;
00148 else return 0;
00149 }
00150
00151 void Pin::getConstraintsInfo(ConstraintsInfo* info, int offset)
00152 {
00153 if(_p) {
00154 Vector2d r = _p->position() - _position;
00155 double lnorm2 = _localPosition.norm2();
00156
00157 if(lnorm2 != 0) {
00158 info->value[offset] = (r.norm2() - lnorm2)*0.5;
00159 info->derivative[offset] = _p->velocity().innerProduct(r);
00160
00161 info->jacobian.row(offset).w(_p->variablesOffset()+Particle::PositionOffset, r[0]);
00162 info->jacobian.row(offset).w(_p->variablesOffset()+Particle::PositionOffset+1, r[1]);
00163
00164 info->jacobianDerivative.row(offset).w(
00165 _p->variablesOffset()+Particle::PositionOffset, _p->velocity()[0]);
00166 info->jacobianDerivative.row(offset).w(
00167 _p->variablesOffset()+Particle::PositionOffset+1, _p->velocity()[1]);
00168 } else {
00169 info->value[offset ] = r[0];
00170 info->value[offset+1] = r[1];
00171 info->derivative[offset ] = _p->velocity()[0];
00172 info->derivative[offset+1] = _p->velocity()[1];
00173
00174 info->jacobian.row(offset).w(_p->variablesOffset()+Particle::PositionOffset, 1);
00175 info->jacobian.row(offset+1).w(_p->variablesOffset()+Particle::PositionOffset+1, 1);
00176 }
00177 } else if(_r) {
00178 Vector2d r1 = _r->vectorLocalToWorld(_localPosition);
00179 Vector2d p1 = _r->position() + r1;
00180 Vector2d v1 = _r->velocityWorld(p1);
00181 double av = _r->angularVelocity();
00182
00183 info->value[offset ] = p1[0] - _position[0];
00184 info->value[offset+1] = p1[1] - _position[1];
00185 info->derivative[offset ] = v1[0];
00186 info->derivative[offset+1] = v1[1];
00187
00188 info->jacobian.row(offset ).w(_r->variablesOffset()+RigidBody::PositionOffset, 1);
00189 info->jacobian.row(offset+1).w(_r->variablesOffset()+RigidBody::PositionOffset+1, 1);
00190 info->jacobian.row(offset ).w(_r->variablesOffset()+RigidBody::AngleOffset, -r1[1]);
00191 info->jacobian.row(offset+1).w(_r->variablesOffset()+RigidBody::AngleOffset, r1[0]);
00192 info->jacobianDerivative.row(offset ).w(_r->variablesOffset()+RigidBody::AngleOffset, -av*r1[0]);
00193 info->jacobianDerivative.row(offset+1).w(_r->variablesOffset()+RigidBody::AngleOffset, -av*r1[1]);
00194 }
00195
00196 }
00197
00198 Stick::Stick(double restLength, Object* body1, Object* body2,
00199 const Vector2d& localPosition1, const Vector2d& localPosition2)
00200 : _restLength(restLength), _localPosition1(localPosition1), _localPosition2(localPosition2)
00201 {
00202 setColor(0xffff0000);
00203 setBody1(body1);
00204 setBody2(body2);
00205 }
00206
00207 void Stick::setBody1(Object* body1)
00208 {
00209 if(body1) {
00210 if(body1->metaObject()->inherits<Particle>()) {
00211 _body1 = body1;
00212 _p1 = static_cast<Particle*>(body1);
00213 _r1 = NULL;
00214 return;
00215 } else if(body1->metaObject()->inherits<RigidBody>()) {
00216 _body1 = body1;
00217 _p1 = NULL;
00218 _r1 = static_cast<RigidBody*>(body1);
00219 return;
00220 }
00221 }
00222 _body1 = NULL;
00223 _p1 = NULL;
00224 _r1 = NULL;
00225 }
00226
00227 void Stick::setBody2(Object* body2)
00228 {
00229 if(body2) {
00230 if(body2->metaObject()->inherits<Particle>()) {
00231 _body2 = body2;
00232 _p2 = static_cast<Particle*>(body2);
00233 _r2 = NULL;
00234 return;
00235 } else if(body2->metaObject()->inherits<RigidBody>()) {
00236 _body2 = body2;
00237 _p2 = NULL;
00238 _r2 = static_cast<RigidBody*>(body2);
00239 return;
00240 }
00241 }
00242 _body2 = NULL;
00243 _p2 = NULL;
00244 _r2 = NULL;
00245 }
00246
00247 Vector2d Stick::position1() const
00248 {
00249 if(_p1) return _p1->position() + _localPosition1;
00250 else if(_r1) return _r1->pointLocalToWorld(_localPosition1);
00251 else return _localPosition1;
00252 }
00253
00254 Vector2d Stick::position2() const
00255 {
00256 if(_p2) return _p2->position() + _localPosition2;
00257 else if(_r2) return _r2->pointLocalToWorld(_localPosition2);
00258 else return _localPosition2;
00259 }
00260
00261 Vector2d Stick::velocity1() const
00262 {
00263 if(_p1) return _p1->velocity();
00264 else if(_r1) return _r1->velocityLocal(_localPosition1);
00265 else return Vector2d(0);
00266 }
00267
00268 Vector2d Stick::velocity2() const
00269 {
00270 if(_p2) return _p2->velocity();
00271 else if(_r2) return _r2->velocityLocal(_localPosition2);
00272 else return Vector2d(0);
00273 }
00274
00275 int Stick::constraintsCount()
00276 {
00277 if(!_body1 && !_body2) return 0;
00278
00279 if(_restLength != 0) return 1;
00280 else return 2;
00281 }
00282
00283 void Stick::getConstraintsInfo(ConstraintsInfo* info, int offset)
00284 {
00285 if(!_body1 && !_body2) return;
00286
00287 Vector2d p = position2() - position1();
00288 Vector2d v = velocity2() - velocity1();
00289
00290
00291 if(_restLength != 0) {
00292 info->value[offset] = (p.norm2() - _restLength*_restLength)*0.5;
00293 info->derivative[offset] = p.innerProduct(v);
00294
00295 if(p[0] == 0 && p[1] == 0) p[0] = 0.1;
00296
00297 if(_p1) {
00298 info->jacobian.row(offset).w(_p1->variablesOffset() + Particle::PositionOffset, -p[0]);
00299 info->jacobian.row(offset).w(_p1->variablesOffset() + Particle::PositionOffset+1, -p[1]);
00300
00301 info->jacobianDerivative.row(offset).w(_p1->variablesOffset() + Particle::PositionOffset, -v[0]);
00302 info->jacobianDerivative.row(offset).w(_p1->variablesOffset() + Particle::PositionOffset+1, -v[1]);
00303
00304 } else if(_r1) {
00305 Vector2d r1 = _r1->vectorLocalToWorld(_localPosition1);
00306
00307 info->jacobian.row(offset).w(_r1->variablesOffset() + RigidBody::PositionOffset, -p[0]);
00308 info->jacobian.row(offset).w(_r1->variablesOffset() + RigidBody::PositionOffset+1, -p[1]);
00309 info->jacobian.row(offset).w(_r1->variablesOffset() + RigidBody::AngleOffset, +p[0]*r1[1] - p[1]*r1[0]);
00310
00311 info->jacobianDerivative.row(offset).w(_r1->variablesOffset() + RigidBody::PositionOffset, -v[0]);
00312 info->jacobianDerivative.row(offset).w(_r1->variablesOffset() + RigidBody::PositionOffset+1, -v[1]);
00313 info->jacobianDerivative.row(offset).w(_r1->variablesOffset() + RigidBody::AngleOffset,
00314 + v[0]*r1[1] - v[1]*r1[0] + _r1->angularVelocity()*p.innerProduct(r1));
00315 }
00316
00317 if(_p2) {
00318 info->jacobian.row(offset).w(_p2->variablesOffset() + Particle::PositionOffset, p[0]);
00319 info->jacobian.row(offset).w(_p2->variablesOffset() + Particle::PositionOffset+1, p[1]);
00320
00321 info->jacobianDerivative.row(offset).w(_p2->variablesOffset() + Particle::PositionOffset, v[0]);
00322 info->jacobianDerivative.row(offset).w(_p2->variablesOffset() + Particle::PositionOffset+1, v[1]);
00323
00324 } else if(_r2) {
00325 Vector2d r2 = _r2->vectorLocalToWorld(_localPosition2);
00326
00327 info->jacobian.row(offset).w(_r2->variablesOffset() + RigidBody::PositionOffset, p[0]);
00328 info->jacobian.row(offset).w(_r2->variablesOffset() + RigidBody::PositionOffset+1, p[1]);
00329 info->jacobian.row(offset).w(_r2->variablesOffset() + RigidBody::AngleOffset, -p[0]*r2[1] + p[1]*r2[0]);
00330
00331 info->jacobianDerivative.row(offset).w(_r2->variablesOffset() + RigidBody::PositionOffset, v[0]);
00332 info->jacobianDerivative.row(offset).w(_r2->variablesOffset() + RigidBody::PositionOffset+1, v[1]);
00333 info->jacobianDerivative.row(offset).w(_r2->variablesOffset() + RigidBody::AngleOffset,
00334 - v[0]*r2[1] + v[1]*r2[0] - _r2->angularVelocity()*p.innerProduct(r2));
00335 }
00336
00337 } else {
00338 info->value[offset ] = p[0];
00339 info->value[offset+1] = p[1];
00340
00341 info->derivative[offset ] = v[0];
00342 info->derivative[offset+1] = v[1];
00343
00344 if(_p1) {
00345 info->jacobian.row(offset ).w(_p1->variablesOffset() + Particle::PositionOffset, -1);
00346 info->jacobian.row(offset+1).w(_p1->variablesOffset() + Particle::PositionOffset+1, -1);
00347
00348 } else if(_r1) {
00349 Vector2d r1 = _r1->vectorLocalToWorld(_localPosition1);
00350 double av = _r1->angularVelocity();
00351
00352 info->jacobian.row(offset ).w(_r1->variablesOffset() + Particle::PositionOffset, -1);
00353 info->jacobian.row(offset+1).w(_r1->variablesOffset() + Particle::PositionOffset+1, -1);
00354
00355 info->jacobian.row(offset ).w(_r1->variablesOffset()+RigidBody::AngleOffset, +r1[1]);
00356 info->jacobian.row(offset+1).w(_r1->variablesOffset()+RigidBody::AngleOffset, -r1[0]);
00357 info->jacobianDerivative.row(offset ).w(_r1->variablesOffset()+RigidBody::AngleOffset, +av*r1[0]);
00358 info->jacobianDerivative.row(offset+1).w(_r1->variablesOffset()+RigidBody::AngleOffset, +av*r1[1]);
00359 }
00360
00361 if(_p2) {
00362 info->jacobian.row(offset ).w(_p2->variablesOffset() + Particle::PositionOffset, 1);
00363 info->jacobian.row(offset+1).w(_p2->variablesOffset() + Particle::PositionOffset+1, 1);
00364
00365 } else if(_r2) {
00366 Vector2d r2 = _r2->vectorLocalToWorld(_localPosition2);
00367 double av = _r2->angularVelocity();
00368
00369 info->jacobian.row(offset ).w(_r2->variablesOffset() + Particle::PositionOffset, 1);
00370 info->jacobian.row(offset+1).w(_r2->variablesOffset() + Particle::PositionOffset+1, 1);
00371
00372 info->jacobian.row(offset ).w(_r2->variablesOffset()+RigidBody::AngleOffset, -r2[1]);
00373 info->jacobian.row(offset+1).w(_r2->variablesOffset()+RigidBody::AngleOffset, +r2[0]);
00374 info->jacobianDerivative.row(offset ).w(_r2->variablesOffset()+RigidBody::AngleOffset, -av*r2[0]);
00375 info->jacobianDerivative.row(offset+1).w(_r2->variablesOffset()+RigidBody::AngleOffset, -av*r2[1]);
00376 }
00377 }
00378 }
00379
00380 void Rope::getConstraintsInfo(ConstraintsInfo* info, int offset)
00381 {
00382 if(!_body1 && !_body2) return;
00383
00384 Vector2d p = position2() - position1();
00385 Vector2d v = velocity2() - velocity1();
00386
00387 if(_restLength != 0) {
00388 if(p.norm() >= _restLength) {
00389 Stick::getConstraintsInfo(info, offset);
00390 info->forceMax[offset] = 0;
00391 } else {
00392 info->value[offset] = 0;
00393 info->derivative[offset] = 0;
00394 }
00395 } else {
00396 Stick::getConstraintsInfo(info, offset);
00397 }
00398 }
00399
00400 }
00401
00402