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: Rainer Gericke, Radu Serban
13 // =============================================================================
14 //
15 // Base class for a coil-spring or air-spring solid axle suspension.
16 // Derived from ChSuspension, but still an abstract base class.
17 //
18 // Non steerable solid axle guided by a triangular and two longitudinal links.
19 // Sprung by coil springs and translational dampers.
20 //
21 // The suspension subsystem is modeled with respect to a right-handed frame,
22 // with X pointing towards the front, Y to the left, and Z up (ISO standard).
23 // The suspension reference frame is assumed to be always aligned with that of
24 // the vehicle.  When attached to a chassis, only an offset is provided.
25 //
26 // All point locations are assumed to be given for the left half of the
27 // suspension and will be mirrored (reflecting the y coordinates) to construct
28 // the right side.
29 //
30 // =============================================================================
31 
32 #ifndef CH_SOLID_3LINK_AXLE_H
33 #define CH_SOLID_3LINK_AXLE_H
34 
35 #include <vector>
36 
37 #include "chrono/assets/ChColorAsset.h"
38 
39 #include "chrono_vehicle/ChApiVehicle.h"
40 #include "chrono_vehicle/wheeled_vehicle/ChSuspension.h"
41 
42 namespace chrono {
43 namespace vehicle {
44 
45 /// @addtogroup vehicle_wheeled_suspension
46 /// @{
47 
48 /// Base class for a coil-spring or air-spring solid axle suspension.
49 ///
50 /// The suspension subsystem is modeled with respect to a right-handed frame,
51 /// with X pointing towards the front, Y to the left, and Z up (ISO standard).
52 /// The suspension reference frame is assumed to be always aligned with that of
53 /// the vehicle.  When attached to a chassis, only an offset is provided.
54 ///
55 /// All point locations are assumed to be given for the left half of the
56 /// suspension and will be mirrored (reflecting the y coordinates) to construct
57 /// the right side.
58 class CH_VEHICLE_API ChSolidThreeLinkAxle : public ChSuspension {
59   public:
60     ChSolidThreeLinkAxle(const std::string& name  ///< [in] name of the subsystem
61     );
62 
63     virtual ~ChSolidThreeLinkAxle();
64 
65     /// Get the name of the vehicle subsystem template.
GetTemplateName()66     virtual std::string GetTemplateName() const override { return "SolidThreeLinkAxle"; }
67 
68     /// Specify whether or not this suspension can be steered.
IsSteerable()69     virtual bool IsSteerable() const final override { return false; }
70 
71     /// Specify whether or not this is an independent suspension.
IsIndependent()72     virtual bool IsIndependent() const final override { return false; }
73 
74     /// Initialize this suspension subsystem.
75     /// The suspension subsystem is initialized by attaching it to the specified chassis and (if provided) to the
76     /// specified subchassis, at the specified location (with respect to and expressed in the reference frame of the
77     /// chassis). It is assumed that the suspension reference frame is always aligned with the chassis reference frame.
78     /// Since this suspension is non-steerable, the steering subsystem is always ignored.
79     virtual void Initialize(
80         std::shared_ptr<ChChassis> chassis,        ///< [in] associated chassis subsystem
81         std::shared_ptr<ChSubchassis> subchassis,  ///< [in] associated subchassis subsystem (may be null)
82         std::shared_ptr<ChSteering> steering,      ///< [in] associated steering subsystem (may be null)
83         const ChVector<>& location,                ///< [in] location relative to the chassis frame
84         double left_ang_vel = 0,                   ///< [in] initial angular velocity of left wheel
85         double right_ang_vel = 0                   ///< [in] initial angular velocity of right wheel
86         ) override;
87 
88     /// Add visualization assets for the suspension subsystem.
89     /// This default implementation uses primitives.
90     virtual void AddVisualizationAssets(VisualizationType vis) override;
91 
92     /// Remove visualization assets for the suspension subsystem.
93     virtual void RemoveVisualizationAssets() override;
94 
95     /// Get the total mass of the suspension subsystem.
96     virtual double GetMass() const override;
97 
98     /// Get the current global COM location of the suspension subsystem.
99     virtual ChVector<> GetCOMPos() const override;
100 
101     /// Get the wheel track for the suspension subsystem.
102     virtual double GetTrack() override;
103 
104     /// Get a handle to the specified spring element.
GetSpring(VehicleSide side)105     std::shared_ptr<ChLinkTSDA> GetSpring(VehicleSide side) const { return m_spring[side]; }
106 
107     /// Get a handle to the specified shock (damper) element.
GetShock(VehicleSide side)108     std::shared_ptr<ChLinkTSDA> GetShock(VehicleSide side) const { return m_shock[side]; }
109 
110     /// Return current suspension forces (spring and shock) on the specified side.
111     virtual ChSuspension::Force ReportSuspensionForce(VehicleSide side) const override;
112 
113     /// Get the force in the spring element.
GetSpringForce(VehicleSide side)114     double GetSpringForce(VehicleSide side) const { return m_spring[side]->GetForce(); }
115 
116     /// Get the current length of the spring element
GetSpringLength(VehicleSide side)117     double GetSpringLength(VehicleSide side) const { return m_spring[side]->GetLength(); }
118 
119     /// Get the current deformation of the spring element.
GetSpringDeformation(VehicleSide side)120     double GetSpringDeformation(VehicleSide side) const { return m_spring[side]->GetDeformation(); }
121 
122     /// Get the force in the shock (damper) element.
GetShockForce(VehicleSide side)123     double GetShockForce(VehicleSide side) const { return m_shock[side]->GetForce(); }
124 
125     /// Get the current length of the shock (damper) element.
GetShockLength(VehicleSide side)126     double GetShockLength(VehicleSide side) const { return m_shock[side]->GetLength(); }
127 
128     /// Get the current deformation velocity of the shock (damper) element.
GetShockVelocity(VehicleSide side)129     double GetShockVelocity(VehicleSide side) const { return m_shock[side]->GetVelocity(); }
130 
131     /// Log current constraint violations.
132     virtual void LogConstraintViolations(VehicleSide side) override;
133 
134     void LogHardpointLocations(const ChVector<>& ref, bool inches = false);
135 
136   protected:
137     /// Identifiers for the various hardpoints.
138     enum PointId {
139         SHOCK_A,     ///< shock, axle
140         SHOCK_C,     ///< shock, chassis
141         SPRING_A,    ///< spring, axle
142         SPRING_C,    ///< spring, chassis
143         SPINDLE,     ///< spindle location
144         TRIANGLE_A,  ///< triangle link location on the axle (single point y = 0)
145         TRIANGLE_C,  ///< triangle link locationon the chassis (two points)
146         LINK_A,      ///< longitudinal link location on the axle (two points)
147         LINK_C,      ///< longitudinal link location on the chassis (two points)
148         NUM_POINTS
149     };
150 
151     /// Return the location of the specified hardpoint.
152     /// The returned location must be expressed in the suspension reference frame.
153     virtual const ChVector<> getLocation(PointId which) = 0;
154 
155     /// Return the center of mass of the axle tube.
156     virtual const ChVector<> getAxleTubeCOM() const = 0;
157 
158     /// Return the mass of the axle tube body.
159     virtual double getAxleTubeMass() const = 0;
160     /// Return the mass of the spindle body.
161     virtual double getSpindleMass() const = 0;
162     /// Return the mass of the triangle body.
163     virtual double getTriangleMass() const = 0;
164     /// Return the mass of the triangle body.
165     virtual double getLinkMass() const = 0;
166 
167     /// Return the radius of the axle tube body (visualization only).
168     virtual double getAxleTubeRadius() const = 0;
169 
170     /// Return the moments of inertia of the axle tube body.
171     virtual const ChVector<>& getAxleTubeInertia() const = 0;
172     /// Return the moments of inertia of the spindle body.
173     virtual const ChVector<>& getSpindleInertia() const = 0;
174     /// Return the moments of inertia of the triangle body.
175     virtual const ChVector<>& getTriangleInertia() const = 0;
176     /// Return the moments of inertia of the triangle body.
177     virtual const ChVector<>& getLinkInertia() const = 0;
178 
179     /// Return the inertia of the axle shaft.
180     virtual double getAxleInertia() const = 0;
181 
182     /// Return the free (rest) length of the spring element.
183     virtual double getSpringRestLength() const = 0;
184     /// Return the functor object for spring force.
185     virtual std::shared_ptr<ChLinkTSDA::ForceFunctor> getSpringForceFunctor() const = 0;
186     /// Return the functor object for shock force.
187     virtual std::shared_ptr<ChLinkTSDA::ForceFunctor> getShockForceFunctor() const = 0;
188 
189     std::shared_ptr<ChBody> m_axleTube;                  ///< handles to the axle tube body
190     // //std::shared_ptr<ChBody> m_tierod;                    ///< handles to the tierod body
191     // //std::shared_ptr<ChLinkLockFree> m_axleTubeGuide;     ///< allows all translations and rotations
192     std::shared_ptr<ChBody> m_triangleBody;              ///< axle guide body with spherical link and rotary link
193     std::shared_ptr<ChLinkLockRevolute> m_triangleRev;   ///< triangle to chassis revolute joint
194     std::shared_ptr<ChLinkLockSpherical> m_triangleSph;  ///< triangle to axle tube spherical joint
195 
196     std::shared_ptr<ChBody> m_linkBody[2];  ///< axle guide body with spherical link and universal link
197     std::shared_ptr<ChLinkUniversal> m_linkBodyToChassis[2];
198     std::shared_ptr<ChLinkLockSpherical> m_linkBodyToAxleTube[2];
199 
200     std::shared_ptr<ChLinkTSDA> m_shock[2];   ///< handles to the spring links (L/R)
201     std::shared_ptr<ChLinkTSDA> m_spring[2];  ///< handles to the shock links (L/R)
202 
203   private:
204     // Hardpoint absolute locations
205     std::vector<ChVector<>> m_pointsL;
206     std::vector<ChVector<>> m_pointsR;
207 
208     // Points for axle tube visualization
209     ChVector<> m_axleOuterL;
210     ChVector<> m_axleOuterR;
211 
212     // Points for triangle visualization
213     ChVector<> m_triangle_sph_point;
214     ChVector<> m_triangle_left_point;
215     ChVector<> m_triangle_right_point;
216 
217     // Points for link visualization
218     ChVector<> m_link_axleL;
219     ChVector<> m_link_axleR;
220     ChVector<> m_link_chassisL;
221     ChVector<> m_link_chassisR;
222 
223     // Points for tierod visualization
224     ChVector<> m_tierodOuterL;
225     ChVector<> m_tierodOuterR;
226 
227     void InitializeSide(VehicleSide side,
228                         std::shared_ptr<ChBodyAuxRef> chassis,
229                         std::shared_ptr<ChBody> scbeam,
230                         const std::vector<ChVector<>>& points,
231                         double ang_vel);
232 
233     static void AddVisualizationLink(std::shared_ptr<ChBody> body,
234                                      const ChVector<> pt_1,
235                                      const ChVector<> pt_2,
236                                      double radius,
237                                      const ChColor& color);
238 
239     virtual void ExportComponentList(rapidjson::Document& jsonDocument) const override;
240 
241     virtual void Output(ChVehicleOutput& database) const override;
242 
243     static const std::string m_pointNames[NUM_POINTS];
244 };
245 
246 /// @} vehicle_wheeled_suspension
247 
248 }  // end namespace vehicle
249 }  // end namespace chrono
250 
251 #endif
252