1 // ============================================================================= 2 // PROJECT CHRONO - http://projectchrono.org 3 // 4 // Copyright (c) 2020 projectchrono.org 5 // All right 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 // Definition of the base vehicle co-simulation TERRAIN NODE class. 16 // 17 // The global reference frame has Z up, X towards the front of the vehicle, and 18 // Y pointing to the left. 19 // 20 // ============================================================================= 21 22 #ifndef CH_VEHCOSIM_TERRAIN_NODE_H 23 #define CH_VEHCOSIM_TERRAIN_NODE_H 24 25 #include "chrono/ChConfig.h" 26 27 #include "chrono_vehicle/ChSubsysDefs.h" 28 #include "chrono_vehicle/ChPart.h" 29 #include "chrono_vehicle/cosim/ChVehicleCosimBaseNode.h" 30 31 #include "chrono_thirdparty/rapidjson/document.h" 32 33 namespace chrono { 34 namespace vehicle { 35 36 /// @addtogroup vehicle_cosim 37 /// @{ 38 39 /// Base class for a terrain node. 40 /// Implements required functionality for a co-simulation node (Initialize(), Synchronize(), Advance()) and all MPI 41 /// communication. 42 /// 43 /// A derived class must implement functions to: 44 /// - specify the communication interface type (SupportsMeshInterface()) 45 /// - construct and initialize the concrete terrain object (OnInitialize()) 46 /// - accept new spindle body states (UpdateWheelProxy() and/or UpdateMeshProxies()) 47 /// - provide terrain forces acting on the spindle bodies (GetForceWheelProxy() and/or GetForcesMeshProxies()) 48 /// - advance the dynamic state of the terrain (OnAdvance()) 49 /// 50 /// Optionally, a derived class may implement functions to: 51 /// - perform additional operations after a synchronization data exchange (OnSynchronize()) 52 /// - perform additional data output (OnOutputData()) 53 /// - provide run-time visualization (Render()) 54 class CH_VEHICLE_API ChVehicleCosimTerrainNode : public ChVehicleCosimBaseNode { 55 public: ~ChVehicleCosimTerrainNode()56 virtual ~ChVehicleCosimTerrainNode() {} 57 58 /// Return the node type as NodeType::TERRAIN. GetNodeType()59 virtual NodeType GetNodeType() const override { return NodeType::TERRAIN; } 60 61 /// Enable/disable run-time visualization (default: false). 62 /// If enabled, rendering is done with the specified frequency. 63 /// Note that a particular concrete terrain node may not support run-time visualization or may not render all 64 /// physics elements. 65 void EnableRuntimeVisualization(bool render, double render_fps = 100); 66 67 /// Set the terrain patch dimensions. 68 /// If invoked, this function must be called before Initialize. 69 void SetDimensions(double length, double width); 70 71 /// Initialize this node. 72 /// This function allows the node to initialize itself and, optionally, perform an 73 /// initial data exchange with any other node. 74 virtual void Initialize() override final; 75 76 /// Synchronize this node. 77 /// This function is called at every co-simulation synchronization time to 78 /// allow the node to exchange information with any other node. 79 virtual void Synchronize(int step_number, double time) override final; 80 81 /// Advance simulation. 82 /// This function is called after a synchronization to allow the node to advance 83 /// its state by the specified time step. A node is allowed to take as many internal 84 /// integration steps as required, but no inter-node communication should occur. 85 virtual void Advance(double step_size) override final; 86 87 /// Output logging and debugging data. 88 virtual void OutputData(int frame) override final; 89 90 /// Output post-processing visualization data. 91 /// If implemented, this function should write a file in the "visualization" subdirectory of m_node_out_dir. OutputVisualizationData(int frame)92 virtual void OutputVisualizationData(int frame) override {} 93 94 /// Return current number of contacts. 95 /// (concrete terrain specific) GetNumContacts()96 virtual int GetNumContacts() const { return 0; } 97 98 protected: 99 /// Construct a terrain node to wrap a terrain patch of given length and width. 100 ChVehicleCosimTerrainNode(double length, double width); 101 102 // ------------------------- Virtual methods 103 104 /// Specify whether or not the terrain node supports the MESH communication interface. 105 /// See ChVehicleCosimBaseNode::InterfaceType. 106 /// A terrain that also supports the MESH communication interface must override the functions UpdateMeshProxies() 107 /// and GetForcesMeshProxies(). 108 virtual bool SupportsMeshInterface() const = 0; 109 110 /// Return the terrain initial height. 111 /// This value must be available before the call to Initialize() (and therefore, before the derived class's 112 /// OnInitialize() is called). 113 virtual double GetInitHeight() const = 0; 114 115 /// Perform any additional operations after the initial data exchange with the MBS node, including creating any 116 /// required proxies for the specified number of tires. A derived class has access to the following vectors (of size 117 /// equal to the number of tires): 118 /// - radius for each tire (through m_tire_radius) 119 /// - width for each tire (through m_tire_width) 120 /// - mesh information for each tire (through m_mesh_data) 121 /// - contact material for each tire (through m_mat_props) 122 /// - vertical load on each tire (through m_load_mass) 123 virtual void OnInitialize(unsigned int num_tires) = 0; 124 125 /// Perform any additional operations after the data exchange and synchronization with the MBS node. A derived class 126 /// has access to the following vectors (of size equal to the number of tires): 127 /// - full dynamic state of the spindle bodies (through m_spindle_state) when using the BODY communication interface 128 /// - state of the mesh vertices (through m_mesh_state) when using the MESH communication interface OnSynchronize(int step_number,double time)129 virtual void OnSynchronize(int step_number, double time) {} 130 131 /// Advance the state of the terrain system by the specified step. 132 virtual void OnAdvance(double step_size) = 0; 133 134 /// Perform additional output at the specified frame (called from within OutputData). OnOutputData(int frame)135 virtual void OnOutputData(int frame) {} 136 137 /// Render simulation. 138 /// This function is called from Advance() at the frequency spoecified in the call to EnableRuntimeVisualization(). 139 /// Any call to Render occurs after a call to OnAdvance(). Render(double time)140 virtual void Render(double time) {} 141 142 // ------------------------- Virtual methods for the MESH communication interface 143 // A derived class must implement these methods if SupportsMeshInterface returns true. 144 145 /// Update the state of all proxy bodies for the i-th tire mesh. 146 /// Use information in the provided MeshState struct (vertex positions and velocities expressed in absolute frame). UpdateMeshProxies(unsigned int i,MeshState & mesh_state)147 virtual void UpdateMeshProxies(unsigned int i, MeshState& mesh_state) { 148 if (SupportsMeshInterface()) { 149 throw ChException("Current terrain type does not support the MESH communication interface!"); 150 } 151 } 152 153 /// Collect cumulative contact forces on all proxy bodies for the i-th tire mesh. 154 /// Load indices of vertices in contact and the corresponding vertex forces (expressed in absolute frame) 155 /// into the provided MeshContact struct. GetForcesMeshProxies(unsigned int i,MeshContact & mesh_contact)156 virtual void GetForcesMeshProxies(unsigned int i, MeshContact& mesh_contact) { 157 if (SupportsMeshInterface()) { 158 throw ChException("Current terrain type does not the MESH communication interface!"); 159 } 160 } 161 162 // ------------------------- Virtual methods for the BODY communication interface 163 164 /// Update the state of the wheel proxy body for the i-th tire. 165 /// Use information in the provided BodyState struct (pose and velocities expressed in absolute frame). 166 virtual void UpdateWheelProxy(unsigned int i, BodyState& spindle_state) = 0; 167 168 /// Collect cumulative contact force and torque on the wheel proxy body for the i-th tire. 169 /// Load contact forces (expressed in absolute frame) into the provided TerrainForce struct. 170 virtual void GetForceWheelProxy(unsigned int i, TerrainForce& wheel_contact) = 0; 171 172 protected: 173 bool m_render; ///< if true, perform run-time rendering 174 double m_render_step; ///< time step between rendered frames 175 176 double m_hdimX; ///< patch half-length (X direction) 177 double m_hdimY; ///< patch half-width (Y direction) 178 179 // Communication data 180 181 InterfaceType m_interface_type; ///< type of communication interface 182 183 std::vector<double> m_tire_radius; ///< tire radius 184 std::vector<double> m_tire_width; ///< tire width 185 std::vector<double> m_load_mass; ///< vertical load on tire 186 std::vector<MaterialInfo> m_mat_props; ///< tire contact material properties 187 std::vector<MeshData> m_mesh_data; ///< tire mesh data 188 std::vector<MeshState> m_mesh_state; ///< tire mesh state (used for MESH communication) 189 std::vector<BodyState> m_spindle_state; ///< spindle state (used for BODY communication interface) 190 191 private: 192 void SynchronizeBody(int step_number, double time); 193 void SynchronizeMesh(int step_number, double time); 194 195 /// Print vertex and face connectivity data for the i-th tire, as received at synchronization. 196 /// Invoked only when using the MESH communicatin interface. 197 void PrintMeshUpdateData(unsigned int i); 198 199 std::vector<MeshContact> m_mesh_contact; ///< tire mesh contact forces (used for MESH communication interface) 200 std::vector<TerrainForce> m_wheel_contact; ///< spindle contact force (used for BODY communication interface) 201 }; 202 203 /// @} vehicle_cosim 204 205 } // end namespace vehicle 206 } // end namespace chrono 207 208 #endif 209