MVSim
Lightweight simulator for 2.5D vehicles and robots
VehicleBase.h
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2026 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
10 #pragma once
11 
12 #include <box2d/b2_body.h>
13 #include <box2d/b2_fixture.h>
14 #include <box2d/b2_polygon_shape.h>
15 #include <box2d/b2_world.h>
16 #include <mrpt/img/TColor.h>
17 #include <mrpt/opengl/CSetOfLines.h>
18 #include <mrpt/opengl/CSetOfObjects.h>
19 #include <mrpt/poses/CPose2D.h>
20 #include <mvsim/ClassFactory.h>
21 #include <mvsim/ControllerBase.h>
22 #include <mvsim/FrictionModels/FrictionBase.h>
23 #include <mvsim/Sensors/SensorBase.h>
24 #include <mvsim/Simulable.h>
25 #include <mvsim/VisualObject.h>
26 #include <mvsim/Wheel.h>
27 #include <mvsim/basic_types.h>
28 
29 #include <atomic>
30 #include <mutex>
31 #include <string>
32 
33 #include "CsvLogger.h"
34 
35 namespace mvsim
36 {
43 class VehicleBase : public VisualObject, public Simulable
44 {
45  public:
46  using Ptr = std::shared_ptr<VehicleBase>;
47 
50  static Ptr factory(World* parent, const rapidxml::xml_node<char>* xml_node);
52  static Ptr factory(World* parent, const std::string& xml_text);
53 
57  const World& parent, const rapidxml::xml_node<char>* xml_node);
58 
59  // ------- Interface with "World" ------
60  virtual void simul_pre_timestep(const TSimulContext& context) override;
61  virtual void simul_post_timestep(const TSimulContext& context) override;
62  virtual void apply_force(
63  const mrpt::math::TVector2D& force,
64  const mrpt::math::TPoint2D& applyPoint = mrpt::math::TPoint2D(0, 0)) override;
65 
68  virtual void create_multibody_system(b2World& world);
69 
72  virtual double getMaxVehicleRadius() const { return maxRadius_; }
73 
75  virtual double getChassisMass() const { return chassis_mass_; }
76  b2Body* getBox2DChassisBody() { return b2dBody_; }
77 
79  mrpt::math::TPoint2D getChassisCenterOfMass() const { return chassis_com_; }
80 
81  size_t getNumWheels() const { return wheels_info_.size(); }
82  const Wheel& getWheelInfo(const size_t idx) const { return wheels_info_[idx]; }
83  Wheel& getWheelInfo(const size_t idx) { return wheels_info_[idx]; }
84 
87  std::vector<mrpt::math::TVector2D> getWheelsVelocityLocal(
88  const mrpt::math::TTwist2D& veh_vel_local) const;
89 
94  virtual mrpt::math::TTwist2D getVelocityLocalOdoEstimate() const = 0;
95 
102  double estimateSlopeTorquePerWheel(size_t nDrivenWheels = 0) const;
103 
104  const TListSensors& getSensors() const { return sensors_; }
105  TListSensors& getSensors() { return sensors_; }
106  CSVLogger::Ptr getLoggerPtr(const std::size_t logger_index)
107  {
108  return loggers_.at(logger_index);
109  }
110 
111  const std::vector<CSVLogger::Ptr>& getLoggers() const { return loggers_; }
112 
115  const mrpt::math::TPolygon2D& getChassisShape() const { return chassis_poly_; }
116 
118  void setVehicleIndex(size_t idx) { vehicle_index_ = idx; }
120  size_t getVehicleIndex() const { return vehicle_index_; }
121  void setRecording(bool record)
122  {
123  for (auto& logger : loggers_)
124  {
125  logger->setRecording(record);
126  }
127  }
128  void clearLogs()
129  {
130  for (auto& logger : loggers_)
131  {
132  logger->clear();
133  }
134  }
135  void newLogSession()
136  {
137  for (auto& logger : loggers_)
138  {
139  logger->newSession();
140  }
141  }
142 
143  virtual ControllerBaseInterface* getControllerInterface() = 0;
144 
145  void registerOnServer(mvsim::Client& c) override;
146 
147  b2Fixture* get_fixture_chassis() { return fixture_chassis_; }
148  std::vector<b2Fixture*>& get_fixture_wheels() { return fixture_wheels_; }
149  const b2Fixture* get_fixture_chassis() const { return fixture_chassis_; }
150  const std::vector<b2Fixture*>& get_fixture_wheels() const { return fixture_wheels_; }
151 
152  void freeOpenGLResources() override
153  {
154  for (auto& sensor : sensors_)
155  {
156  sensor->freeOpenGLResources();
157  }
158  }
159  void chassisAndWheelsVisible(bool visible);
160 
161  double chassisZMin() const { return chassis_z_min_; }
162  double chassisZMax() const { return chassis_z_max_; }
163 
168  const mrpt::math::TPoint3D& getSlopeDirection() const { return slopeDir_; }
169  void setSlopeDirection(const mrpt::math::TPoint3D& d) { slopeDir_ = d; }
170 
173  mrpt::poses::CPose2D getOdometry() const { return odometry_; }
174 
175  void resetOdometry()
176  {
177  odometry_ = mrpt::poses::CPose2D();
178  odometry_pre_simul_pose_.reset();
179  }
180 
181  protected:
182  std::vector<CSVLogger::Ptr> loggers_;
183  std::string log_path_;
184  bool auto_start_recording_ = false;
185 
186  virtual void initLoggers();
187  virtual void writeLogStrings();
188  virtual void internalGuiUpdate(
189  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
190  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical, bool childrenOnly) override;
191 
192  protected:
193  // Protected ctor for class factory
194  VehicleBase(World* parent, size_t nWheels);
195 
199  virtual void dynamics_load_params_from_xml(const rapidxml::xml_node<char>* xml_node) = 0;
200 
201  virtual std::vector<double> invoke_motor_controllers(const TSimulContext& context) = 0;
202 
203  virtual void invoke_motor_controllers_post_step([[maybe_unused]] const TSimulContext& context)
204  {
205  }
206 
207  VisualObject* meAsVisualObject() override { return this; }
208 
215 
218  size_t vehicle_index_ = 0;
219 
221  std::vector<FrictionBase::Ptr> frictions_;
222 
223  TListSensors sensors_;
224 
225  // Chassis info:
226  double chassis_mass_ = 15.0;
227  mrpt::math::TPolygon2D chassis_poly_;
228 
230  float linear_damping_ = 0.1;
231 
233  float angular_damping_ = 0.1;
234 
237  double maxRadius_ = 0.1;
238 
239  double chassis_z_min_ = 0.05, chassis_z_max_ = 0.6;
240 
241  mrpt::img::TColor chassis_color_{0xff, 0x00, 0x00};
242 
245  mrpt::math::TPoint2D chassis_com_{0, 0};
246 
249  mrpt::math::TPoint3D slopeDir_{0, 0, -1};
250 
251  void updateMaxRadiusFromPoly();
252 
255  {
256  // Initializes the multipliers with random factors near 1.0
257  OdometryNoise();
258 
259  [[nodiscard]] mrpt::poses::CPose2D actualDeltaToNoisyOdo(
260  const mrpt::poses::CPose2D& delta) const
261  {
262  return {
263  delta.x() * x_multiplier, delta.y() * y_multiplier, delta.phi() * yaw_multiplier};
264  }
265 
266  double x_multiplier;
267  double y_multiplier;
268  double yaw_multiplier;
269  };
270  OdometryNoise odometry_noise_;
271 
276  std::deque<Wheel> wheels_info_;
277 
278  // Box2D elements:
279  b2Fixture* fixture_chassis_ = nullptr;
280 
283  std::vector<b2Fixture*> fixture_wheels_;
284 
285  private:
286  // Called from internalGuiUpdate()
287  void internal_internalGuiUpdate_sensors(
288  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
289  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical);
290  // Called from internalGuiUpdate()
291  void internal_internalGuiUpdate_forces(mrpt::opengl::COpenGLScene& scene);
292 
293  mrpt::opengl::CSetOfObjects::Ptr glChassisViz_, glChassisPhysical_;
294  std::vector<mrpt::opengl::CSetOfObjects::Ptr> glWheelsViz_, glWheelsPhysical_;
295  mrpt::opengl::CSetOfLines::Ptr glForces_;
296  mrpt::opengl::CSetOfLines::Ptr glMotorTorques_;
297  std::atomic_bool glInit_ = false;
298 
299  std::vector<mrpt::math::TSegment3D> forceSegmentsForRendering_;
300  std::vector<mrpt::math::TSegment3D> torqueSegmentsForRendering_;
301  std::mutex forceSegmentsForRenderingMtx_;
302 
304  mrpt::poses::CPose2D odometry_;
306  std::optional<mrpt::poses::CPose3D> odometry_pre_simul_pose_;
307 
308  public:
309  // data logger header entries
310  static constexpr std::string_view DL_TIMESTAMP = "Timestamp";
311  static constexpr std::size_t LOGGER_IDX_POSE = 0;
312  static constexpr std::size_t LOGGER_IDX_WHEELS = 1;
313 
314  static constexpr std::string_view PL_Q_X = "q0x";
315  static constexpr std::string_view PL_Q_Y = "q1y";
316  static constexpr std::string_view PL_Q_Z = "q2z";
317  static constexpr std::string_view PL_Q_YAW = "q3yaw";
318  static constexpr std::string_view PL_Q_PITCH = "q4pitch";
319  static constexpr std::string_view PL_Q_ROLL = "q5roll";
320  static constexpr std::string_view PL_DQ_X = "dqx";
321  static constexpr std::string_view PL_DQ_Y = "dqy";
322  static constexpr std::string_view PL_DQ_W = "dqw";
323 
324  static constexpr std::string_view PL_ODO_X = "odo_x";
325  static constexpr std::string_view PL_ODO_Y = "odo_y";
326  static constexpr std::string_view PL_ODO_YAW = "odo_yaw";
327 
328  static constexpr std::string_view WL_TORQUE = "torque";
329  static constexpr std::string_view WL_FORCE_Z = "force_z";
330  static constexpr std::string_view WL_VEL_X = "velocity_x";
331  static constexpr std::string_view WL_VEL_Y = "velocity_y";
332  static constexpr std::string_view WL_FRIC_X = "friction_x";
333  static constexpr std::string_view WL_FRIC_Y = "friction_y";
334 
335  bool isLogging() const;
336 }; // end VehicleBase
337 
338 // Class factory:
340 extern TClassFactory_vehicleDynamics classFactory_vehicleDynamics;
341 
342 #define DECLARES_REGISTER_VEHICLE_DYNAMICS(CLASS_NAME) \
343  DECLARES_REGISTER_CLASS1(CLASS_NAME, VehicleBase, World*)
344 
345 #define REGISTER_VEHICLE_DYNAMICS(TEXTUAL_NAME, CLASS_NAME) \
346  REGISTER_CLASS1( \
347  TClassFactory_vehicleDynamics, classFactory_vehicleDynamics, TEXTUAL_NAME, CLASS_NAME)
348 } // namespace mvsim
Definition: ClassFactory.h:26
Definition: Client.h:49
Definition: Simulable.h:40
Definition: VehicleBase.h:44
bool idealControllerActive_
Definition: VehicleBase.h:214
virtual void apply_force(const mrpt::math::TVector2D &force, const mrpt::math::TPoint2D &applyPoint=mrpt::math::TPoint2D(0, 0)) override
virtual void create_multibody_system(b2World &world)
virtual double getChassisMass() const
Definition: VehicleBase.h:75
mrpt::math::TPoint3D slopeDir_
Definition: VehicleBase.h:249
size_t vehicle_index_
Definition: VehicleBase.h:218
const mrpt::math::TPolygon2D & getChassisShape() const
Definition: VehicleBase.h:115
static Ptr factory(World *parent, const rapidxml::xml_node< char > *xml_node)
std::vector< b2Fixture * > fixture_wheels_
Definition: VehicleBase.h:283
std::deque< Wheel > wheels_info_
Definition: VehicleBase.h:276
mrpt::poses::CPose2D getOdometry() const
Definition: VehicleBase.h:173
double estimateSlopeTorquePerWheel(size_t nDrivenWheels=0) const
float angular_damping_
Definition: VehicleBase.h:233
static void register_vehicle_class(const World &parent, const rapidxml::xml_node< char > *xml_node)
virtual double getMaxVehicleRadius() const
Definition: VehicleBase.h:72
std::vector< FrictionBase::Ptr > frictions_
Definition: VehicleBase.h:221
std::vector< mrpt::math::TVector2D > getWheelsVelocityLocal(const mrpt::math::TTwist2D &veh_vel_local) const
b2Fixture * fixture_chassis_
Created at.
Definition: VehicleBase.h:279
static Ptr factory(World *parent, const std::string &xml_text)
This is an overloaded member function, provided for convenience. It differs from the above function o...
mrpt::math::TPoint2D chassis_com_
Definition: VehicleBase.h:245
const mrpt::math::TPoint3D & getSlopeDirection() const
Definition: VehicleBase.h:168
double maxRadius_
Definition: VehicleBase.h:237
virtual void simul_post_timestep(const TSimulContext &context) override
void setVehicleIndex(size_t idx)
Definition: VehicleBase.h:118
virtual void simul_pre_timestep(const TSimulContext &context) override
float linear_damping_
Definition: VehicleBase.h:230
mrpt::math::TPoint2D getChassisCenterOfMass() const
In local coordinates (this excludes the mass of wheels)
Definition: VehicleBase.h:79
TListSensors sensors_
Sensors aboard.
Definition: VehicleBase.h:223
size_t getVehicleIndex() const
Definition: VehicleBase.h:120
virtual void dynamics_load_params_from_xml(const rapidxml::xml_node< char > *xml_node)=0
virtual mrpt::math::TTwist2D getVelocityLocalOdoEstimate() const =0
Definition: VisualObject.h:36
Definition: World.h:132
Definition: basic_types.h:58
Definition: VehicleBase.h:255