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