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, Daniel Melanz 13 // ============================================================================= 14 // 15 // Base class for a double-A arm suspension modeled with bodies and constraints. 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_DOUBLEWISHBONE_H 30 #define CH_DOUBLEWISHBONE_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 double-A arm suspension modeled with bodies and constraints. 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 ChDoubleWishbone : public ChSuspension { 55 public: 56 virtual ~ChDoubleWishbone(); 57 58 /// Get the name of the vehicle subsystem template. GetTemplateName()59 virtual std::string GetTemplateName() const override { return "DoubleWishbone"; } 60 61 /// Specify whether or not this suspension can be steered. IsSteerable()62 virtual bool IsSteerable() const final override { return true; } 63 64 /// Specify whether or not this is an independent suspension. IsIndependent()65 virtual bool IsIndependent() const final override { return true; } 66 67 /// Initialize this suspension subsystem. 68 /// The suspension subsystem is initialized by attaching it to the specified chassis and (if provided) to the 69 /// specified subchassis, at the specified location (with respect to and expressed in the reference frame of the 70 /// chassis). It is assumed that the suspension reference frame is always aligned with the chassis reference frame. 71 /// If a steering subsystem is provided, the suspension tierods are to be attached to the steering's central link 72 /// body (steered suspension); otherwise they are to be attached to the chassis (non-steered suspension). 73 virtual void Initialize( 74 std::shared_ptr<ChChassis> chassis, ///< [in] associated chassis subsystem 75 std::shared_ptr<ChSubchassis> subchassis, ///< [in] associated subchassis subsystem (may be null) 76 std::shared_ptr<ChSteering> steering, ///< [in] associated steering subsystem (may be null) 77 const ChVector<>& location, ///< [in] location relative to the chassis frame 78 double left_ang_vel = 0, ///< [in] initial angular velocity of left wheel 79 double right_ang_vel = 0 ///< [in] initial angular velocity of right wheel 80 ) override; 81 82 /// Add visualization assets for the suspension subsystem. 83 /// This default implementation uses primitives. 84 virtual void AddVisualizationAssets(VisualizationType vis) override; 85 86 /// Remove visualization assets for the suspension subsystem. 87 virtual void RemoveVisualizationAssets() override; 88 89 /// Get the total mass of the suspension subsystem. 90 virtual double GetMass() const override; 91 92 /// Get the current global COM location of the suspension subsystem. 93 virtual ChVector<> GetCOMPos() const override; 94 95 /// Get the wheel track for the suspension subsystem. 96 virtual double GetTrack() override; 97 98 /// Get a handle to the specified spring element. GetSpring(VehicleSide side)99 std::shared_ptr<ChLinkTSDA> GetSpring(VehicleSide side) const { return m_spring[side]; } 100 101 /// Get a handle to the specified shock (damper) element. GetShock(VehicleSide side)102 std::shared_ptr<ChLinkTSDA> GetShock(VehicleSide side) const { return m_shock[side]; } 103 104 /// Return current suspension forces (spring and shock) on the specified side. 105 virtual ChSuspension::Force ReportSuspensionForce(VehicleSide side) const override; 106 107 /// Get the force in the spring element. GetSpringForce(VehicleSide side)108 double GetSpringForce(VehicleSide side) const { return m_spring[side]->GetForce(); } 109 110 /// Get the current length of the spring element GetSpringLength(VehicleSide side)111 double GetSpringLength(VehicleSide side) const { return m_spring[side]->GetLength(); } 112 113 /// Get the current deformation of the spring element. GetSpringDeformation(VehicleSide side)114 double GetSpringDeformation(VehicleSide side) const { return m_spring[side]->GetDeformation(); } 115 116 /// Get the force in the shock (damper) element. GetShockForce(VehicleSide side)117 double GetShockForce(VehicleSide side) const { return m_shock[side]->GetForce(); } 118 119 /// Get the current length of the shock (damper) element. GetShockLength(VehicleSide side)120 double GetShockLength(VehicleSide side) const { return m_shock[side]->GetLength(); } 121 122 /// Get the current deformation velocity of the shock (damper) element. GetShockVelocity(VehicleSide side)123 double GetShockVelocity(VehicleSide side) const { return m_shock[side]->GetVelocity(); } 124 125 /// Global coordinates, LCA ball joint position Get_LCA_sph_pos(VehicleSide side)126 ChVector<> Get_LCA_sph_pos(VehicleSide side) { return m_sphericalLCA[side]->GetPos(); } 127 128 /// Global coordinates, UCA ball joint position Get_UCA_sph_pos(VehicleSide side)129 ChVector<> Get_UCA_sph_pos(VehicleSide side) { return m_sphericalUCA[side]->GetPos(); } 130 131 /// Log current constraint violations. 132 virtual void LogConstraintViolations(VehicleSide side) override; 133 134 /// Specify the suspension body on the specified side to attach a possible antirollbar subsystem. 135 /// Return the corresponding lower control arm. GetAntirollBody(VehicleSide side)136 virtual std::shared_ptr<ChBody> GetAntirollBody(VehicleSide side) const override { return m_LCA[side]; } 137 138 /// Log the locations of all hardpoints. 139 /// The reported locations are expressed in the suspension reference frame. 140 /// By default, these values are reported in SI units (meters), but can be 141 /// optionally reported in inches. 142 void LogHardpointLocations(const ChVector<>& ref, bool inches = false); 143 144 protected: 145 /// Identifiers for the various hardpoints. 146 enum PointId { 147 SPINDLE, ///< spindle location 148 UPRIGHT, ///< upright location 149 UCA_F, ///< upper control arm, chassis front 150 UCA_B, ///< upper control arm, chassis back 151 UCA_U, ///< upper control arm, upright 152 UCA_CM, ///< upper control arm, center of mass 153 LCA_F, ///< lower control arm, chassis front 154 LCA_B, ///< lower control arm, chassis back 155 LCA_U, ///< lower control arm, upright 156 LCA_CM, ///< lower control arm, center of mass 157 SHOCK_C, ///< shock, chassis 158 SHOCK_A, ///< shock, lower control arm 159 SPRING_C, ///< spring, chassis 160 SPRING_A, ///< spring, lower control arm 161 TIEROD_C, ///< tierod, chassis 162 TIEROD_U, ///< tierod, upright 163 NUM_POINTS 164 }; 165 166 /// Protected constructor. 167 ChDoubleWishbone( 168 const std::string& name, ///< [in] name of the subsystem 169 bool vehicle_frame_inertia = false ///< [in] inertia specified in vehicle-aligned centroidal frames? 170 ); 171 172 /// Indicate whether or not inertia matrices are specified with respect to a 173 /// vehicle-aligned centroidal frame (flag=true) or with respect to the body 174 /// centroidal frame (flag=false). Note that this function must be called 175 /// before Initialize(). SetVehicleFrameInertiaFlag(bool val)176 void SetVehicleFrameInertiaFlag(bool val) { m_vehicle_frame_inertia = val; } 177 178 /// Indicate whether or not tirod bodies are modelled (default: false). 179 /// If false, tierods are modelled using distance constraints. 180 /// If true, rigid tierod bodies are created (in which case a derived class must provide the mass and inertia) and 181 /// connected either with kinematic joints or bushings (depending on whether or not bushing data is defined). UseTierodBodies()182 virtual bool UseTierodBodies() const { return false; } 183 184 /// Return the location of the specified hardpoint. 185 /// The returned location must be expressed in the suspension reference frame. 186 virtual const ChVector<> getLocation(PointId which) = 0; 187 188 /// Return the mass of the spindle body. 189 virtual double getSpindleMass() const = 0; 190 /// Return the mass of the upper control arm body. 191 virtual double getUCAMass() const = 0; 192 /// Return the mass of the lower control body. 193 virtual double getLCAMass() const = 0; 194 /// Return the mass of the upright body. 195 virtual double getUprightMass() const = 0; 196 /// Return the mass of the tierod body. getTierodMass()197 virtual double getTierodMass() const { return 0; } 198 199 /// Return the moments of inertia of the spindle body. 200 virtual const ChVector<>& getSpindleInertia() const = 0; 201 202 /// Return the moments of inertia of the upper control arm body. 203 virtual const ChVector<>& getUCAInertiaMoments() const = 0; 204 /// Return the products of inertia of the upper control arm body. 205 virtual const ChVector<>& getUCAInertiaProducts() const = 0; 206 207 /// Return the moments of inertia of the lower control arm body. 208 virtual const ChVector<>& getLCAInertiaMoments() const = 0; 209 /// Return the products of inertia of the lower control arm body. 210 virtual const ChVector<>& getLCAInertiaProducts() const = 0; 211 212 /// Return the moments of inertia of the upright body. 213 virtual const ChVector<>& getUprightInertiaMoments() const = 0; 214 /// Return the products of inertia of the upright body. 215 virtual const ChVector<>& getUprightInertiaProducts() const = 0; 216 217 /// Return the moments of inertia of the tierod body. getTierodInertia()218 virtual const ChVector<> getTierodInertia() const { return ChVector<>(0); } 219 220 /// Return the inertia of the axle shaft. 221 virtual double getAxleInertia() const = 0; 222 223 /// Return the radius of the upper control arm body (visualization only). 224 virtual double getUCARadius() const = 0; 225 /// Return the radius of the lower control arm body (visualization only). 226 virtual double getLCARadius() const = 0; 227 /// Return the radius of the upright body (visualization only). 228 virtual double getUprightRadius() const = 0; 229 /// Return the radius of the tierod body (visualization only). getTierodRadius()230 virtual double getTierodRadius() const { return 0; } 231 232 /// Return the free (rest) length of the spring element. 233 virtual double getSpringRestLength() const = 0; 234 /// Return the functor object for spring force. 235 virtual std::shared_ptr<ChLinkTSDA::ForceFunctor> getSpringForceFunctor() const = 0; 236 /// Return the functor object for shock force. 237 virtual std::shared_ptr<ChLinkTSDA::ForceFunctor> getShockForceFunctor() const = 0; 238 239 /// Return stiffness and damping data for the UCA bushing. 240 /// Returning nullptr (default) results in using a kinematic revolute joint. getUCABushingData()241 virtual std::shared_ptr<ChVehicleBushingData> getUCABushingData() const { return nullptr; } 242 /// Return stiffness and damping data for the LCA bushing. 243 /// Returning nullptr (default) results in using a kinematic revolute joint. getLCABushingData()244 virtual std::shared_ptr<ChVehicleBushingData> getLCABushingData() const { return nullptr; } 245 /// Return stiffness and damping data for the tierod bushings. 246 /// Used only if tierod bodies are defined (see UseTierodBody). 247 /// Returning nullptr (default) results in using kinematic joints (spherical + universal). getTierodBushingData()248 virtual std::shared_ptr<ChVehicleBushingData> getTierodBushingData() const { return nullptr; } 249 250 std::shared_ptr<ChBody> m_upright[2]; ///< upright bodies (left/right) 251 std::shared_ptr<ChBody> m_UCA[2]; ///< upper control arm bodies (left/right) 252 std::shared_ptr<ChBody> m_LCA[2]; ///< lower control arm bodies (left/right) 253 std::shared_ptr<ChBody> m_tierod[2]; ///< tierod bodies, if used (left/right) 254 255 std::shared_ptr<ChVehicleJoint> m_revoluteUCA[2]; ///< chassis-UCA revolute joints (left/right) 256 std::shared_ptr<ChVehicleJoint> m_sphericalUCA[2]; ///< upright-UCA spherical joints (left/right) 257 std::shared_ptr<ChVehicleJoint> m_revoluteLCA[2]; ///< chassis-LCA revolute joints (left/right) 258 std::shared_ptr<ChVehicleJoint> m_sphericalLCA[2]; ///< upright-LCA spherical joints (left/right) 259 260 std::shared_ptr<ChLinkDistance> m_distTierod[2]; ///< tierod distance constraints (left/right) 261 std::shared_ptr<ChVehicleJoint> m_sphericalTierod[2]; ///< tierod-upright spherical joints (left/right) 262 std::shared_ptr<ChVehicleJoint> m_universalTierod[2]; ///< tierod-chassis universal joints (left/right) 263 264 std::shared_ptr<ChLinkTSDA> m_shock[2]; ///< spring links (left/right) 265 std::shared_ptr<ChLinkTSDA> m_spring[2]; ///< shock links (left/right) 266 267 private: 268 // Flag indicating that the inertia matrices for the upright and control arms 269 // are provided in vehicle-aligned centroidal frames 270 bool m_vehicle_frame_inertia; 271 272 // Hardpoint absolute locations 273 std::vector<ChVector<>> m_pointsL; 274 std::vector<ChVector<>> m_pointsR; 275 276 void InitializeSide(VehicleSide side, 277 std::shared_ptr<ChChassis> chassis, 278 std::shared_ptr<ChBody> tierod_body, 279 const std::vector<ChVector<> >& points, 280 double ang_vel); 281 282 static void AddVisualizationControlArm(std::shared_ptr<ChBody> arm, 283 const ChVector<> pt_F, 284 const ChVector<> pt_B, 285 const ChVector<> pt_U, 286 double radius); 287 static void AddVisualizationUpright(std::shared_ptr<ChBody> upright, 288 const ChVector<> pt_C, 289 const ChVector<> pt_U, 290 const ChVector<> pt_L, 291 const ChVector<> pt_T, 292 double radius); 293 static void AddVisualizationTierod(std::shared_ptr<ChBody> tierod, 294 const ChVector<> pt_C, 295 const ChVector<> pt_U, 296 double radius); 297 298 virtual void ExportComponentList(rapidjson::Document& jsonDocument) const override; 299 300 virtual void Output(ChVehicleOutput& database) const override; 301 302 static const std::string m_pointNames[NUM_POINTS]; 303 }; 304 305 /// @} vehicle_wheeled_suspension 306 307 } // end namespace vehicle 308 } // end namespace chrono 309 310 #endif 311