Skip to content

Commit b0c826d

Browse files
committed
doc: more details in manual C code gen example
1 parent 9529eae commit b0c826d

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ModelPredictiveControl"
22
uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c"
3-
version = "2.4.1"
3+
version = "2.4.2"
44
authors = ["Francis Gagnon"]
55

66
[deps]

docs/src/manual/linmpc.md

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ Note that measured disturbances are assumed constant in the future by default bu
297297
## Generating C code
298298

299299
The [`LinearMPC.jl`](@extref LinearMPC) package extension provides code generation
300-
capabilities to export the controller as optimized C code. First, install the package with:
300+
capabilities to export the controller as optimized and standalone C code. First, install the
301+
package with:
301302

302303
```test
303304
using Pkg; Pkg.add("LinearMPC")
@@ -308,6 +309,7 @@ The feedforward MPC controller can be converted to a [`LinearMPC.MPC`](@ref) obj
308309
```@example 1
309310
import LinearMPC
310311
c_mpc_d = LinearMPC.MPC(mpc_d);
312+
nothing # hide
311313
```
312314

313315
We test the converted controller in closed-loop to verify that it behaves identically to the
@@ -350,11 +352,43 @@ can now generate the C code using:
350352
LinearMPC.codegen(c_mpc_d; dir="codegen", fname="mpc_funcs")
351353
```
352354

353-
The three C functions to call at each control periods are declared in the generated file
354-
`codegen/mpc_funcs.h`:
355+
The three C functions to call at each control period are declared in the generated
356+
`codegen/mpc_funcs.h` file, and they receive pointers of `c_float` arrays:
355357

356358
```C
357-
void mpc_correct_state(c_float* state, c_float* measurement, c_float* distrubance);
359+
void mpc_correct_state(c_float* state, c_float* measurement, c_float* disturbance);
358360
int mpc_compute_control(c_float* control, c_float* state, c_float* reference, c_float* disturbance);
359361
void mpc_predict_state(c_float* state, c_float* control, c_float* disturbance);
360362
```
363+
364+
For example, on Linux, you can add the following code in a new `main.c` file:
365+
366+
```C
367+
#include "mpc_funcs.h"
368+
#include <stdio.h>
369+
int main(){
370+
// initialize arrays:
371+
c_float u[2] = {20, 20};
372+
c_float x[6] = {0, 0, 0, 0, 0, 0};
373+
c_float r[2] = {50, 35};
374+
c_float y[2] = {50, 30};
375+
c_float d[1] = {20};
376+
// execute one control period:
377+
mpc_correct_state(x, y, d);
378+
mpc_compute_control(u, x, r, d);
379+
mpc_predict_state(x, u, d);
380+
// print the computed control:
381+
printf("The computed u value is: [%f, %f]\n", u[0], u[1]);
382+
return 0;
383+
}
384+
```
385+
386+
compile with using `gcc *.c -o main.bin` and run it with `./main.bin`. The printed `u` value
387+
should be identical to:
388+
389+
```@example 1
390+
LinearMPC.set_state!(c_mpc_d, zeros(c_mpc_d.model.nx))
391+
x̂ = LinearMPC.correct_state!(c_mpc_d, [50, 30], [20])
392+
u = LinearMPC.compute_control(c_mpc_d, x̂; r=[50, 35], d=[20], uprev=[20, 20])
393+
println("The computed u value is: $(round.(u, digits=6))")
394+
```

0 commit comments

Comments
 (0)