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
13 // =============================================================================
14 //
15 // Base class for a semi-trailing arm suspension (non-steerable).
16 // Derived from ChSuspension, but still an abstract base class.
17 //
18 // The suspension subsystem is modeled with respect to a right-handed frame,
19 // with X pointing towards the front, Y to the left, and Z up (ISO standard).
20 // The suspension reference frame is assumed to be always aligned with that of
21 // the vehicle.  When attached to a chassis, only an offset is provided.
22 //
23 // All point locations are assumed to be given for the left half of the
24 // suspension and will be mirrored (reflecting the y coordinates) to construct
25 // the right side.
26 //
27 // =============================================================================
28 
29 #ifndef CH_SEMITRAILINGARM_H
30 #define CH_SEMITRAILINGARM_H
31 
32 #include <vector>
33 
34 #include "chrono_vehicle/ChApiVehicle.h"
35 #include "chrono_vehicle/wheeled_vehicle/ChSuspension.h"
36 
37 namespace chrono {
38 namespace vehicle {
39 
40 /// @addtogroup vehicle_wheeled_suspension
41 /// @{
42 
43 /// Base class for a semi-trailing arm suspension (non-steerable).
44 /// Derived from ChSuspension, but still an abstract base class.
45 ///
46 /// The suspension subsystem is modeled with respect to a right-handed frame,
47 /// with X pointing towards the front, Y to the left, and Z up (ISO standard).
48 /// The suspension reference frame is assumed to be always aligned with that of
49 /// the vehicle.  When attached to a chassis, only an offset is provided.
50 ///
51 /// All point locations are assumed to be given for the left half of the
52 /// suspension and will be mirrored (reflecting the y coordinates) to construct
53 /// the right side.
54 class CH_VEHICLE_API ChSemiTrailingArm : public ChSuspension {
55   public:
56     ChSemiTrailingArm(const std::string& name  ///< [in] name of the subsystem
57                       );
58 
59     virtual ~ChSemiTrailingArm();
60 
61     /// Get the name of the vehicle subsystem template.
GetTemplateName()62     virtual std::string GetTemplateName() const override { return "SemiTrailingArm"; }
63 
64     /// Specify whether or not this suspension can be steered.
IsSteerable()65     virtual bool IsSteerable() const final override { return false; }
66 
67     /// Specify whether or not this is an independent suspension.
IsIndependent()68     virtual bool IsIndependent() const final override { return true; }
69 
70     /// Initialize this suspension subsystem.
71     /// The suspension subsystem is initialized by attaching it to the specified chassis and (if provided) to the
72     /// specified subchassis, at the specified location (with respect to and expressed in the reference frame of the
73     /// chassis). It is assumed that the suspension reference frame is always aligned with the chassis reference frame.
74     /// Since this suspension is non-steerable, the steering subsystem is always ignored.
75     virtual void Initialize(
76         std::shared_ptr<ChChassis> chassis,        ///< [in] associated chassis subsystem
77         std::shared_ptr<ChSubchassis> subchassis,  ///< [in] associated subchassis subsystem (may be null)
78         std::shared_ptr<ChSteering> steering,      ///< [in] associated steering subsystem (may be null)
79         const ChVector<>& location,                ///< [in] location relative to the chassis frame
80         double left_ang_vel = 0,                   ///< [in] initial angular velocity of left wheel
81         double right_ang_vel = 0                   ///< [in] initial angular velocity of right wheel
82         ) override;
83 
84     /// Add visualization assets for the suspension subsystem.
85     /// This default implementation uses primitives.
86     virtual void AddVisualizationAssets(VisualizationType vis) override;
87 
88     /// Remove visualization assets for the suspension subsystem.
89     virtual void RemoveVisualizationAssets() override;
90 
91     /// Get the total mass of the suspension subsystem.
92     virtual double GetMass() const override;
93 
94     /// Get the current global COM location of the suspension subsystem.
95     virtual ChVector<> GetCOMPos() const override;
96 
97     /// Get the wheel track for the suspension subsystem.
98     virtual double GetTrack() override;
99 
100     /// Get a handle to the specified spring element.
GetSpring(VehicleSide side)101     std::shared_ptr<ChLinkTSDA> GetSpring(VehicleSide side) const { return m_spring[side]; }
102 
103     /// Get a handle to the specified shock (damper) element.
GetShock(VehicleSide side)104     std::shared_ptr<ChLinkTSDA> GetShock(VehicleSide side) const { return m_shock[side]; }
105 
106     /// Return current suspension forces (spring and shock) on the specified side.
107     virtual ChSuspension::Force ReportSuspensionForce(VehicleSide side) const override;
108 
109     /// Get the force in the spring element.
GetSpringForce(VehicleSide side)110     double GetSpringForce(VehicleSide side) const { return m_spring[side]->GetForce(); }
111 
112     /// Get the current length of the spring element
GetSpringLength(VehicleSide side)113     double GetSpringLength(VehicleSide side) const { return m_spring[side]->GetLength(); }
114 
115     /// Get the current deformation of the spring element.
GetSpringDeformation(VehicleSide side)116     double GetSpringDeformation(VehicleSide side) const { return m_spring[side]->GetDeformation(); }
117 
118     /// Get the force in the shock (damper) element.
GetShockForce(VehicleSide side)119     double GetShockForce(VehicleSide side) const { return m_shock[side]->GetForce(); }
120 
121     /// Get the current length of the shock (damper) element.
GetShockLength(VehicleSide side)122     double GetShockLength(VehicleSide side) const { return m_shock[side]->GetLength(); }
123 
124     /// Get the current deformation velocity of the shock (damper) element.
GetShockVelocity(VehicleSide side)125     double GetShockVelocity(VehicleSide side) const { return m_shock[side]->GetVelocity(); }
126 
127     /// Log current constraint violations.
128     virtual void LogConstraintViolations(VehicleSide side) override;
129 
130     /// Specify the suspension body on the specified side to attach a possible antirollbar subsystem.
131     /// Return the corresponding trailing arm.
GetAntirollBody(VehicleSide side)132     virtual std::shared_ptr<ChBody> GetAntirollBody(VehicleSide side) const override { return m_arm[side]; }
133 
134     /// Log the locations of all hardpoints.
135     /// The reported locations are expressed in the suspension reference frame.
136     /// By default, these values are reported in SI units (meters), but can be
137     /// optionally reported in inches.
138     void LogHardpointLocations(const ChVector<>& ref, bool inches = false);
139 
140   protected:
141     /// Identifiers for the various hardpoints.
142     enum PointId {
143         SPINDLE,   ///< spindle location (center of mass)
144         TA_CM,     ///< trailing arm, center of mass
145         TA_O,      ///< trailing arm, chassis connection outter
146         TA_I,      ///< trailing arm, chassis connection inner
147         TA_S,      ///< trailing arm, connection to spindle
148         SHOCK_C,   ///< shock, chassis
149         SHOCK_A,   ///< shock, lower control arm
150         SPRING_C,  ///< spring, chassis
151         SPRING_A,  ///< spring, lower control arm
152         NUM_POINTS
153     };
154 
155     /// Return the location of the specified hardpoint.
156     /// The returned location must be expressed in the suspension reference frame.
157     virtual const ChVector<> getLocation(PointId which) = 0;
158 
159     /// Return the mass of the spindle body.
160     virtual double getSpindleMass() const = 0;
161     /// Return the mass of the trailing arm body.
162     virtual double getArmMass() const = 0;
163 
164     /// Return the moments of inertia of the spindle body.
165     virtual const ChVector<>& getSpindleInertia() const = 0;
166     /// Return the moments of inertia of the trailing arm body.
167     virtual const ChVector<>& getArmInertia() const = 0;
168 
169     /// Return the inertia of the axle shaft.
170     virtual double getAxleInertia() const = 0;
171 
172     /// Return the radius of the trailing arm body (visualization only).
173     virtual double getArmRadius() const = 0;
174 
175     /// Return the free (rest) length of the spring element.
176     virtual double getSpringRestLength() const = 0;
177     /// Return the functor object for spring force.
178     virtual std::shared_ptr<ChLinkTSDA::ForceFunctor> getSpringForceFunctor() const = 0;
179     /// Return the functor object for shock force.
180     virtual std::shared_ptr<ChLinkTSDA::ForceFunctor> getShockForceFunctor() const = 0;
181 
182     /// Return stiffness and damping data for the arm bushing.
183     /// Returning nullptr (default) results in using a kinematic revolute joint.
getCABushingData()184     virtual std::shared_ptr<ChVehicleBushingData> getCABushingData() const { return nullptr; }
185 
186     std::shared_ptr<ChBody> m_arm[2];  ///< trailing arm bodies (left/right)
187 
188     std::shared_ptr<ChVehicleJoint> m_revoluteArm[2];  ///< chassis-arm revolute joints (left/right)
189 
190     std::shared_ptr<ChLinkTSDA> m_shock[2];   ///< spring links (left/right)
191     std::shared_ptr<ChLinkTSDA> m_spring[2];  ///< shock links (left/right)
192 
193   private:
194     // Hardpoint absolute locations
195     std::vector<ChVector<>> m_pointsL;
196     std::vector<ChVector<>> m_pointsR;
197 
198     void InitializeSide(VehicleSide side,
199                         std::shared_ptr<ChChassis> chassis,
200                         const std::vector<ChVector<>>& points,
201                         double ang_vel);
202 
203     static void AddVisualizationArm(std::shared_ptr<ChBody> arm,
204                                     const ChVector<> pt_AC_O,
205                                     const ChVector<> pt_AC_I,
206                                     const ChVector<> pt_AS,
207                                     const ChVector<> pt_S,
208                                     double radius);
209 
210     virtual void ExportComponentList(rapidjson::Document& jsonDocument) const override;
211 
212     virtual void Output(ChVehicleOutput& database) const override;
213 
214     static const std::string m_pointNames[NUM_POINTS];
215 };
216 
217 /// @} vehicle_wheeled_suspension
218 
219 }  // end namespace vehicle
220 }  // end namespace chrono
221 
222 #endif
223