File indexing completed on 2025-04-27 06:48:54
0001 /* 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /** \file rigidbody.h 0008 * \brief RigidBody class 0009 */ 0010 0011 #ifndef STEPCORE_RIGIDBODY_H 0012 #define STEPCORE_RIGIDBODY_H 0013 0014 #include "world.h" 0015 #include "vector.h" 0016 #include "object.h" 0017 0018 namespace StepCore { 0019 0020 class RigidBody; 0021 0022 /** \ingroup errors 0023 * \brief Errors object for RigidBody 0024 */ 0025 class RigidBodyErrors: public ObjectErrors 0026 { 0027 STEPCORE_OBJECT(RigidBodyErrors) 0028 0029 public: 0030 /** Constructs RigidBodyErrors */ 0031 explicit RigidBodyErrors(Item* owner = nullptr) 0032 : ObjectErrors(owner), _positionVariance(0,0), _angleVariance(0), _velocityVariance(0,0), 0033 _angularVelocityVariance(0), _forceVariance(0,0), _torqueVariance(0), 0034 _massVariance(0), _inertiaVariance(0) {} 0035 0036 /** Get owner as RigidBody */ 0037 RigidBody* rigidBody() const; 0038 0039 /** Get position variance */ 0040 const Vector2d& positionVariance() const { return _positionVariance; } 0041 /** Set position variance */ 0042 void setPositionVariance(const Vector2d& positionVariance) { 0043 _positionVariance = positionVariance; } 0044 0045 /** Get angle variance */ 0046 double angleVariance() const { return _angleVariance; } 0047 /** Set angle variance */ 0048 void setAngleVariance(double angleVariance) { _angleVariance = angleVariance; } 0049 0050 /** Get velocity variance */ 0051 const Vector2d& velocityVariance() const { return _velocityVariance; } 0052 /** Set velocity variance */ 0053 void setVelocityVariance(const Vector2d& velocityVariance) { 0054 _velocityVariance = velocityVariance; } 0055 0056 /** Get angularVelocity variance */ 0057 double angularVelocityVariance() const { return _angularVelocityVariance; } 0058 /** Set angularVelocity variance */ 0059 void setAngularVelocityVariance(double angularVelocityVariance) { 0060 _angularVelocityVariance = angularVelocityVariance; } 0061 0062 /** Get acceleration variance */ 0063 Vector2d accelerationVariance() const; 0064 0065 /** Get angularAcceleration variance */ 0066 double angularAccelerationVariance() const; 0067 0068 /** Get force variance */ 0069 const Vector2d& forceVariance() const { return _forceVariance; } 0070 /** Set force variance */ 0071 void setForceVariance(const Vector2d& forceVariance) { 0072 _forceVariance = forceVariance; } 0073 0074 /** Get torque variance */ 0075 double torqueVariance() const { return _torqueVariance; } 0076 0077 /** Apply force (and torque) variance to the body at given position (in World coordinates) */ 0078 void applyForceVariance(const Vector2d& force, 0079 const Vector2d& position, 0080 const Vector2d& forceVariance, 0081 const Vector2d& positionVariance); 0082 0083 /** Apply torque (but no force) variance to the body */ 0084 void applyTorqueVariance(double torqueVariance) { _torqueVariance += torqueVariance; } 0085 0086 /** Get mass variance */ 0087 double massVariance() const { return _massVariance; } 0088 /** Set mass variance */ 0089 void setMassVariance(double massVariance) { 0090 _massVariance = massVariance; } 0091 0092 /** Get inertia variance */ 0093 double inertiaVariance() const { return _inertiaVariance; } 0094 /** Set inertia variance */ 0095 void setInertiaVariance(double inertiaVariance) { 0096 _inertiaVariance = inertiaVariance; } 0097 0098 /** Get momentum variance */ 0099 Vector2d momentumVariance() const; 0100 /** Set momentum variance (will modify velocity variance) */ 0101 void setMomentumVariance(const Vector2d& momentumVariance); 0102 0103 /** Get angular momentum variance */ 0104 double angularMomentumVariance() const; 0105 /** Set angular momentum variance (will modify angularVelocity variance) */ 0106 void setAngularMomentumVariance(double angularMomentumVariance); 0107 0108 /** Get kinetic energy variance */ 0109 double kineticEnergyVariance() const; 0110 /** Set kinetic energy variance (will modify velocity variance) */ 0111 void setKineticEnergyVariance(double kineticEnergyVariance); 0112 0113 protected: 0114 Vector2d _positionVariance; 0115 double _angleVariance; 0116 0117 Vector2d _velocityVariance; 0118 double _angularVelocityVariance; 0119 0120 Vector2d _forceVariance; 0121 double _torqueVariance; 0122 0123 double _massVariance; 0124 double _inertiaVariance; 0125 0126 friend class RigidBody; 0127 }; 0128 0129 /** \ingroup bodies 0130 * \brief Rigid body 0131 */ 0132 class RigidBody: public Body 0133 { 0134 STEPCORE_OBJECT(RigidBody) 0135 0136 public: 0137 enum { 0138 PositionOffset = 0, ///< Offset of body position in variables array 0139 AngleOffset = 2 ///< Offset of body angle in variables array 0140 }; 0141 0142 /** Constructs RigidBody */ 0143 explicit RigidBody(const Vector2d &position = Vector2d::Zero(), double angle = 0, 0144 const Vector2d &velocity = Vector2d::Zero(), double angularVelocity = 0, 0145 double mass = 1, double inertia = 1); 0146 0147 /** Get position of the center of mass of the body */ 0148 const Vector2d& position() const { return _position; } 0149 /** Set position of the center of mass of the body */ 0150 void setPosition(const Vector2d& position) { _position = position; } 0151 0152 /** Get angle of the body */ 0153 double angle() const { return _angle; } 0154 /** Set angle of the body */ 0155 void setAngle(double angle) { _angle = angle; } 0156 0157 /** Get velocity of the center of mass of the body */ 0158 const Vector2d& velocity() const { return _velocity; } 0159 /** Set velocity of the particle */ 0160 void setVelocity(const Vector2d& velocity) { _velocity = velocity; } 0161 /** Get velocity of given (world) point on the body */ 0162 Vector2d velocityWorld(const Vector2d& worldPoint) const; 0163 /** Get velocity of given (local) point on the body */ 0164 Vector2d velocityLocal(const Vector2d& localPoint) const; 0165 0166 /** Get angular velocity of the body */ 0167 double angularVelocity() const { return _angularVelocity; } 0168 /** Set angular velocity of the body */ 0169 void setAngularVelocity(double angularVelocity) { _angularVelocity = angularVelocity; } 0170 0171 /** Get acceleration of the center of mass of the body */ 0172 Vector2d acceleration() const { return _force/_mass; } 0173 0174 /** Get angular acceleration of the body */ 0175 double angularAcceleration() const { return _torque/_inertia; } 0176 0177 /** Get force that acts upon the body */ 0178 const Vector2d& force() const { return _force; } 0179 /** Set force that acts upon the body */ 0180 void setForce(const Vector2d& force) { _force = force; } 0181 0182 /** Get torque that acts upon the body */ 0183 double torque() const { return _torque; } 0184 /** Set torque that acts upon the body */ 0185 void setTorque(double torque) { _torque = torque; } 0186 0187 //void applyForceLocal(const Vector2d& localPosition = Vector2d(0,0)); 0188 0189 /** Apply force (and torque) to the body at given position (in World coordinates) */ 0190 void applyForce(const Vector2d& force, const Vector2d& position); 0191 0192 /** Apply torque (but no force) to the body */ 0193 void applyTorque(double torque) { _torque += torque; } 0194 0195 /** Get mass of the body */ 0196 double mass() const { return _mass; } 0197 /** Set mass of the body */ 0198 void setMass(double mass) { _mass = mass; } 0199 0200 /** Get inertia "tensor" of the body */ 0201 double inertia() const { return _inertia; } 0202 /** Set inertia "tensor" of the body */ 0203 void setInertia(double inertia) { _inertia = inertia; } 0204 0205 /** Get momentum of the body */ 0206 Vector2d momentum() const { return _velocity * _mass; } 0207 /** Set momentum of the body (will modify only velocity) */ 0208 void setMomentum(const Vector2d& momentum) { _velocity = momentum / _mass; } 0209 0210 /** Get angular momentum of the body */ 0211 double angularMomentum() const { return _angularVelocity * _inertia; } 0212 /** Set angular momentum of the body (will modify only angularVelocity) */ 0213 void setAngularMomentum(double angularMomentum) { 0214 _angularVelocity = angularMomentum / _inertia; } 0215 0216 /** Get kinetic energy of the body */ 0217 double kineticEnergy() const { 0218 return _mass * _velocity.squaredNorm()/2 + _inertia * square(_angularVelocity)/2; } 0219 /** Set kinetic energy of the body (will modify only velocity and (possibly) angularVelocity) */ 0220 void setKineticEnergy(double kineticEnergy); 0221 0222 /** Translate local vector on body to world vector */ 0223 Vector2d vectorLocalToWorld(const Vector2d& v) const; 0224 /** Translate world vector to local vector on body */ 0225 Vector2d vectorWorldToLocal(const Vector2d& v) const; 0226 0227 /** Translate local coordinates on body to world coordinates */ 0228 Vector2d pointLocalToWorld(const Vector2d& p) const; 0229 /** Translate world coordinates to local coordinates on body */ 0230 Vector2d pointWorldToLocal(const Vector2d& p) const; 0231 0232 //---------- Integration over body 0233 0234 //---------- Shape 0235 // XXX 0236 //const Vector2dList& vertexes() const; 0237 0238 int variablesCount() override { return 3; } 0239 void getVariables(double* position, double* velocity, 0240 double* positionVariance, double* velocityVariance) override; 0241 void setVariables(const double* position, const double* velocity, 0242 const double* positionVariance, const double* velocityVariance) override; 0243 void addForce(const double* force, const double* forceVariance) override; 0244 void resetForce(bool resetVariance) override; 0245 void getAccelerations(double* acceleration, double* accelerationVariance) override; 0246 void getInverseMass(VectorXd* inverseMass, 0247 DynSparseRowMatrix* variance, int offset) override; 0248 /** Get (and possibly create) RigidBodyErrors object */ 0249 RigidBodyErrors* rigidBodyErrors() { 0250 return static_cast<RigidBodyErrors*>(objectErrors()); } 0251 0252 protected: 0253 ObjectErrors* createObjectErrors() override { return new RigidBodyErrors(this); } 0254 0255 Vector2d _position; 0256 double _angle; 0257 0258 Vector2d _velocity; 0259 double _angularVelocity; 0260 0261 Vector2d _force; 0262 double _torque; 0263 0264 double _mass; 0265 double _inertia; 0266 0267 friend class RigidBodyErrors; 0268 }; 0269 0270 /** \ingroup bodies 0271 * \brief Rigid disk 0272 */ 0273 class Disk: public RigidBody 0274 { 0275 STEPCORE_OBJECT(Disk) 0276 public: 0277 /** Constructs Disk */ 0278 explicit Disk(const Vector2d &position = Vector2d::Zero(), double angle = 0, 0279 const Vector2d &velocity = Vector2d::Zero(), double angularVelocity = 0, 0280 double mass = 1, double inertia = 1, double radius = 0.5) 0281 : RigidBody(position, angle, velocity, angularVelocity, mass, inertia), 0282 _radius(radius) {} 0283 0284 /** Get disk radius */ 0285 double radius() const { return _radius; } 0286 /** Set disk radius */ 0287 void setRadius(double radius) { _radius = radius; } 0288 0289 protected: 0290 double _radius; 0291 }; 0292 0293 /** \ingroup bodies 0294 * \brief Base class for all polygons 0295 */ 0296 class BasePolygon: public RigidBody 0297 { 0298 STEPCORE_OBJECT(BasePolygon) 0299 public: 0300 /** Constructs BasePolygon */ 0301 explicit BasePolygon(const Vector2d &position = Vector2d::Zero(), double angle = 0, 0302 const Vector2d &velocity = Vector2d::Zero(), double angularVelocity = 0, 0303 double mass = 1, double inertia = 1) 0304 : RigidBody(position, angle, velocity, angularVelocity, mass, inertia) {} 0305 0306 /** Get vertex list (constant) */ 0307 const Vector2dList& vertexes() const { return _vertexes; } 0308 0309 protected: 0310 Vector2dList _vertexes; 0311 }; 0312 0313 class Box: public BasePolygon 0314 { 0315 STEPCORE_OBJECT(Box) 0316 public: 0317 /** Constructs Box */ 0318 explicit Box(const Vector2d &position = Vector2d::Zero(), double angle = 0, 0319 const Vector2d &velocity = Vector2d::Zero(), double angularVelocity = 0, 0320 double mass = 1, double inertia = 1, const Vector2d &size = Vector2d(1,1)); 0321 0322 /** Get box size */ 0323 Vector2d size() const { return Vector2d(_vertexes[1][0] - _vertexes[0][0], 0324 _vertexes[3][1] - _vertexes[0][1]); } 0325 /** Set box size */ 0326 void setSize(const Vector2d& size); 0327 }; 0328 0329 /** \ingroup bodies 0330 * \brief Rigid arbitrary-shaped polygon 0331 */ 0332 class Polygon: public BasePolygon 0333 { 0334 STEPCORE_OBJECT(Polygon) 0335 0336 public: 0337 /** Get vertex list (constant) */ 0338 const Vector2dList& vertexes() const { return _vertexes; } 0339 /** Get vertex list (editable) */ 0340 Vector2dList& vertexes() { return _vertexes; } 0341 /** Set vertex list */ 0342 void setVertexes(const Vector2dList& vertexes) { _vertexes = vertexes; } 0343 }; 0344 0345 #if 0 0346 /** \ingroup bodies 0347 * \brief Unmovable rigid plane 0348 */ 0349 class Plane: public Body 0350 { 0351 STEPCORE_OBJECT(Plane) 0352 0353 public: 0354 /** Constructs a plane defined by two points */ 0355 explicit Plane(Vector2d point1 = Vector2d::Zero(), Vector2d point2 = Vector2d(1,0)) 0356 : _point1(point1), _point2(point2) {} 0357 0358 /** Get first point */ 0359 const Vector2d& point1() const { return _point1; } 0360 /** Set first point */ 0361 void setPoint1(const Vector2d& point1) { _point1 = point1; } 0362 0363 /** Get second point */ 0364 const Vector2d& point2() const { return _point2; } 0365 /** Set second point */ 0366 void setPoint2(const Vector2d& point2) { _point2 = point2; } 0367 0368 protected: 0369 Vector2d _point1; 0370 Vector2d _point2; 0371 }; 0372 #endif 0373 0374 } // namespace StepCore 0375 0376 #endif 0377