VehicleDifferential_ControllerTwistPID.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 
11 
12 #include "xml_utils.h"
13 
14 using namespace mvsim;
15 using namespace std;
16 
18  : ControllerBase(veh)
19 {
20  // Get distance between wheels:
21  // Warning: the controller *assumes* that both wheels are parallel (as it's
22  // a rule in differential robots!!)
23  distWheels_ = veh_.wheels_info_[0].y - veh_.wheels_info_[1].y;
24  ASSERT_(distWheels_ > 0);
25 }
26 
27 // See base class docs
30 {
31  const auto sp = setpoint();
32 
33  // For each wheel:
34  // 1) Compute desired velocity set-point (in m/s)
35  // 2) Run the PI/PID for that wheel independently (in newtons)
36  const double spVelL = sp.vx - 0.5 * sp.omega * distWheels_;
37  const double spVelR = sp.vx + 0.5 * sp.omega * distWheels_;
38 
39  // Compute each wheel actual velocity (from an "odometry" estimation of
40  // velocity, not ground-truth!):
41  const mrpt::math::TTwist2D vehVelOdo = veh_.getVelocityLocalOdoEstimate();
42  const double actVelL = vehVelOdo.vx - 0.5 * vehVelOdo.omega * distWheels_;
43  const double actVelR = vehVelOdo.vx + 0.5 * vehVelOdo.omega * distWheels_;
44 
45  // Apply controller:
46  for (auto& pid : PIDs_)
47  {
48  pid.KP = KP;
49  pid.KI = KI;
50  pid.KD = KD;
51  pid.max_out = max_torque;
52  }
53 
54  // "-" because \tau<0 makes robot moves forwards.
55  const double followErrorL = spVelL - actVelL;
56  const double followErrorR = spVelR - actVelR;
57 
58  const double zeroThres = 0.001; // m/s
59 
60  if (std::abs(spVelL) < zeroThres && //
61  std::abs(spVelR) < zeroThres && //
62  std::abs(spVelR) < zeroThres && //
63  std::abs(spVelR) < zeroThres)
64  {
65  co.wheel_torque_l = 0;
66  co.wheel_torque_r = 0;
67  for (auto& pid : PIDs_) pid.reset();
68  }
69  else
70  {
71  co.wheel_torque_l = -PIDs_[0].compute(followErrorL, ci.context.dt);
72  co.wheel_torque_r = -PIDs_[1].compute(followErrorR, ci.context.dt);
73  }
74 }
75 
77 {
78  TParameterDefinitions params;
79  params["KP"] = TParamEntry("%lf", &KP);
80  params["KI"] = TParamEntry("%lf", &KI);
81  params["KD"] = TParamEntry("%lf", &KD);
82  params["max_torque"] = TParamEntry("%lf", &max_torque);
83 
84  // Initial speed.
85  params["V"] = TParamEntry("%lf", &setpoint_.vx);
86  params["W"] = TParamEntry("%lf_deg", &setpoint_.omega);
87 
88  parse_xmlnode_children_as_param(node, params);
89 }
90 
92  const TeleopInput& in, TeleopOutput& out)
93 {
95 
96  auto lck = mrpt::lockHelper(setpointMtx_);
97 
98  switch (in.keycode)
99  {
100  case 'W':
101  case 'w':
102  setpoint_.vx += 0.1;
103  break;
104 
105  case 'S':
106  case 's':
107  setpoint_.vx -= 0.1;
108  break;
109 
110  case 'A':
111  case 'a':
112  setpoint_.omega += 2.0 * M_PI / 180;
113  break;
114 
115  case 'D':
116  case 'd':
117  setpoint_.omega -= 2.0 * M_PI / 180;
118  break;
119 
120  case ' ':
121  {
122  setpoint_ = {0, 0, 0};
123  for (auto& pid : PIDs_) pid.reset();
124  }
125  break;
126  };
127 
128  out.append_gui_lines += "[Controller=" + std::string(class_name()) + "]";
129 
130  if (in.js && in.js->axes.size() >= 2)
131  {
132  const auto& js = in.js.value();
133  const float js_x = js.axes[0];
134  const float js_y = js.axes[1];
135 
136  setpoint_.vx = -js_y * joyMaxLinSpeed;
137  setpoint_.omega = -js_x * joyMaxAngSpeed;
138 
139  if (js.buttons.size() >= 7)
140  {
141  if (js.buttons[5]) joyMaxLinSpeed *= 1.01;
142  if (js.buttons[7]) joyMaxLinSpeed /= 1.01;
143 
144  if (js.buttons[4]) joyMaxAngSpeed *= 1.01;
145  if (js.buttons[6]) joyMaxAngSpeed /= 1.01;
146 
147  if (js.buttons[3]) // brake
148  {
149  setpoint_ = {0, 0, 0};
150  for (auto& pid : PIDs_) pid.reset();
151  }
152  }
153 
154  out.append_gui_lines += mrpt::format(
155  "Teleop joystick:\n"
156  "maxLinSpeed=%.03f m/s\n"
157  "maxAngSpeed=%.03f deg/s\n",
158  joyMaxLinSpeed, mrpt::RAD2DEG(joyMaxAngSpeed));
159  }
160  else
161  {
162  out.append_gui_lines +=
163  "Teleop keys:\n"
164  "w/s=forward/backward.\n"
165  "a/d=left/right.\n"
166  "spacebar=stop.\n";
167  }
168 
169  out.append_gui_lines += mrpt::format(
170  "setpoint: lin=%.03f ang=%.03f deg/s\n", setpoint_.vx, 180.0 / M_PI * setpoint_.omega);
171 }
mvsim
Definition: Client.h:21
mvsim::ControllerBaseTempl::teleop_interface
virtual void teleop_interface(const TeleopInput &in, TeleopOutput &out) override
Definition: ControllerBase.h:67
mvsim::TParamEntry
Definition: TParameterDefinitions.h:38
mvsim::parse_xmlnode_children_as_param
void parse_xmlnode_children_as_param(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="", mrpt::system::COutputLogger *logger=nullptr)
Definition: xml_utils.cpp:215
mvsim::ControllerBaseInterface::TeleopOutput::append_gui_lines
std::string append_gui_lines
Definition: ControllerBase.h:35
mvsim::DynamicsDifferential::TControllerOutput::wheel_torque_r
double wheel_torque_r
Definition: VehicleDifferential.h:84
mvsim::DynamicsDifferential::ControllerTwistPID::control_step
virtual void control_step(const DynamicsDifferential::TControllerInput &ci, DynamicsDifferential::TControllerOutput &co) override
Definition: VehicleDifferential_ControllerTwistPID.cpp:28
mvsim::DynamicsDifferential::ControllerTwistPID::load_config
virtual void load_config(const rapidxml::xml_node< char > &node) override
Definition: VehicleDifferential_ControllerTwistPID.cpp:76
mvsim::DynamicsDifferential::TControllerOutput
Definition: VehicleDifferential.h:79
xml_utils.h
VehicleDifferential.h
mvsim::TSimulContext::dt
double dt
timestep
Definition: basic_types.h:63
mvsim::DynamicsDifferential::TControllerOutput::wheel_torque_l
double wheel_torque_l
Definition: VehicleDifferential.h:83
mvsim::ControllerBaseTempl
Definition: ControllerBase.h:59
mvsim::TParameterDefinitions
std::map< std::string, TParamEntry > TParameterDefinitions
Definition: TParameterDefinitions.h:64
mvsim::ControllerBaseInterface::TeleopOutput
Definition: ControllerBase.h:33
mvsim::DynamicsDifferential::ControllerTwistPID::ControllerTwistPID
ControllerTwistPID(DynamicsDifferential &veh)
Definition: VehicleDifferential_ControllerTwistPID.cpp:17
mvsim::DynamicsDifferential::ControllerTwistPID::distWheels_
double distWheels_
Definition: VehicleDifferential.h:149
mvsim::DynamicsDifferential::TControllerInput::context
TSimulContext context
Definition: VehicleDifferential.h:76
rapidxml::xml_node< char >
std
mvsim::ControllerBaseInterface::TeleopInput
Definition: ControllerBase.h:25
mvsim::DynamicsDifferential::TControllerInput
Definition: VehicleDifferential.h:74
mvsim::ControllerBaseTempl::veh_
VEH_DYNAMICS & veh_
Definition: ControllerBase.h:124
mvsim::ControllerBaseInterface::TeleopInput::js
std::optional< TJoyStickEvent > js
Definition: ControllerBase.h:28
mvsim::ControllerBaseInterface::TeleopInput::keycode
int keycode
Definition: ControllerBase.h:27
mvsim::DynamicsDifferential::ControllerTwistPID::teleop_interface
virtual void teleop_interface(const TeleopInput &in, TeleopOutput &out) override
Definition: VehicleDifferential_ControllerTwistPID.cpp:91
mvsim::DynamicsDifferential
Definition: VehicleDifferential.h:30


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