1 // ============================================================================= 2 // PROJECT CHRONO - http://projectchrono.org 3 // 4 // Copyright (c) 2014 projectchrono.org 5 // All rights reserved. 6 // 7 // Use of this source code is governed by a BSD-style license that can be found 8 // in the LICENSE file at the top level of the distribution and at 9 // http://projectchrono.org/license-chrono.txt. 10 // 11 // ============================================================================= 12 // Authors: Alessandro Tasora, Radu Serban 13 // ============================================================================= 14 15 #ifndef CHBODY_H 16 #define CHBODY_H 17 18 #include <cmath> 19 20 #include "chrono/physics/ChBodyFrame.h" 21 #include "chrono/physics/ChContactable.h" 22 #include "chrono/physics/ChForce.h" 23 #include "chrono/physics/ChLoadable.h" 24 #include "chrono/physics/ChMarker.h" 25 #include "chrono/physics/ChPhysicsItem.h" 26 #include "chrono/collision/ChCollisionSystem.h" 27 #include "chrono/solver/ChConstraint.h" 28 #include "chrono/solver/ChVariablesBodyOwnMass.h" 29 30 namespace chrono { 31 32 // Forward references (for parent hierarchy pointer) 33 34 class ChSystem; 35 36 /// Class for rigid bodies. A rigid body is an entity which 37 /// can move in 3D space, and can be constrained to other rigid 38 /// bodies using ChLink objects. Rigid bodies can contain auxiliary 39 /// references (the ChMarker objects) and forces (the ChForce objects). 40 /// These objects have mass and inertia properties. A shape can also 41 /// be associated to the body, for collision detection. 42 /// 43 /// Further info at the @ref rigid_bodies manual page. 44 45 class ChApi ChBody : public ChPhysicsItem, public ChBodyFrame, public ChContactable_1vars<6>, public ChLoadableUVW { 46 public: 47 /// Build a rigid body. 48 ChBody(collision::ChCollisionSystemType collision_type = collision::ChCollisionSystemType::BULLET); 49 50 /// Build a rigid body with a different collision model. 51 ChBody(std::shared_ptr<collision::ChCollisionModel> new_collision_model); 52 53 ChBody(const ChBody& other); 54 55 /// Destructor 56 virtual ~ChBody(); 57 58 /// "Virtual" copy constructor (covariant return type). Clone()59 virtual ChBody* Clone() const override { return new ChBody(*this); } 60 61 // FLAGS 62 63 /// Sets the 'fixed' state of the body. If true, it does not move 64 /// respect to the absolute world, despite constraints, forces, etc. 65 void SetBodyFixed(bool state); 66 /// Return true if this body is fixed to ground. 67 bool GetBodyFixed() const; 68 69 /// If true, the normal restitution coefficient is evaluated from painted material channel. 70 void SetEvalContactCn(bool state); 71 bool GetEvalContactCn() const; 72 73 /// If true, the tangential restitution coefficient is evaluated from painted material channel. 74 void SetEvalContactCt(bool state); 75 bool GetEvalContactCt() const; 76 77 /// If true, the kinetic friction coefficient is evaluated from painted material channel. 78 void SetEvalContactKf(bool state); 79 bool GetEvalContactKf() const; 80 81 /// If true, the static friction coefficient is evaluated 82 /// from painted material channel. 83 void SetEvalContactSf(bool state); 84 bool GetEvalContactSf() const; 85 86 /// Enable/disable the collision for this rigid body. 87 /// before anim starts, if you added an external object 88 /// that implements onAddCollisionGeometries(), ex. in a plug-in for a CAD) 89 void SetCollide(bool state); 90 91 /// Return true if collision is enabled for this body. 92 virtual bool GetCollide() const override; 93 94 /// Show collision mesh in 3D views. 95 void SetShowCollisionMesh(bool state); 96 97 /// Return true if collision mesh is shown in 3D views. 98 bool GetShowCollisionMesh() const; 99 100 /// Enable the maximum linear speed limit (beyond this limit it will be clamped). 101 /// This is useful in virtual reality and real-time simulations, because 102 /// it reduces the risk of bad collision detection. 103 /// The realism is limited, but the simulation is more stable. 104 void SetLimitSpeed(bool state); 105 106 /// Return true if maximum linear speed is limited. 107 bool GetLimitSpeed() const; 108 109 /// Deactivate the gyroscopic torque (quadratic term). 110 /// This is useful in virtual reality and real-time 111 /// simulations, where objects that spin too fast with non-uniform inertia 112 /// tensors (ex thin cylinders) might cause the integration to diverge quickly. 113 /// The realism is limited, but the simulation is more stable. 114 void SetNoGyroTorque(bool state); 115 116 /// Return true if gyroscopic torque is deactivated. 117 bool GetNoGyroTorque() const; 118 119 /// Enable/disable option for setting bodies to "sleep". 120 /// If use sleeping = true, bodies which stay in same place 121 /// for long enough time will be deactivated, for optimization. 122 /// The realism is limited, but the simulation is faster. 123 void SetUseSleeping(bool state); 124 125 /// Return true if 'sleep' mode is activated. 126 bool GetUseSleeping() const; 127 128 /// Force the body in sleeping mode or not (usually this state change is not 129 /// handled by users, anyway, because it is mostly automatic). 130 void SetSleeping(bool state); 131 132 /// Return true if this body is currently in 'sleep' mode. 133 bool GetSleeping() const; 134 135 /// Test if a body could go in sleeping state if requirements are satisfied. 136 /// Return true if state could be changed from no sleep to sleep. 137 bool TrySleeping(); 138 139 /// Return true if the body is active; i.e. it is neither fixed to ground 140 /// nor is it in "sleep" mode. Return false otherwise. 141 bool IsActive(); 142 143 /// Set body id for indexing (internal use only) SetId(int id)144 void SetId(int id) { body_id = id; } 145 146 /// Set body id for indexing (internal use only) GetId()147 unsigned int GetId() { return body_id; } 148 149 /// Set global body index (internal use only) SetGid(unsigned int id)150 void SetGid(unsigned int id) { body_gid = id; } 151 152 /// Get the global body index (internal use only) GetGid()153 unsigned int GetGid() const { return body_gid; } 154 155 // FUNCTIONS 156 157 /// Number of coordinates of body: 7 because uses quaternions for rotation. GetDOF()158 virtual int GetDOF() override { return 7; } 159 160 /// Number of coordinates of body: 6 because derivatives use angular velocity. GetDOF_w()161 virtual int GetDOF_w() override { return 6; } 162 163 /// Return a reference to the encapsulated ChVariablesBody, representing states (pos, speed, or accel.) and forces. 164 /// The ChVariablesBodyOwnMass is the interface to the system solver. Variables()165 virtual ChVariables& Variables() override { return variables; } 166 167 /// Set no speed and no accelerations (but does not change the position) 168 void SetNoSpeedNoAcceleration() override; 169 170 /// Change the collision model. 171 void SetCollisionModel(std::shared_ptr<collision::ChCollisionModel> new_collision_model); 172 173 /// Access the collision model for the collision engine. 174 /// To get a non-null pointer, remember to SetCollide(true), before. GetCollisionModel()175 std::shared_ptr<collision::ChCollisionModel> GetCollisionModel() { return collision_model; } 176 177 /// Synchronize coll.model coordinate and bounding box to the position of the body. 178 virtual void SyncCollisionModels() override; 179 virtual void AddCollisionModelsToSystem() override; 180 virtual void RemoveCollisionModelsFromSystem() override; 181 182 /// Get the rigid body coordinate system that represents 183 /// the GOG (Center of Gravity). The mass and inertia tensor 184 /// are defined respect to this coordinate system, that is also 185 /// assumed the default main coordinates of the body. 186 /// By default, doing mybody.GetPos() etc. is like mybody.GetFrame_COG_abs().GetPos() etc. GetFrame_COG_to_abs()187 virtual const ChFrameMoving<>& GetFrame_COG_to_abs() const { return *this; } 188 189 /// Get the rigid body coordinate system that is used for 190 /// defining the collision shapes and the ChMarker objects. 191 /// For the base ChBody, this is always the same reference of the COG. GetFrame_REF_to_abs()192 virtual const ChFrameMoving<>& GetFrame_REF_to_abs() const { return *this; } 193 194 /// Get the master coordinate system for the assets (this will return the 195 /// main coordinate system of the rigid body) 196 virtual ChFrame<> GetAssetsFrame(unsigned int nclone = 0) override { return (GetFrame_REF_to_abs()); } 197 198 /// Get the entire AABB axis-aligned bounding box of the object, 199 /// as defined by the collision model (if any). 200 virtual void GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax) override; 201 202 /// Method to deserialize only the state (position, speed) 203 virtual void StreamINstate(ChStreamInBinary& mstream) override; 204 205 /// Method to serialize only the state (position, speed) 206 virtual void StreamOUTstate(ChStreamOutBinary& mstream) override; 207 208 /// The density of the rigid body, as [mass]/[unit volume]. Used just if 209 /// the inertia tensor and mass are automatically recomputed from the 210 /// geometry (in case a CAD plugin for example provides the surfaces.) 211 // float GetDensity() const { return density; } // obsolete, use the base ChLoadable::GetDensity() SetDensity(float mdensity)212 void SetDensity(float mdensity) { density = mdensity; } 213 214 // DATABASE HANDLING. 215 // 216 // To attach/remove items (rigid bodies, links, etc.) you must use 217 // shared pointer, so that you don't need to care about item deletion, 218 // which will be automatic when needed. 219 // Please don't add the same item multiple times; also, don't remove 220 // items which haven't ever been added. 221 222 /// Attach a marker to this body. 223 void AddMarker(std::shared_ptr<ChMarker> amarker); 224 /// Attach a force to this body. 225 void AddForce(std::shared_ptr<ChForce> aforce); 226 227 /// Remove a specific marker from this body. Warning: linear time search. 228 void RemoveMarker(std::shared_ptr<ChMarker> amarker); 229 /// Remove a specific force from this body. Warning: linear time search. 230 void RemoveForce(std::shared_ptr<ChForce> aforce); 231 232 /// Remove all markers at once. Faster than doing multiple RemoveForce() 233 /// Don't care about deletion: it is automatic, only when needed. 234 void RemoveAllForces(); 235 /// Remove all markers at once. Faster than doing multiple RemoveForce() 236 /// Don't care about deletion: it is automatic, only when needed. 237 void RemoveAllMarkers(); 238 239 /// Finds a marker from its ChObject name 240 std::shared_ptr<ChMarker> SearchMarker(const char* m_name); 241 /// Finds a force from its ChObject name 242 std::shared_ptr<ChForce> SearchForce(const char* m_name); 243 244 /// Gets the list of children markers. 245 /// NOTE: to modify this list, use the appropriate Remove.. 246 /// and Add.. functions. GetMarkerList()247 const std::vector<std::shared_ptr<ChMarker>>& GetMarkerList() const { return marklist; } 248 249 /// Gets the list of children forces. 250 /// NOTE: to modify this list, use the appropriate Remove.. 251 /// and Add.. functions. GetForceList()252 const std::vector<std::shared_ptr<ChForce>>& GetForceList() const { return forcelist; } 253 254 // Point/vector transf.(NOTE! you may also use operators of ChMovingFrame) 255 256 ChVector<> Point_World2Body(const ChVector<>& mpoint); 257 ChVector<> Point_Body2World(const ChVector<>& mpoint); 258 ChVector<> Dir_World2Body(const ChVector<>& dir); 259 ChVector<> Dir_Body2World(const ChVector<>& dir); 260 ChVector<> RelPoint_AbsSpeed(const ChVector<>& mrelpoint); 261 ChVector<> RelPoint_AbsAcc(const ChVector<>& mrelpoint); 262 263 /// Set the body mass. 264 /// Try not to mix bodies with too high/too low values of mass, for numerical stability. SetMass(double newmass)265 void SetMass(double newmass) { 266 if (newmass > 0.) 267 variables.SetBodyMass(newmass); 268 } 269 270 /// Get the body mass. GetMass()271 double GetMass() { return variables.GetBodyMass(); } 272 273 /// Set the inertia tensor of the body. 274 /// The provided 3x3 matrix should be symmetric and contain the inertia tensor, expressed in the local coordinate 275 /// system: 276 /// <pre> 277 /// [ int{y^2+z^2}dm -int{xy}dm -int{xz}dm ] 278 /// newXInertia = [ int{x^2+z^2} -int{yz}dm ] 279 /// [ int{x^2+y^2}dm ] 280 /// </pre> 281 void SetInertia(const ChMatrix33<>& newXInertia); 282 283 /// Get the inertia tensor, expressed in the local coordinate system. 284 /// The return 3x3 symmetric matrix contains the following values: 285 /// <pre> 286 /// [ int{y^2+z^2}dm -int{xy}dm -int{xz}dm ] 287 /// [ int{x^2+z^2} -int{yz}dm ] 288 /// [ int{x^2+y^2}dm ] 289 /// </pre> GetInertia()290 const ChMatrix33<>& GetInertia() const { return variables.GetBodyInertia(); } 291 292 /// Get the inverse of the inertia matrix. GetInvInertia()293 const ChMatrix33<>& GetInvInertia() const { return variables.GetBodyInvInertia(); } 294 295 /// Set the diagonal part of the inertia tensor (Ixx, Iyy, Izz values). 296 /// The provided 3x1 vector should contain the moments of inertia, expressed in the local coordinate frame: 297 /// <pre> 298 /// iner = [ int{y^2+z^2}dm int{x^2+z^2} int{x^2+y^2}dm ] 299 /// </pre> 300 void SetInertiaXX(const ChVector<>& iner); 301 302 /// Get the diagonal part of the inertia tensor (Ixx, Iyy, Izz values). 303 /// The return 3x1 vector contains the following values: 304 /// <pre> 305 /// [ int{y^2+z^2}dm int{x^2+z^2} int{x^2+y^2}dm ] 306 /// </pre> 307 ChVector<> GetInertiaXX() const; 308 309 /// Set the off-diagonal part of the inertia tensor (Ixy, Ixz, Iyz values). 310 /// The provided 3x1 vector should contain the products of inertia, 311 /// expressed in the local coordinate frame: 312 /// <pre> 313 /// iner = [ -int{xy}dm -int{xz}dm -int{yz}dm ] 314 /// </pre> 315 void SetInertiaXY(const ChVector<>& iner); 316 317 /// Get the extra-diagonal part of the inertia tensor (Ixy, Ixz, Iyz values). 318 /// The return 3x1 vector contains the following values: 319 /// <pre> 320 /// [ -int{xy}dm -int{xz}dm -int{yz}dm ] 321 /// </pre> 322 ChVector<> GetInertiaXY() const; 323 324 /// Set the maximum linear speed (beyond this limit it will be clamped). 325 /// This is useful in virtual reality and real-time simulations, because 326 /// it reduces the risk of bad collision detection. 327 /// This speed limit is active only if you set SetLimitSpeed(true); SetMaxSpeed(float m_max_speed)328 void SetMaxSpeed(float m_max_speed) { max_speed = m_max_speed; } GetMaxSpeed()329 float GetMaxSpeed() const { return max_speed; } 330 331 /// Set the maximum angular speed (beyond this limit it will be clamped). 332 /// This is useful in virtual reality and real-time simulations, because 333 /// it reduces the risk of bad collision detection. 334 /// This speed limit is active only if you set SetLimitSpeed(true); SetMaxWvel(float m_max_wvel)335 void SetMaxWvel(float m_max_wvel) { max_wvel = m_max_wvel; } GetMaxWvel()336 float GetMaxWvel() const { return max_wvel; } 337 338 /// Clamp the body speed to the provided limits. 339 /// When this function is called, the speed of the body is clamped 340 /// to the range specified by max_speed and max_wvel. Remember to 341 /// put the body in the SetLimitSpeed(true) mode. 342 void ClampSpeed(); 343 344 /// Set the amount of time which must pass before going automatically in 345 /// sleep mode when the body has very small movements. SetSleepTime(float m_t)346 void SetSleepTime(float m_t) { sleep_time = m_t; } GetSleepTime()347 float GetSleepTime() const { return sleep_time; } 348 349 /// Set the max linear speed to be kept for 'sleep_time' before freezing. SetSleepMinSpeed(float m_t)350 void SetSleepMinSpeed(float m_t) { sleep_minspeed = m_t; } GetSleepMinSpeed()351 float GetSleepMinSpeed() const { return sleep_minspeed; } 352 353 /// Set the max linear speed to be kept for 'sleep_time' before freezing. SetSleepMinWvel(float m_t)354 void SetSleepMinWvel(float m_t) { sleep_minwvel = m_t; } GetSleepMinWvel()355 float GetSleepMinWvel() const { return sleep_minwvel; } 356 357 /// Computes the 4x4 inertia tensor in quaternion space, if needed. 358 void ComputeQInertia(ChMatrix44<>& mQInertia); 359 360 /// Computes the gyroscopic torque. In fact, in sake of highest 361 /// speed, the gyroscopic torque isn't automatically updated each time a 362 /// SetCoord() or SetCoord_dt() etc. is called, but only if necessary, 363 /// for each UpdateState(). 364 void ComputeGyro(); 365 366 // UTILITIES FOR FORCES/TORQUES: 367 368 /// Add an applied force to the body's accumulator (as an increment). 369 /// It is the caller's responsibility to clear the force and torque accumulators at each integration step. 370 /// If local = true, the provided applied force is assumed to be expressed in body coordinates. 371 /// If local = false, the provided applied force is assumed to be expressed in absolute coordinates. 372 void Accumulate_force(const ChVector<>& force, ///< applied force 373 const ChVector<>& appl_point, ///< application point 374 bool local ///< force and point expressed in body local frame? 375 ); 376 377 /// Add an applied torque to the body's accumulator (as an increment). 378 /// It is the caller's responsibility to clear the force and torque accumulators at each integration step. 379 /// If local = true, the provided applied torque is assumed to be expressed in body coordinates. 380 /// If local = false, the provided applied torque is assumed to be expressed in absolute coordinates. 381 void Accumulate_torque(const ChVector<>& torque, ///< applied torque 382 bool local ///< torque expressed in body local frame? 383 ); 384 385 /// Clear the force and torque accumulators. 386 void Empty_forces_accumulators(); 387 388 /// Return the current value of the accumulator force. 389 /// Note that this is a resultant force as applied to the COM and expressed in the absolute frame. Get_accumulated_force()390 const ChVector<>& Get_accumulated_force() const { return Force_acc; } 391 392 /// Return the current value of the accumulator torque. 393 /// Note that this is a resultant torque expressed in the body local frame. Get_accumulated_torque()394 const ChVector<>& Get_accumulated_torque() const { return Torque_acc; } 395 396 // UPDATE FUNCTIONS 397 398 /// Update all children markers of the rigid body, at current body state 399 void UpdateMarkers(double mytime); 400 /// Update all children forces of the rigid body, at current body state. 401 void UpdateForces(double mytime); 402 /// Update local time of rigid body, and time-dependent data 403 void UpdateTime(double mytime); 404 405 /// Update all auxiliary data of the rigid body and of 406 /// its children (markers, forces..), at given time 407 virtual void Update(double mytime, bool update_assets = true) override; 408 /// Update all auxiliary data of the rigid body and of 409 /// its children (markers, forces..) 410 virtual void Update(bool update_assets = true) override; 411 412 /// Return the resultant applied force on the body. 413 /// This resultant force includes all external applied loads acting on this body (from gravity, loads, springs, 414 /// etc). However, this does *not* include any constraint forces. In particular, contact forces are not included if 415 /// using the NSC formulation, but are included when using the SMC formulation. 416 ChVector<> GetAppliedForce(); 417 418 /// Return the resultant applied torque on the body. 419 /// This resultant torque includes all external applied loads acting on this body (from gravity, loads, springs, 420 /// etc). However, this does *not* include any constraint forces. In particular, contact torques are not included if 421 /// using the NSC formulation, but are included when using the SMC formulation. 422 ChVector<> GetAppliedTorque(); 423 424 /// Get the resultant contact force acting on this body. 425 ChVector<> GetContactForce(); 426 427 /// Get the resultant contact torque acting on this body. 428 ChVector<> GetContactTorque(); 429 430 /// This is only for backward compatibility GetPhysicsItem()431 virtual ChPhysicsItem* GetPhysicsItem() override { return this; } 432 433 // SERIALIZATION 434 435 /// Method to allow serialization of transient data to archives. 436 virtual void ArchiveOUT(ChArchiveOut& marchive) override; 437 438 /// Method to allow deserialization of transient data from archives. 439 virtual void ArchiveIN(ChArchiveIn& marchive) override; 440 441 public: 442 // Public functions for ADVANCED use. 443 // For example, access to these methods may be needed in implementing custom loads 444 445 /// Get the pointers to the contained ChVariables, appending to the mvars vector. 446 virtual void LoadableGetVariables(std::vector<ChVariables*>& mvars) override; 447 448 /// Increment all DOFs using a delta. 449 virtual void LoadableStateIncrement(const unsigned int off_x, 450 ChState& x_new, 451 const ChState& x, 452 const unsigned int off_v, 453 const ChStateDelta& Dv) override; 454 455 /// Gets all the DOFs packed in a single vector (position part) 456 virtual void LoadableGetStateBlock_x(int block_offset, ChState& mD) override; 457 458 /// Gets all the DOFs packed in a single vector (speed part) 459 virtual void LoadableGetStateBlock_w(int block_offset, ChStateDelta& mD) override; 460 461 /// Evaluate Q=N'*F, for Q generalized lagrangian load, where N is some type of matrix evaluated at point P(U,V,W) 462 /// assumed in absolute coordinates, and F is a load assumed in absolute coordinates. det[J] is unused. 463 virtual void ComputeNF( 464 const double U, ///< x coordinate of application point in absolute space 465 const double V, ///< y coordinate of application point in absolute space 466 const double W, ///< z coordinate of application point in absolute space 467 ChVectorDynamic<>& Qi, ///< Return result of N'*F here, maybe with offset block_offset 468 double& detJ, ///< Return det[J] here 469 const ChVectorDynamic<>& F, ///< Input F vector, size is 6, it is {Force,Torque} in absolute coords. 470 ChVectorDynamic<>* state_x, ///< if != 0, update state (pos. part) to this, then evaluate Q 471 ChVectorDynamic<>* state_w ///< if != 0, update state (speed part) to this, then evaluate Q 472 ) override; 473 474 protected: 475 std::shared_ptr<collision::ChCollisionModel> collision_model; ///< pointer to the collision model 476 477 unsigned int body_id; ///< body-specific identifier, used for indexing (internal use only) 478 unsigned int body_gid; ///< body-specific identifier, used for global indexing (internal use only) 479 480 std::vector<std::shared_ptr<ChMarker>> marklist; ///< list of markers 481 std::vector<std::shared_ptr<ChForce>> forcelist; ///< list of forces 482 483 ChVector<> gyro; ///< gyroscopic torque, i.e. Qm = Wvel x (XInertia*Wvel) 484 485 ChVector<> Xforce; ///< force acting on body, applied to COM (in absolute coords) 486 ChVector<> Xtorque; ///< torque acting on body (in body local coords) 487 488 ChVector<> Force_acc; ///< force accumulator, applied to COM (in absolute coords) 489 ChVector<> Torque_acc; ///< torque accumulator (in body local coords) 490 491 float density; ///< used when doing the 'recompute mass' operation. 492 493 ChVariablesBodyOwnMass variables; ///< interface to solver (store inertia and coordinates) 494 495 float max_speed; ///< limit on linear speed 496 float max_wvel; ///< limit on angular velocity 497 498 float sleep_time; 499 float sleep_minspeed; 500 float sleep_minwvel; 501 float sleep_starttime; 502 503 private: 504 // STATE FUNCTIONS 505 506 // (override/implement interfaces for global state vectors, see ChPhysicsItem for comments.) 507 508 virtual void IntStateGather(const unsigned int off_x, 509 ChState& x, 510 const unsigned int off_v, 511 ChStateDelta& v, 512 double& T) override; 513 virtual void IntStateScatter(const unsigned int off_x, 514 const ChState& x, 515 const unsigned int off_v, 516 const ChStateDelta& v, 517 const double T, 518 bool full_update) override; 519 virtual void IntStateGatherAcceleration(const unsigned int off_a, ChStateDelta& a) override; 520 virtual void IntStateScatterAcceleration(const unsigned int off_a, const ChStateDelta& a) override; 521 virtual void IntStateIncrement(const unsigned int off_x, 522 ChState& x_new, 523 const ChState& x, 524 const unsigned int off_v, 525 const ChStateDelta& Dv) override; 526 virtual void IntLoadResidual_F(const unsigned int off, ChVectorDynamic<>& R, const double c) override; 527 virtual void IntLoadResidual_Mv(const unsigned int off, 528 ChVectorDynamic<>& R, 529 const ChVectorDynamic<>& w, 530 const double c) override; 531 virtual void IntToDescriptor(const unsigned int off_v, 532 const ChStateDelta& v, 533 const ChVectorDynamic<>& R, 534 const unsigned int off_L, 535 const ChVectorDynamic<>& L, 536 const ChVectorDynamic<>& Qc) override; 537 virtual void IntFromDescriptor(const unsigned int off_v, 538 ChStateDelta& v, 539 const unsigned int off_L, 540 ChVectorDynamic<>& L) override; 541 542 // SOLVER FUNCTIONS 543 544 // Override/implement solver system functions of ChPhysicsItem 545 // (to assemble/manage data for system solver) 546 547 /// Sets the 'fb' part of the encapsulated ChVariablesBodyOwnMass to zero. 548 virtual void VariablesFbReset() override; 549 550 /// Adds the current forces applied to body (including gyroscopic torque) in 551 /// encapsulated ChVariablesBody, in the 'fb' part: qf+=forces*factor 552 virtual void VariablesFbLoadForces(double factor = 1) override; 553 554 /// Initialize the 'qb' part of the ChVariablesBody with the 555 /// current value of body speeds. Note: since 'qb' is the unknown, this 556 /// function seems unnecessary, unless used before VariablesFbIncrementMq() 557 virtual void VariablesQbLoadSpeed() override; 558 559 /// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized 560 /// with v_old using VariablesQbLoadSpeed, this method can be used in 561 /// timestepping schemes that do: M*v_new = M*v_old + forces*dt 562 virtual void VariablesFbIncrementMq() override; 563 564 /// Fetches the body speed (both linear and angular) from the 565 /// 'qb' part of the ChVariablesBody (does not updates the full body&markers state) 566 /// and sets it as the current body speed. 567 /// If 'step' is not 0, also computes the approximate acceleration of 568 /// the body using backward differences, that is accel=(new_speed-old_speed)/step. 569 /// Mostly used after the solver provided the solution in ChVariablesBody . 570 virtual void VariablesQbSetSpeed(double step = 0) override; 571 572 /// Increment body position by the 'qb' part of the ChVariablesBody, 573 /// multiplied by a 'step' factor. 574 /// pos+=qb*step 575 /// If qb is a speed, this behaves like a single step of 1-st order 576 /// numerical integration (Eulero integration). 577 /// Does not automatically update markers & forces. 578 virtual void VariablesQbIncrementPosition(double step) override; 579 580 /// Tell to a system descriptor that there are variables of type 581 /// ChVariables in this object (for further passing it to a solver) 582 virtual void InjectVariables(ChSystemDescriptor& mdescriptor) override; 583 584 // INTERFACE TO ChContactable 585 GetContactableType()586 virtual ChContactable::eChContactableType GetContactableType() const override { return CONTACTABLE_6; } 587 GetVariables1()588 virtual ChVariables* GetVariables1() override { return &this->variables; } 589 590 /// Indicate whether or not the object must be considered in collision detection. IsContactActive()591 virtual bool IsContactActive() override { return this->IsActive(); } 592 593 /// Get the number of DOFs affected by this object (position part) ContactableGet_ndof_x()594 virtual int ContactableGet_ndof_x() override { return 7; } 595 596 /// Get the number of DOFs affected by this object (speed part) ContactableGet_ndof_w()597 virtual int ContactableGet_ndof_w() override { return 6; } 598 599 /// Get all the DOFs packed in a single vector (position part) 600 virtual void ContactableGetStateBlock_x(ChState& x) override; 601 602 /// Get all the DOFs packed in a single vector (speed part) 603 virtual void ContactableGetStateBlock_w(ChStateDelta& w) override; 604 605 /// Increment the provided state of this object by the given state-delta increment. 606 /// Compute: x_new = x + dw. 607 virtual void ContactableIncrementState(const ChState& x, const ChStateDelta& dw, ChState& x_new) override; 608 609 /// Express the local point in absolute frame, for the given state position. 610 virtual ChVector<> GetContactPoint(const ChVector<>& loc_point, const ChState& state_x) override; 611 612 /// Get the absolute speed of a local point attached to the contactable. 613 /// The given point is assumed to be expressed in the local frame of this object. 614 /// This function must use the provided states. 615 virtual ChVector<> GetContactPointSpeed(const ChVector<>& loc_point, 616 const ChState& state_x, 617 const ChStateDelta& state_w) override; 618 619 /// Get the absolute speed of point abs_point if attached to the surface. 620 virtual ChVector<> GetContactPointSpeed(const ChVector<>& abs_point) override; 621 622 /// Return the coordinate system for the associated collision model. 623 /// ChCollisionModel might call this to get the position of the 624 /// contact model (when rigid) and sync it. 625 virtual ChCoordsys<> GetCsysForCollisionModel() override; 626 627 /// Apply the force, expressed in absolute reference, applied in pos, to the 628 /// coordinates of the variables. Force for example could come from a penalty model. 629 virtual void ContactForceLoadResidual_F(const ChVector<>& F, 630 const ChVector<>& abs_point, 631 ChVectorDynamic<>& R) override; 632 633 /// Apply the given force at the given point and load the generalized force array. 634 /// The force and its application point are specified in the global frame. 635 /// Each object must set the entries in Q corresponding to its variables, starting at the specified offset. 636 /// If needed, the object states must be extracted from the provided state position. 637 virtual void ContactForceLoadQ(const ChVector<>& F, 638 const ChVector<>& point, 639 const ChState& state_x, 640 ChVectorDynamic<>& Q, 641 int offset) override; 642 643 /// Compute the jacobian(s) part(s) for this contactable item. 644 /// For a ChBody, this updates the corresponding 1x6 jacobian. 645 virtual void ComputeJacobianForContactPart(const ChVector<>& abs_point, 646 ChMatrix33<>& contact_plane, 647 ChVariableTupleCarrier_1vars<6>::type_constraint_tuple& jacobian_tuple_N, 648 ChVariableTupleCarrier_1vars<6>::type_constraint_tuple& jacobian_tuple_U, 649 ChVariableTupleCarrier_1vars<6>::type_constraint_tuple& jacobian_tuple_V, 650 bool second) override; 651 652 /// Compute the jacobian(s) part(s) for this contactable item, for rolling about N,u,v. 653 /// Used only for rolling friction NSC contacts. 654 virtual void ComputeJacobianForRollingContactPart( 655 const ChVector<>& abs_point, 656 ChMatrix33<>& contact_plane, 657 ChVariableTupleCarrier_1vars<6>::type_constraint_tuple& jacobian_tuple_N, 658 ChVariableTupleCarrier_1vars<6>::type_constraint_tuple& jacobian_tuple_U, 659 ChVariableTupleCarrier_1vars<6>::type_constraint_tuple& jacobian_tuple_V, 660 bool second) override; 661 662 /// Used by some SMC code GetContactableMass()663 virtual double GetContactableMass() override { return this->GetMass(); } 664 665 // INTERFACE to ChLoadable 666 667 /// Gets the number of DOFs affected by this element (position part) LoadableGet_ndof_x()668 virtual int LoadableGet_ndof_x() override { return 7; } 669 670 /// Gets the number of DOFs affected by this element (speed part) LoadableGet_ndof_w()671 virtual int LoadableGet_ndof_w() override { return 6; } 672 673 /// Number of coordinates in the interpolated field. Here, 6: = xyz displ + xyz rots. Get_field_ncoords()674 virtual int Get_field_ncoords() override { return 6; } 675 676 /// Tell the number of DOFs blocks. GetSubBlocks()677 virtual int GetSubBlocks() override { return 1; } 678 679 /// Get the offset of the specified sub-block of DOFs in global vector. GetSubBlockOffset(int nblock)680 virtual unsigned int GetSubBlockOffset(int nblock) override { return GetOffset_w(); } 681 682 /// Get the size of the specified sub-block of DOFs in global vector. GetSubBlockSize(int nblock)683 virtual unsigned int GetSubBlockSize(int nblock) override { return 6; } 684 685 /// Check if the specified sub-block of DOFs is active. IsSubBlockActive(int nblock)686 virtual bool IsSubBlockActive(int nblock) const override { return true; } 687 688 /// This is not needed because not used in quadrature. GetDensity()689 virtual double GetDensity() override { return density; } 690 691 /// Bit flags 692 enum BodyFlag { 693 COLLIDE = (1L << 0), // detects collisions 694 CDINVISIBLE = (1L << 1), // collision detection invisible 695 EVAL_CONTACT_CN = (1L << 2), // evaluate CONTACT_CN channel (normal restitution) 696 EVAL_CONTACT_CT = (1L << 3), // evaluate CONTACT_CT channel (tangential rest.) 697 EVAL_CONTACT_KF = (1L << 4), // evaluate CONTACT_KF channel (kinetic friction coeff) 698 EVAL_CONTACT_SF = (1L << 5), // evaluate CONTACT_SF channel (static friction coeff) 699 SHOW_COLLMESH = (1L << 6), // show collision mesh - obsolete 700 FIXED = (1L << 7), // body is fixed to ground 701 LIMITSPEED = (1L << 8), // body angular and linear speed is limited (clamped) 702 SLEEPING = (1L << 9), // body is sleeping [internal] 703 USESLEEPING = (1L << 10), // if body remains in same place for too long time, it will be frozen 704 NOGYROTORQUE = (1L << 11), // do not get the gyroscopic (quadratic) term, for low-fi but stable simulation 705 COULDSLEEP = (1L << 12) // if body remains in same place for too long time, it will be frozen 706 }; 707 708 int bflags; ///< encoding for all body flags 709 710 /// Flags handling functions 711 void BFlagsSetAllOFF(); 712 void BFlagsSetAllON(); 713 void BFlagSetON(BodyFlag mask); 714 void BFlagSetOFF(BodyFlag mask); 715 void BFlagSet(BodyFlag mask, bool state); 716 bool BFlagGet(BodyFlag mask) const; 717 718 // Give private access 719 friend class ChSystem; 720 friend class ChSystemMulticore; 721 friend class ChSystemMulticoreNSC; 722 friend class ChAssembly; 723 friend class ChConveyor; 724 }; 725 726 CH_CLASS_VERSION(ChBody, 0) 727 728 const int BODY_DOF = 6; ///< degrees of freedom of body in 3d space 729 const int BODY_QDOF = 7; ///< degrees of freedom with quaternion rotation state 730 const int BODY_ROT = 3; ///< rotational dof in Newton dynamics 731 732 } // end namespace chrono 733 734 #endif 735