Skip to content

Commit df02e60

Browse files
committed
Add CasADi C++ API example
This commit adds a CasADi C++ API example of an Ackermann-steered robot navigating to a target waypoint within the prediction horizon. The example plots the planned trajectory and the control acutation. The commit includes a generalised C++ interface for the MPC controller together with an example executable and an updated CMake file to build said example. The commit also includes instructions on building the Matplot++ library, required for generating the trajectory and control actuation plots.
1 parent e792d9e commit df02e60

File tree

8 files changed

+852
-0
lines changed

8 files changed

+852
-0
lines changed

CMakeLists.txt

+20
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@ cmake_minimum_required(VERSION 3.8)
33
project(mpc_playground)
44

55
find_package(casadi REQUIRED)
6+
find_package(Matplot++ REQUIRED)
7+
8+
###############
9+
# MPC example #
10+
###############
11+
12+
add_executable(mpc_example
13+
"src/mpc_interface.cpp"
14+
"src/mpc_ms_ackermann.cpp"
15+
)
16+
17+
target_include_directories(mpc_example
18+
PUBLIC
19+
"include"
20+
)
21+
22+
target_link_libraries(mpc_example
23+
casadi
24+
Matplot++::matplot
25+
)
626

727
###############
828
# CasADi test #

README.md

+49
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ Codes are available here:
1818

1919
![Differential drive robot example controls plot](assets/img/dd-controls.png)
2020

21+
## Ackermann-steered robot
22+
23+
This example shows an Ackermann-steered robot using a 3 DOF vehicle model and a linear tire. The OCP is solved using multiple shooting.
24+
25+
Codes are available here:
26+
27+
* [Multiple shooting, Ackermann-steered robot (C++)](src/mpc_ms_ackermann.cpp)
28+
29+
![Ackermann robot example trajectory animation](assets/img/ack-trajectory.jpg)
30+
31+
![Ackermann robot example states plot](assets/img/ack-controls-1.jpg)
32+
33+
![Ackermann robot example controls plot](assets/img/ack-controls-2.jpg)
34+
2135
# Getting started
2236

