VehicleDifferential.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2024 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 #include <mrpt/opengl/COpenGLScene.h>
12 #include <mvsim/World.h>
13 
14 #include <rapidxml.hpp>
15 
16 #include "xml_utils.h"
17 
18 using namespace mvsim;
19 using namespace std;
20 
21 // Ctor:
23  World* parent, const std::vector<ConfigPerWheel>& cfgPerWheel)
24  : VehicleBase(parent, cfgPerWheel.size() /*num wheels*/), configPerWheel_(cfgPerWheel)
25 {
26  using namespace mrpt::math;
27 
28  chassis_mass_ = 15.0;
29  chassis_z_min_ = 0.05;
30  chassis_z_max_ = 0.6;
31  chassis_color_ = mrpt::img::TColor(0xff, 0x00, 0x00);
32 
33  // Default shape:
34  chassis_poly_.clear();
35  chassis_poly_.emplace_back(-0.4, -0.5);
36  chassis_poly_.emplace_back(-0.4, 0.5);
37  chassis_poly_.emplace_back(0.4, 0.5);
38  chassis_poly_.emplace_back(0.6, 0.3);
39  chassis_poly_.emplace_back(0.6, -0.3);
40  chassis_poly_.emplace_back(0.4, -0.5);
42 
43  fixture_chassis_ = nullptr;
44  for (auto& fw : fixture_wheels_) fw = nullptr;
45 }
46 
49 {
50  const std::map<std::string, std::string> varValues = {{"NAME", name_}};
51 
52  // <chassis ...> </chassis>
53  const rapidxml::xml_node<char>* xml_chassis = xml_node->first_node("chassis");
54  if (xml_chassis)
55  {
56  // Attribs:
57  TParameterDefinitions attribs;
58  attribs["mass"] = TParamEntry("%lf", &this->chassis_mass_);
59  attribs["zmin"] = TParamEntry("%lf", &this->chassis_z_min_);
60  attribs["zmax"] = TParamEntry("%lf", &this->chassis_z_max_);
61  attribs["color"] = TParamEntry("%color", &this->chassis_color_);
62 
64  *xml_chassis, attribs, varValues,
65  "[DynamicsDifferential::dynamics_load_params_from_xml]");
66 
67  // Shape node (optional, fallback to default shape if none found)
68  const rapidxml::xml_node<char>* xml_shape = xml_chassis->first_node("shape");
69  if (xml_shape)
71  *xml_shape, chassis_poly_, "[DynamicsDifferential::dynamics_load_params_from_xml]");
72  }
73 
74  // <l_wheel ...>, <r_wheel ...>
75 
76  // reset default values
77  ASSERT_EQUAL_(getNumWheels(), configPerWheel_.size());
78 
79  // Load common params:
80  for (size_t i = 0; i < getNumWheels(); i++)
81  {
82  const auto& cpw = configPerWheel_.at(i);
83 
84  const rapidxml::xml_node<char>* xml_wheel = xml_node->first_node(cpw.name.c_str());
85  if (xml_wheel)
86  wheels_info_[i].loadFromXML(xml_wheel);
87  else
88  {
89  wheels_info_[i].x = cpw.pos.x;
90  wheels_info_[i].y = cpw.pos.y;
91  }
92  }
93 
94  // Vehicle controller:
95  // -------------------------------------------------
96  {
97  const rapidxml::xml_node<char>* xml_control = xml_node->first_node("controller");
98  if (xml_control)
99  {
100  rapidxml::xml_attribute<char>* control_class = xml_control->first_attribute("class");
101  if (!control_class || !control_class->value())
102  throw runtime_error(
103  "[DynamicsDifferential] Missing 'class' attribute in "
104  "<controller> XML node");
105 
106  const std::string sCtrlClass = std::string(control_class->value());
107  if (sCtrlClass == ControllerRawForces::class_name())
108  controller_ = std::make_shared<ControllerRawForces>(*this);
109  else if (sCtrlClass == ControllerTwistPID::class_name())
110  controller_ = std::make_shared<ControllerTwistPID>(*this);
111  else if (sCtrlClass == ControllerTwistIdeal::class_name())
112  controller_ = std::make_shared<ControllerTwistIdeal>(*this);
113  else
114  THROW_EXCEPTION_FMT(
115  "[DynamicsDifferential] Unknown 'class'='%s' in "
116  "<controller> XML node",
117  sCtrlClass.c_str());
118 
119  controller_->load_config(*xml_control);
120  }
121  }
122 
123  // Default controller:
124  if (!controller_) controller_ = std::make_shared<ControllerRawForces>(*this);
125 }
126 
127 // See docs in base class:
129 {
130  // Longitudinal forces at each wheel:
131  std::vector<double> otpw;
132  otpw.assign(getNumWheels(), 0.0);
133 
134  if (controller_)
135  {
136  // Invoke controller:
137  TControllerInput ci;
138  ci.context = context;
140  controller_->control_step(ci, co);
141 
142  // Take its output:
143  switch (getNumWheels())
144  {
145  case 2:
146  otpw[WHEEL_L] = co.wheel_torque_l;
147  otpw[WHEEL_R] = co.wheel_torque_r;
148  break;
149  case 3:
150  otpw[WHEEL_L] = co.wheel_torque_l;
151  otpw[WHEEL_R] = co.wheel_torque_r;
152  otpw[WHEEL_CASTER_FRONT] = 0;
153  break;
154  case 4:
155  otpw[WHEEL_LR] = co.wheel_torque_l;
156  otpw[WHEEL_RR] = co.wheel_torque_r;
157  otpw[WHEEL_LF] = co.wheel_torque_l;
158  otpw[WHEEL_RF] = co.wheel_torque_r;
159  break;
160  default:
161  THROW_EXCEPTION("Unexpected number of wheels!");
162  };
163  }
164  return otpw;
165 }
166 
168 {
169  if (controller_) controller_->on_post_step(context);
170 }
171 
172 // See docs in base class:
174 {
175  mrpt::math::TTwist2D odo_vel;
176  // Equations:
177 
178  // Velocities in local +X at each wheel i={0,1}:
179  // v_i = vx - w_veh * wheel_{i,y} = w_i * R_i
180  // Re-arranging:
181  const double w0 = wheels_info_[WHEEL_L].getW();
182  const double w1 = wheels_info_[WHEEL_R].getW();
183  const double R0 = wheels_info_[WHEEL_L].diameter * 0.5;
184  const double R1 = wheels_info_[WHEEL_R].diameter * 0.5;
185 
186  const double Ay = wheels_info_[WHEEL_L].y - wheels_info_[WHEEL_R].y;
187  ASSERTMSG_(
188  Ay != 0.0,
189  "The two wheels of a differential vehicle cannot be at the same Y "
190  "coordinate!");
191 
192  const double w_veh = (w1 * R1 - w0 * R0) / Ay;
193  const double vx_veh = w0 * R0 + w_veh * wheels_info_[WHEEL_L].y;
194 
195  odo_vel.vx = vx_veh;
196  odo_vel.vy = 0.0;
197  odo_vel.omega = w_veh;
198 
199  return odo_vel;
200 }
mvsim
Definition: Client.h:21
mvsim::VehicleBase::chassis_z_max_
double chassis_z_max_
Definition: VehicleBase.h:187
mvsim::DynamicsDifferential::WHEEL_L
@ WHEEL_L
Definition: VehicleDifferential.h:37
mvsim::VehicleBase::fixture_wheels_
std::vector< b2Fixture * > fixture_wheels_
Definition: VehicleBase.h:208
mvsim::DynamicsDifferential::ControllerTwistIdeal::class_name
static const char * class_name()
Definition: VehicleDifferential.h:165
mvsim::TParamEntry
Definition: TParameterDefinitions.h:38
mvsim::VehicleBase::chassis_mass_
double chassis_mass_
Definition: VehicleBase.h:180
mvsim::VehicleBase::chassis_color_
mrpt::img::TColor chassis_color_
Definition: VehicleBase.h:189
World.h
mvsim::DynamicsDifferential::TControllerOutput::wheel_torque_r
double wheel_torque_r
Definition: VehicleDifferential.h:84
mvsim::DynamicsDifferential::WHEEL_RR
@ WHEEL_RR
Definition: VehicleDifferential.h:43
mvsim::DynamicsDifferential::TControllerOutput
Definition: VehicleDifferential.h:79
mvsim::VehicleBase::wheels_info_
std::deque< Wheel > wheels_info_
Definition: VehicleBase.h:201
xml_utils.h
mvsim::DynamicsDifferential::invoke_motor_controllers
virtual std::vector< double > invoke_motor_controllers(const TSimulContext &context) override
Definition: VehicleDifferential.cpp:128
VehicleDifferential.h
mvsim::DynamicsDifferential::controller_
ControllerBase::Ptr controller_
The installed controller.
Definition: VehicleDifferential.h:220
rapidxml::xml_attribute< char >
mvsim::DynamicsDifferential::TControllerOutput::wheel_torque_l
double wheel_torque_l
Definition: VehicleDifferential.h:83
mvsim::DynamicsDifferential::configPerWheel_
const std::vector< ConfigPerWheel > configPerWheel_
Defined at ctor time:
Definition: VehicleDifferential.h:217
mvsim::DynamicsDifferential::WHEEL_LR
@ WHEEL_LR
Definition: VehicleDifferential.h:42
mvsim::DynamicsDifferential::DynamicsDifferential
DynamicsDifferential(World *parent)
Definition: VehicleDifferential.h:60
mvsim::DynamicsDifferential::WHEEL_RF
@ WHEEL_RF
Definition: VehicleDifferential.h:45
mvsim::TSimulContext
Definition: basic_types.h:58
rapidxml::xml_node::first_node
xml_node< Ch > * first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:936
mvsim::DynamicsDifferential::WHEEL_LF
@ WHEEL_LF
Definition: VehicleDifferential.h:44
mvsim::TParameterDefinitions
std::map< std::string, TParamEntry > TParameterDefinitions
Definition: TParameterDefinitions.h:64
mvsim::Simulable::name_
std::string name_
Definition: Simulable.h:145
mvsim::DynamicsDifferential::dynamics_load_params_from_xml
virtual void dynamics_load_params_from_xml(const rapidxml::xml_node< char > *xml_node) override
Definition: VehicleDifferential.cpp:48
mvsim::DynamicsDifferential::getVelocityLocalOdoEstimate
virtual mrpt::math::TTwist2D getVelocityLocalOdoEstimate() const override
Definition: VehicleDifferential.cpp:173
mvsim::World
Definition: World.h:82
mvsim::DynamicsDifferential::TControllerInput::context
TSimulContext context
Definition: VehicleDifferential.h:76
mvsim::VehicleBase::getNumWheels
size_t getNumWheels() const
Definition: VehicleBase.h:82
mvsim::VehicleBase
Definition: VehicleBase.h:44
rapidxml::xml_node< char >
mvsim::DynamicsDifferential::WHEEL_R
@ WHEEL_R
Definition: VehicleDifferential.h:38
std
mvsim::VehicleBase::chassis_poly_
mrpt::math::TPolygon2D chassis_poly_
Definition: VehicleBase.h:181
mvsim::DynamicsDifferential::WHEEL_CASTER_FRONT
@ WHEEL_CASTER_FRONT
Definition: VehicleDifferential.h:40
mvsim::parse_xmlnode_shape
void parse_xmlnode_shape(const rapidxml::xml_node< char > &xml_node, mrpt::math::TPolygon2D &out_poly, const char *functionNameContext="")
Definition: xml_utils.cpp:258
mvsim::DynamicsDifferential::TControllerInput
Definition: VehicleDifferential.h:74
mvsim::DynamicsDifferential::ControllerTwistPID::class_name
static const char * class_name()
Definition: VehicleDifferential.h:115
mrpt::math
Definition: xml_utils.h:22
mvsim::VehicleBase::fixture_chassis_
b2Fixture * fixture_chassis_
Created at.
Definition: VehicleBase.h:204
rapidxml.hpp
mvsim::parse_xmlnode_attribs
void parse_xmlnode_attribs(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="")
Definition: xml_utils.cpp:182
rapidxml::xml_node::first_attribute
xml_attribute< Ch > * first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
Definition: rapidxml.hpp:1025
mvsim::VehicleBase::chassis_z_min_
double chassis_z_min_
Definition: VehicleBase.h:187
mvsim::VehicleBase::updateMaxRadiusFromPoly
void updateMaxRadiusFromPoly()
Definition: VehicleBase.cpp:577
mvsim::DynamicsDifferential::invoke_motor_controllers_post_step
virtual void invoke_motor_controllers_post_step(const TSimulContext &context) override
Definition: VehicleDifferential.cpp:167


mvsim
Author(s):
autogenerated on Wed May 28 2025 02:13:08