跳到主要内容

Simulink部署

这里介绍了如何在Simulink中调用生成的代码.

这里以Windows系统为例, 介绍如何在Simulink中调用生成的代码. 其他平台的使用方法类似, 只需在Simulink中设置正确的编译器与链接库即可.

我们以轨迹跟踪控制问题为例, 该示例的文件结构如下:

working_dir/
├── traj_tracking/
│ ├── traj_tracking_prob.c
│ ├── traj_tracking_prob.h
│ ├── traj_tracking_solver.h
│ ├── libtraj_tracking_solver_static.lib
├── traj_tracking.py
├── traj_tracking_sim.slx
.

其中:

  • traj_tracking.py是模型文件, 该文件中定义了轨迹跟踪控制问题的模型, 以及代码生成的相关设置 (其中platform选择'windows-x86_64-mingw' (Windows平台) , lib_type选择'static' (静态链接库))
  • traj_tracking/ 是代码生成的目录
  • traj_tracking_sim.slx 是Simulink模型文件

前置工作

在Matlab中选择MinGW编译器, 以便生成的代码可以在Simulink中运行:

>> mex -setup
MEX configured to use 'MinGW64 Compiler (C)' for C language compilation.
注意

Matlab中选择的编译器需要兼容生成的求解器库, 否则会导致编译错误.

例如, 'windows-x86_64-mingw'对应生成的求解器库, 在Matlab中需要选择MinGW编译器. 其他编译器 (如Visual Studio) 会导致编译错误.

使用S-Function调用生成的代码

这里我们使用S-Function Builder来调用生成的代码. 具体步骤如下:

  1. 打开Simulink, 新建一个模型
  2. 在Simulink中添加一个S-Function Builder模块, 双击打开
  3. 在S-Function Builder的Editor中包含求解器的头文件
    #include "traj_tracking_prob.h"
    #include "traj_tracking_solver.h"
  4. 在S-Function Builder的Libraries中添加求解器的库文件
    • traj_tracking/加入到include path中
    • libtraj_tracking_solver_static.lib加入到libraries中
    • traj_tracking_prob.c加入到source files中 sfunction_lib

到这里, S-Function Builder中引入求解器的头文件与库文件已经完成, 下面轨迹跟踪控制问题相关的具体的设置:

  1. 在S-Function Builder的Ports and Parameters中定义该模块的输入输出端口, 这里我们定义了3个输入端口 (x0, xref_traj, yref) 和3个输出端口 (u, iter, solve_time):

    sfunction_io

  2. 在S-Function Builder的Editor中实现轨迹跟踪控制器的初始化, 求解与终止函数

  3. 点击Build按钮, 生成S-Function模块:

    sfunction_block

下面是S-Function Builder的Editor中填入的完整代码:

/* Includes_BEGIN */
#include "traj_tracking_prob.h"
#include "traj_tracking_solver.h"
#include <math.h>
/* Includes_END */

/* Externs_BEGIN */
static Traj_tracking_Problem prob;
static Traj_tracking_Option option;
static Traj_tracking_WorkSpace ws;
static Traj_tracking_Output output;
/* Externs_END */

void traj_tracking_controller_Start_wrapper(void)
{
/* Start_BEGIN */
traj_tracking_init(&prob, &option, &ws);
option.print_level = 0;
option.try_warm_start_barrier = 1;
/* Start_END */
}

void traj_tracking_controller_Outputs_wrapper(const real_T *x0,
const real_T *xref_traj,
const real_T *yref,
real_T *u,
int32_T *iter,
real_T *solve_time)
{
/* Output_BEGIN */
const double vref = 1.0;
const double ts_discretization = 0.2;
/* params */
prob.param[TRAJ_TRACKING_PARAM_XWEIGHT] = 1.0;
prob.param[TRAJ_TRACKING_PARAM_YWEIGHT] = 1.0;
prob.param[TRAJ_TRACKING_PARAM_VWEIGHT] = 1.0;

// initial state
prob.param[TRAJ_TRACKING_PARAM_X0] = x0[0];
prob.param[TRAJ_TRACKING_PARAM_Y0] = x0[1];
prob.param[TRAJ_TRACKING_PARAM_PHI0] = x0[2];
prob.param[TRAJ_TRACKING_PARAM_V0] = x0[3];

// reference trajectory
prob.param[TRAJ_TRACKING_PARAM_VREF] = vref;
for (size_t i = 0; i < TRAJ_TRACKING_DIM_N; i++) {
prob.param_stage[i][TRAJ_TRACKING_PARAM_STAGE_XREF] = xref_traj[i];
}
prob.param[TRAJ_TRACKING_PARAM_YREF] = yref[0];

// solve
traj_tracking_solve(&prob, &option, &ws, &output);

u[0] = output.primal.var[0][TRAJ_TRACKING_VAR_A];
u[1] = output.primal.var[0][TRAJ_TRACKING_VAR_DELTA];

iter[0] = output.iter;

solve_time[0] = output.solve_time;
/* Output_END */
}

void traj_tracking_controller_Terminate_wrapper(void)
{
/* Terminate_BEGIN */

/* Terminate_END */
}

运行Simulink模型

完成S-Function设置, 并且完成轨迹跟踪控制问题的闭环仿真搭建后, 运行Simulink模型即可.

整体闭环仿真框图如下图所示: sim

闭环仿真轨迹如下图所示: xy_path

附录

以下是本节中用到的文件:

需要运行traj_tracking.py生成代码, 然后在Simulink中打开traj_tracking_sim_2017a.slx文件, 运行仿真.