2337
Clone the repository to a folder of your choice:
@@ -97,4 +111,39 @@ CasADi looks for the HSL solvers under a legacy name. You may be required to cre
97111
```shell
98112
cd /usr/lib/local
99113
ln -S libcoinhsl.so libhsl.so
114+
```
115+
116+
### (Optional) Building the Matplot++ library from sources
117+
118+
To generate plots at the end of the execution of the C++ examples, the [Matplot++](https://alandefreitas.github.io/matplotplusplus/) library is required. Below are instructions to build the Matplot++ library from sources on Ubuntu 22.04.
119+
120+
Install the required dependencies:
121+
122+
```shell
123+
sudo apt install -y cmake-curses-gui libfftw3-dev
124+
```
125+
126+
Clone the [alandefreitas/matplotplusplus](https://github.com/alandefreitas/matplotplusplus) in a folder of your choice (the home directory for the current user `~/` in these instructions):
127+
128+
```shell
129+
git clone https://github.com/alandefreitas/matplotplusplus ~/matplotplusplus
130+
```
131+
132+
Create a build folder and configure the build using CMake:
133+
134+
```shell
135+
mkdir -p ~/matplotplusplus/build/
136+
cd ~/matplotplusplus/build/
137+
ccmake ../
138+
```
139+
140+
Press `C` to configure your project. After configuring the project:
141+
142+
* Set `CMAKE_BUILD_TYPE` to `Release`
143+
* Set `BUILD_EXAMPLES` to `OFF`
144+
145+
Run the build and install processes:
146+
147+
```shell
148+
sudo make install -j$((`nproc`+1))
100149
```

assets/img/ack-controls-1.jpg

29.9 KB
Loading

assets/img/ack-controls-2.jpg

29.7 KB
Loading

assets/img/ack-trajectory.jpg

28 KB
Loading
+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include <string>
2+
3+
#include <casadi/casadi.hpp>
4+
5+
using namespace casadi;
6+
7+
namespace MPC {
8+
9+
class ModelPredictiveController {
10+
public:
11+
ModelPredictiveController();
12+
~ModelPredictiveController();
13+
double GetGoalXPosition();
14+
double GetGoalYPosition();
15+
double GetLateralSpeedInitialValue();
16+
double SetLateralSpeedLowerBound();
17+
double GetLateralSpeedUpperBound();
18+
double GetLongitudinalAccelerationInitialValue();
19+
double GetLongitudinalAccelerationLowerBound();
20+
double GetLongitudinalAccelerationUpperBound();
21+
double GetLongitudinalJerkInitialValue();
22+
double GetLongitudinalJerkLowerBound();
23+
double GetLongitudinalJerkUpperBound();
24+
double GetLongitudinalSpeedInitialValue();
25+
double GetLongitudinalSpeedLowerBound();
26+
double GetLongitudinalSpeedUpperBound();
27+
std::vector<double> GetOptimalLongitudinalJerk();
28+
std::vector<double> GetOptimalSteeringRate();
29+
std::vector<double> GetOptimalTimeSpan();
30+
std::vector<double> GetOptimalXPosition();
31+
std::vector<double> GetOptimalYPosition();
32+
double GetSteeringAngleInitialValue();
33+
double GetSteeringAngleLowerBound();
34+
double GetSteeringAngleUpperBound();
35+
double GetSteeringRateInitialValue();
36+
double GetSteeringRateLowerBound();
37+
double GetSteeringRateUpperBound();
38+
double GetXPositionInitialValue();
39+
double GetXPositionLowerBound();
40+
double GetXPositionUpperBound();
41+
double GetYPositionInitialValue();
42+
double GetYPositionLowerBound();
43+
double GetYPositionUpperBound();
44+
double GetYawInitialValue();
45+
double GetYawLowerBound();
46+
double GetYawUpperBound();
47+
double GetYawRateInitialValue();
48+
double GetYawRateLowerBound();
49+
double GetYawRateUpperBound();
50+
void Initialise();
51+
void Plan();
52+
void SetFrontAxleCentreOfGravityDistance(double d_a);
53+
void SetFrontAxleCorneringStiffness(double c_alpha_f);
54+
void SetGoalXPosition(double goal_x);
55+
void SetGoalYaw(double goal_psi);
56+
void SetGoalYPosition(double goal_y);
57+
void SetLateralSpeedInitialValue(double v_0);
58+
void SetLateralSpeedLowerBound(double v_low);
59+
void SetLateralSpeedUpperBound(double v_up);
60+
void SetLinearSolver(std::string linear_solver);
61+
void SetLinearSolverTolerance(double tol);
62+
void SetLinearSolverMaximumIterations(int max_iters);
63+
void SetLongitudinalAccelerationInitialValue(double a_0);
64+
void SetLongitudinalAccelerationLowerBound(double a_low);
65+
void SetLongitudinalAccelerationUpperBound(double a_up);
66+
void SetLongitudinalJerkInitialValue(double j_0);
67+
void SetLongitudinalJerkLowerBound(double j_low);
68+
void SetLongitudinalJerkUpperBound(double j_up);
69+
void SetLongitudinalSpeedInitialValue(double u_0);
70+
void SetLongitudinalSpeedLowerBound(double u_low);
71+
void SetLongitudinalSpeedUpperBound(double u_up);
72+
void SetMass(double m);
73+
void SetRearAxleCorneringStiffness(double c_alpha_r);
74+
void SetRearAxleCentreOfGravityDistance(double d_b);
75+
void SetSteeringAngleInitialValue(double delta_0);
76+
void SetSteeringAngleLowerBound(double delta_low);
77+
void SetSteeringAngleUpperBound(double delta_up);
78+
void SetSteeringRateInitialValue(double delta_dot_0);
79+
void SetSteeringRateLowerBound(double delta_dot_low);
80+
void SetSteeringRateUpperBound(double delta_dot_up);
81+
void SetXPositionInitialValue(double x_0);
82+
void SetXPositionLowerBound(double x_low);
83+
void SetXPositionUpperBound(double x_up);
84+
void SetYPositionInitialValue(double y_0);
85+
void SetYPositionLowerBound(double y_low);
86+
void SetYPositionUpperBound(double y_up);
87+
void SetYawInitialValue(double psi_0);
88+
void SetYawLowerBound(double psi_low);
89+
void SetYawMomentOfInertia(double i_zz);
90+
void SetYawRateInitialValue(double r_0);
91+
void SetYawRateLowerBound(double r_low);
92+
void SetYawRateUpperBound(double r_up);
93+
void SetYawUpperBound(double psi_up);
94+
void UpdateObjectiveFunction();
95+
private:
96+
SX a_ = SX::sym("a");
97+
double a_0_ = 0.0;
98+
double a_low_ = -inf;
99+
double a_up_ = inf;
100+
double c_alpha_f_ = -5.0e4;
101+
double c_alpha_r_ = -5.0e4;
102+
SX controls_;
103+
int controls_count_;
104+
double d_a_ = 1.0;
105+
double d_b_ = 1.0;
106+
SXDict dae_;
107+
SX delta_ = SX::sym("delta");
108+
double delta_0_ = 0.0;
109+
double delta_low_ = -inf;
110+
double delta_up_ = inf;
111+
SX delta_dot_ = SX::sym("delta_dot");
112+
double delta_dot_0_ = 0.0;
113+
double delta_dot_low_ = -inf;
114+
std::vector<double> delta_dot_opt_;
115+
double delta_dot_up_ = inf;
116+
double epsilon_ = 1.0e-4;
117+
double goal_psi_ = 0.0;
118+
double goal_x_ = 0.0;
119+
double goal_y_ = 0.0;
120+
double i_zz_ = 1.0e4;
121+
Function integrator_;
122+
Function integrator_parallel_;
123+
Dict integrator_opts_;
124+
SX j_ = SX::sym("j");
125+
double j_0_ = 0.0;
126+
double j_low_ = -inf;
127+
std::vector<double> j_opt_;
128+
double j_up_ = inf;
129+
std::string linear_solver_ = "ma27";
130+
Dict nlp_opts_;
131+
int nodes_count_ = 10;
132+
double m_ = 1800;
133+
double max_iters_ = 25;
134+
SX ode_;
135+
MX phi_ = 0.0;
136+
SX psi_ = SX::sym("psi");
137+
double psi_0_ = 0.0;
138+
double psi_low_ = -inf;
139+
std::vector<double> psi_opt_;
140+
double psi_up_ = inf;
141+
SX quadrature_;
142+
SX r_ = SX::sym("r");
143+
double r_0_ = 0.0;
144+
double r_low_ = -inf;
145+
double r_up_ = inf;
146+
SX states_;
147+
int states_count_;
148+
std::vector<double> t_opt_;
149+
double time_span_ = 5.0;
150+
double tol_ = 1.0e-4;
151+
SX u_ = SX::sym("u");
152+
double u_0_ = 0.0;
153+
double u_low_ = -inf;
154+
double u_up_ = inf;
155+
SX v_ = SX::sym("v");
156+
double v_0_ = 0.0;
157+
double v_low_ = -inf;
158+
double v_up_ = inf;
159+
SX x_ = SX::sym("x");
160+
double x_0_ = 0.0;
161+
double x_low_ = -inf;
162+
std::vector<double> x_opt_;
163+
double x_up_ = inf;
164+
SX y_ = SX::sym("y");
165+
double y_0_ = 0.0;
166+
double y_low_ = -inf;
167+
std::vector<double> y_opt_;
168+
double y_up_ = inf;
169+
};
170+
171+
} // end namespace MPC

0 commit comments

Comments
 (0)