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: Radu Serban, Justin Madsen
13 // =============================================================================
14 //
15 // Base class for all suspension subsystems
16 //
17 // =============================================================================
18 
19 #ifndef CH_SUSPENSION_H
20 #define CH_SUSPENSION_H
21 
22 #include <string>
23 #include <vector>
24 
25 #include "chrono/physics/ChSystem.h"
26 #include "chrono/physics/ChShaft.h"
27 #include "chrono/physics/ChShaftsBody.h"
28 #include "chrono/assets/ChCylinderShape.h"
29 
30 #include "chrono_vehicle/ChApiVehicle.h"
31 #include "chrono_vehicle/ChChassis.h"
32 #include "chrono_vehicle/wheeled_vehicle/ChSubchassis.h"
33 #include "chrono_vehicle/wheeled_vehicle/ChSteering.h"
34 
35 namespace chrono {
36 namespace vehicle {
37 
38 /// @addtogroup vehicle_wheeled_suspension
39 /// @{
40 
41 /// Base class for a suspension subsystem.
42 class CH_VEHICLE_API ChSuspension : public ChPart {
43   public:
44     struct Force {
45         double spring_force;
46         double shock_force;
47         double spring_length;
48         double spring_velocity;
49         double shock_length;
50         double shock_velocity;
51     };
52 
53     ChSuspension(const std::string& name);
54 
55     virtual ~ChSuspension();
56 
57     /// Specify whether or not this suspension can be steered.
58     virtual bool IsSteerable() const = 0;
59 
60     /// Specify whether or not this is an independent suspension.
61     virtual bool IsIndependent() const = 0;
62 
63     /// Get the location of the suspension subsystem relative to the chassis reference frame.
64     /// The suspension reference frame is always aligned with the chassis reference frame.
GetLocation()65     const ChVector<>& GetLocation() const { return m_location; }
66 
67     /// Get a handle to the spindle body on the specified side.
GetSpindle(VehicleSide side)68     std::shared_ptr<ChBody> GetSpindle(VehicleSide side) const { return m_spindle[side]; }
69 
70     /// Get a handle to the axle shaft on the specified side.
GetAxle(VehicleSide side)71     std::shared_ptr<ChShaft> GetAxle(VehicleSide side) const { return m_axle[side]; }
72 
73     /// Get a handle to the revolute joint on the specified side.
GetRevolute(VehicleSide side)74     std::shared_ptr<ChLinkLockRevolute> GetRevolute(VehicleSide side) const { return m_revolute[side]; }
75 
76     /// Get the global location of the spindle on the specified side.
GetSpindlePos(VehicleSide side)77     const ChVector<>& GetSpindlePos(VehicleSide side) const { return m_spindle[side]->GetPos(); }
78 
79     /// Get the orientation of the spindle body on the specified side.
80     /// The spindle body orientation is returned as a quaternion representing a
81     /// rotation with respect to the global reference frame.
82     ChQuaternion<> GetSpindleRot(VehicleSide side) const;
83 
84     /// Get the linear velocity of the spindle body on the specified side.
85     /// Return the linear velocity of the spindle center, expressed in the global
86     /// reference frame.
GetSpindleLinVel(VehicleSide side)87     const ChVector<>& GetSpindleLinVel(VehicleSide side) const { return m_spindle[side]->GetPos_dt(); }
88 
89     /// Get the angular velocity of the spindle body on the specified side.
90     /// Return the angular velocity of the spindle frame, expressed in the global
91     /// reference frame.
GetSpindleAngVel(VehicleSide side)92     ChVector<> GetSpindleAngVel(VehicleSide side) const { return m_spindle[side]->GetWvel_par(); }
93 
94     /// Get the angular speed of the axle on the specified side.
GetAxleSpeed(VehicleSide side)95     double GetAxleSpeed(VehicleSide side) const { return m_axle[side]->GetPos_dt(); }
96 
97     /// Synchronize this suspension subsystem.
98     /// This function must be called before synchronizing any wheels associated with this suspension.
99     void Synchronize();
100 
101     /// Apply the provided motor torque.
102     /// The given torque is applied to the specified (left or right) axle. This
103     /// function provides the interface to the drivetrain subsystem (intermediated
104     /// by the vehicle system).
105     void ApplyAxleTorque(VehicleSide side,  ///< indicates the axle (left or right) where the torque should be applied
106                          double torque      ///< value of applied torque
107     );
108 
109     /// Initialize this suspension subsystem.
110     /// The suspension subsystem is initialized by attaching it to the specified chassis and (if provided) to the
111     /// specified subchassis, at the specified location (with respect to and expressed in the reference frame of the
112     /// chassis). It is assumed that the suspension reference frame is always aligned with the chassis reference frame.
113     /// If a steering subsystem is provided, the suspension tierods are to be attached to the steering's central link
114     /// body (steered suspension); otherwise they are to be attached to the chassis (non-steered suspension).
115     virtual void Initialize(
116         std::shared_ptr<ChChassis> chassis,        ///< [in] associated chassis subsystem
117         std::shared_ptr<ChSubchassis> subchassis,  ///< [in] associated subchassis subsystem (may be null)
118         std::shared_ptr<ChSteering> steering,      ///< [in] associated steering subsystem (may be null)
119         const ChVector<>& location,                ///< [in] location relative to the chassis frame
120         double left_ang_vel = 0,                   ///< [in] initial angular velocity of left wheel
121         double right_ang_vel = 0                   ///< [in] initial angular velocity of right wheel
122         ) = 0;
123 
124     /// Return the radius of the spindle body (visualization only).
125     virtual double getSpindleRadius() const = 0;
126 
127     /// Return the width of the spindle body (visualization only).
128     virtual double getSpindleWidth() const = 0;
129 
130     /// Add visualization assets for the suspension subsystem.
131     /// This default implementation uses primitives for spindle visualization.
132     virtual void AddVisualizationAssets(VisualizationType vis) override;
133 
134     /// Remove visualization assets for the suspension subsystem.
135     virtual void RemoveVisualizationAssets() override;
136 
137     /// Specify the suspension body on the specified side to attach a possible antirollbar subsystem.
138     /// The default implementation returns a NULL pointer.
GetAntirollBody(VehicleSide side)139     virtual std::shared_ptr<ChBody> GetAntirollBody(VehicleSide side) const { return nullptr; }
140 
141     /// Specify the body on the specified side for a possible connection to brake subsystem.
142     /// The default implementation returns a NULL pointer (indicating that a brake should connect to the chassis).
GetBrakeBody(VehicleSide side)143     virtual std::shared_ptr<ChBody> GetBrakeBody(VehicleSide side) const { return nullptr; }
144 
145     /// Get the total mass of the suspension subsystem.
146     virtual double GetMass() const = 0;
147 
148     /// Get the current global COM location of the suspension subsystem.
149     virtual ChVector<> GetCOMPos() const = 0;
150 
151     /// Get the wheel track for the suspension subsystem.
152     virtual double GetTrack() = 0;
153 
154     /// Return current suspension forces (spring and shock) on the specified side.
155     /// Different derived types (suspension templates) may load different quantities in the output struct.
156     virtual Force ReportSuspensionForce(VehicleSide side) const = 0;
157 
158     /// Log current constraint violations.
LogConstraintViolations(VehicleSide side)159     virtual void LogConstraintViolations(VehicleSide side) {}
160 
161     /// Simple model of a parking brake.
162     void ApplyParkingBrake(bool brake);
163 
164   protected:
165     ChVector<> m_location;                               ///< location relative to chassis
166     std::shared_ptr<ChBody> m_spindle[2];                ///< handles to spindle bodies
167     std::shared_ptr<ChShaft> m_axle[2];                  ///< handles to axle shafts
168     std::shared_ptr<ChShaftsBody> m_axle_to_spindle[2];  ///< handles to spindle-shaft connectors
169     std::shared_ptr<ChLinkLockRevolute> m_revolute[2];   ///< handles to spindle revolute joints
170 
171   private:
172     std::shared_ptr<ChCylinderShape> m_spindle_shapes[2];
173 
174     void AddVisualizationSpindle(VehicleSide side, double radius, double width);
175 };
176 
177 /// Vector of handles to suspension subsystems.
178 typedef std::vector<std::shared_ptr<ChSuspension> > ChSuspensionList;
179 
180 /// @} vehicle_wheeled_suspension
181 
182 }  // end namespace vehicle
183 }  // end namespace chrono
184 
185 #endif
186