CasADi库C++用法整理学习---以NMPC代码为例

参考几个使用方法博客
1
官方文档写的很清楚

对SM,DM,XM数据类型疑惑。什么时候使用什么样的类型,还是都可以?

x = MX.sym(“x”)
这将创建一个 1×1 矩阵,即一个包含名为 x 的符号基元的标量。这只是显示名称,而不是标识符。多个变量可以具有相同的名称,但仍然不同。identifier 是返回值。您还可以通过向 SX.sym 提供其他参数来创建向量值或矩阵值符号变量:

在这里插入图片描述
在这里插入图片描述

#include <casadi/casadi.hpp>
using namespace casadi;
int main() {SX x = SX::sym("x");SX y = SX::sym("y",5);SX Z = SX::sym("Z",4,2)SX f = pow(x,2) + 10;f = sqrt(f);std::cout << "f: " << f << std::endl;return 0;
}//sqrt((10+sq(x)))

DM 与 SX 非常相似,但不同之处在于非零元素是数值,而不是符号表达式。语法也是相同的,除了 SX.sym 等函数没有等效项。
DM 主要用于将矩阵存储在 CasADi 中,并用作函数的输入和输出。它不用于计算密集型计算。

MX 类型允许像 SX 一样构建由一系列基本操作组成的表达式。但与 SX 不同的是,这些初等运算并不局限于标量一元或二进制运算(R→R 或 R×R→R)。相反,用于形成 MX 表达式的基本运算可以是通用的多个稀疏矩阵值输入、多个稀疏矩阵值输出函数:Rn1×m1×…×RnN×mN→Rp1×q1×…×RpM×qM

  • SX和,MX两者对比
    在这里插入图片描述
    在这里插入图片描述

请注意,结果仅包含使用 MX 符号的两次运算(一次乘法和一次加法),而 SX 等效项则有八次运算(结果矩阵的每个元素两次)。因此,在处理具有许多元素的自然向量或矩阵值运算时,MX 可能更经济。
不能将 SX 对象与 MX 对象相乘,也不能执行任何其他操作来在同一表达式图中混合两者。但是,您可以在 MX 图中包含对 SX 表达式定义的 Function 的调用。

MPC 代码
注意:opti.subject_to,opti.minimize,MX::mtimes,opti.variable,opti.parameter都是怎么用的
总的来说:

opti.variable: 定义变量。
opti.parameter: 定义参考值,已知的常量。
opti.set_value: 设置参数的具体值。
opti.minimize: 定义目标函数。
opti.subject_to: 添加约束条件。
MX::mtimes: 执行矩阵乘法。
#include "mpc_tracking/mpc.h"Mpc::Mpc() {N_ = 10;dt_ = 0.1;u_max_ = 1;w_max_ = 0.5;vector<double> weights = {1,1,1,2,2}; //Q,Ru_min_ = - u_max_;w_min_ = - w_max_;Q_ = DM::zeros(3,3); //索引之前初始化sizeR_ = DM::zeros(2,2);setWeights(weights);kinematic_equation_ = setKinematicEquation();
}
Mpc::~Mpc() {}void Mpc::setWeights(vector<double> weights) {//cout << "setweights" << endl;Q_(0, 0) = weights[0];Q_(1, 1) = weights[1];Q_(2, 2) = weights[2];R_(0, 0) = weights[3];R_(1, 1) = weights[4];//R_(2, 2) = weights[5];//cout << "set weight finish" << endl;}Function Mpc::setKinematicEquation() {//cout << "set kinematic" << endl;MX x = MX::sym("x");MX y = MX::sym("y");MX theta = MX::sym("theta");MX state_vars = MX::vertcat({x, y, theta});  //将状态变量组合成一个垂直向量(列向量)。MX v = MX::sym("v");MX w = MX::sym("w");MX control_vars = MX::vertcat({v, w});  //控制变量control_vars是一个包含两个元素的垂直向量,分别是v(线速度)和w(角速度)//rhs means right hand sideMX rhs = MX::vertcat({v * MX::cos(theta), v * MX::sin(theta), w}); // 动力学方程return Function("kinematic_equation", {state_vars, control_vars}, {rhs});// MX x = MX::sym("x");// MX y = MX::sym("y");// MX theta = MX::sym("theta");// MX state_vars = MX::vertcat({x, y, theta});// MX u = MX::sym("u");// MX v = MX::sym("v");// MX w = MX::sym("w");// MX control_vars = MX::vertcat({u, v, w});// MX rhs = u * MX::cos(theta) - v * MX::sin(theta); //这个方程描述了一个更复杂的非线性系统,例如四轮独立驱动的车辆或具有横向控制输入的系统// rhs = MX::vertcat({rhs, u * MX::sin(theta) + v * MX::cos(theta), w});// return Function("kinematic_equation", {state_vars, control_vars}, {rhs});
}bool Mpc::solve(Eigen::Vector3d current_states, Eigen::MatrixXd desired_states) {//cout << "jinqiujiele" << endl;Opti opti = Opti();Slice all;MX cost = 0;X = opti.variable(3, N_ + 1);// 定义一个3行N_+1列的矩阵变量X 注意:是变量。//第一个时间步(索引为0)表示当前时刻的状态 后面N_个时间步表示未来N_个时刻的状态和U对应U = opti.variable(2, N_);MX x = X(0, all);MX y = X(1, all);MX theta = X(2, all);MX v = U(0, all);MX w = U(1, all);//MX w = U(2, all);MX X_ref = opti.parameter(3, N_ + 1);   // 定义一个3行N_+1列的参数矩阵X_ref 注意:是已知的常量MX X_cur = opti.parameter(3);DM x_tmp1 = {current_states[0], current_states[1], current_states[2]};opti.set_value(X_cur, x_tmp1);  //set current state opti.set_value 用于设置参数的具体值cout << "set current state success" << endl;//按列索引vector<double> X_ref_v(desired_states.data(), desired_states.data() + desired_states.size());//auto tp1 = std::chrono::steady_clock::now();DM X_ref_d(X_ref_v);//X_ref_d.resize(3, N_ + 1);//cout << "desired_states:" << desired_states << endl;//cout << "X_ref_v:" << X_ref_v << endl;//cout << "X_ref_d:" << X_ref_d << endl;// DM x_tmp2(3, N_ + 1);// for (int i = 0; i < 3; ++i) {//     for (int j = 0; j <= N_; ++j) {//         x_tmp2(i, j) = desired_states(i, j);//     }// }X_ref = MX::reshape(X_ref_d, 3, N_ + 1);//opti.set_value(X_ref, X_ref_d);  //set reference traj// auto tp2 = std::chrono::steady_clock::now();// cout <<"set trajectory time:" // << chrono::duration_cast<chrono::microseconds>(tp2 - tp1).count() // << "microseconds" << endl;//cout << "set reference traj success" << endl;//cout << "x_ref:" << X_ref.size() << endl;//set costfunctionfor (int i = 0; i < N_; ++i) {MX X_err = X(all, i) - X_ref(all, i); MX U_0 = U(all, i);//cout << "U_0 size:" << U_0.size() << endl;//cout << "cost size:" << cost_.size() << endl;cost += MX::mtimes({X_err.T(), Q_, X_err}); //目标函数是状态误差和控制输入的成本之和//cout << "cost size:" << cost_.size() << endl; cost += MX::mtimes({U_0.T(), R_, U_0});//cout << "cost size:" << cost_.size() << endl;}//cout << "cost size:" << cost_.size() << endl;//MX::mtimes 用于执行矩阵乘法,用于计算两个矩阵的乘积cost += MX::mtimes({(X(all, N_) - X_ref(all, N_)).T(), Q_,X(all, N_) - X_ref(all, N_)});  //终端项//cout << "cost:" << cost << endl;opti.minimize(cost); //opti.minimize 用于定义优化问题的目标函数//cout << "set cost success" << endl;//kinematic constrains opti.subject_to 用于添加约束条件到优化问题中for (int i = 0; i < N_; ++i) {vector<MX> input(2);input[0] = X(all, i);input[1] = U(all, i);MX X_next = kinematic_equation_(input)[0] * dt_ + X(all, i); //这里体现了模型预测控制,模型。  下一步的状态=通过模型计算的速度* dt_ +当前状态opti.subject_to(X_next == X(all, i + 1));  // 动力学约束}//init value 初始化,初始状态赋值第一列所有行opti.subject_to(X(all, 0) == X_cur);//第一个时间步(索引为0)表示当前时刻的状态//speed angle_speed limit 控制输入的约束opti.subject_to(0 <= v <= u_max_);opti.subject_to(w_min_ <= w <= w_max_);//set solvercasadi::Dict solver_opts; // 设置求解器选项solver_opts["expand"] = true; //MX change to SX for speed upsolver_opts["ipopt.max_iter"] = 100;solver_opts["ipopt.print_level"] = 0;solver_opts["print_time"] = 0;solver_opts["ipopt.acceptable_tol"] = 1e-6;solver_opts["ipopt.acceptable_obj_change_tol"] = 1e-6;opti.solver("ipopt", solver_opts);//auto sol = opti.solve();solution_ = std::make_unique<casadi::OptiSol>(opti.solve());return true;
}
vector<double> Mpc::getFirstU() {vector<double> res;auto first_v =  solution_->value(U)(0, 0);auto first_w = solution_->value(U)(1, 0);//cout << "first_u" << first_u << " " << "first_v" << first_v << endl;res.push_back(static_cast<double>(first_v));res.push_back(static_cast<double>(first_w));return res;
}vector<double> Mpc::getPredictX() {vector<double> res;auto predict_x = solution_->value(X);cout << "nomal" << endl;//cout << "predict_x size :" << predict_x.size() << endl;for (int i = 0; i <= N_; ++i) {res.push_back(static_cast<double>(predict_x(0, i)));res.push_back(static_cast<double>(predict_x(1, i)));}return res;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/881988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关键词提取技术:TF-IDF 详解

1. 什么是TF-IDF&#xff1f; TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09; 是一种统计方法&#xff0c;用于评估单词在文档集或语料库中的重要性。它是自然语言处理和信息检索中的核心技术之一。 TF-IDF主要基于以下两个概念&#xff1a; TF&a…

书籍推荐:《从零构建大型语言模型》附免费PDF下载

通过从头开始构建一个大型语言模型&#xff0c;了解如何创建、训练和调整大型语言模型 &#xff08;LLMs&#xff09;&#xff01; 一、构建大型语言模型&#xff08;从头开始&#xff09; 在《构建大型语言模型&#xff08;从头开始&#xff09;》中&#xff0c;你将了解如何…

C++ —— 关于继承(inheritance)

目录 1. 继承的概念及定义 1.1 继承的概念 1.2 继承的定义格式 1.3 继承基类成员访问方式的变化 1.4 类模板的继承 2.基类与派生类的转换 3. 继承中的作用域 3.1 隐藏规则 4. 派⽣类的默认成员函数 4.1 4个常见默认成员函数 4.2 实现⼀个不能被继承的类 5. 继承与友元…

webpack 学习入门

webpack 1. 简介1.1 webpack 是什么1.2 webpack 五个核心概念1.2.1 入口 - Entry1.2.2 出口 - Output1.2.3 Loader1.2.4 插件 - Plugins1.2.6 模式 - Mode 2. webpack 初体验2.1 初始化配置2.1.1. 准备2.1.2. 写代码2.1.3 编译打包应用 3. webpack 开发环境的基本配置3.1 打包样…

HTML(七)表格

https://chatgai.lovepor.cn/ 在HTML中&#xff0c;表格的标准形式如下&#xff1a; <table></table> 使用上面的语言&#xff0c;就已经生成了一个表格&#xff0c;只不过这个表格什么都没有 那么&#xff0c;该如何让表格存在东西呢&#xff1f; 首先&#xf…

springboot 整合spring ai实现 基于知识库的客服问答

rag 需求产生的背景介绍&#xff1a; 在使用大模型时&#xff0c;常遇到的问题之一是模型可能产生幻觉&#xff0c;即生成的内容缺乏准确性。此外&#xff0c;由于大模型不直接访问企业的专有数据&#xff0c;其响应可能会显得泛泛而谈&#xff0c;不够精准或具体&#xff0c;…

基于YOLOv10的农场实时目标检测系统(python+pyside6界面+系统源码+可训练的数据集+也完成的训练模型)

摘要&#xff1a; 基于YOLOv10的农场实时目标检测系统&#xff0c;利用4393张图片&#xff08;3905张训练集&#xff0c;488张验证集&#xff09;进行模型训练&#xff0c;最终开发出一个高效的农场目标检测模型。为了方便用户操作和实时检测&#xff0c;本系统还开发了基于Pyt…

VSCode运行QT界面

VSCode用久了,感觉Qt Creator的写起代码来还是不如VSCode得心应手,虽然目前还是存在一些问题,先把目前实现的状况做个记录,后续有机会再进一步优化。 当前方式 通过QtCreator创建一个CMake项目,然后使用CMake的方式在VSCode中进行编译。 claude给出的建议 左上角的名字会…

SiLM27212 270V 4A/4A 支持高频信号输入 集成自举二极管的高低边门极驱动器

SiLM27212系列选型&#xff1a; SiLM27212LEK-DG SiLM27212EK-DG SiLM27212LCA-DG SiLM27212CA-DG SiLM27212LCB-DG SiLM27212CB-DG SiLM27212系列是一款支持高频信号输入的高低边N沟道MOSFET驱动器&#xff0c;有着优异的性能&#xff0c;广泛应用于各类模…

Linux查看下nginx及使用的配置文件

1、查到nginx进程 ps -aef | grep nginx2、通过进行pid查到nginx路径 pwdx <pid>3、根据路径得到配置文件 path***/nginx -t如下&#xff1a;

MacOS虚拟机安装Windows停滞在“让我们为你连接到网络”,如何解决?

1. 问题描述 MacOS在虚拟机安装win11过程中&#xff0c;停止在“让我们为你连接到网络”步骤&#xff0c;页面没有任何可以点击的按钮&#xff0c;进行下一步操作。 2. 解决方案&#xff08;亲测有效&#xff09; 到达该界面&#xff0c;按下ShiftF10&#xff08;Windows&…

【机器学习】深入浅出讲解贝叶斯分类算法

0. 前言 1.贝叶斯分类器介绍 贝叶斯分类是一类分类算法的总称&#xff0c;这类算法均以贝叶斯定理为基础&#xff0c;故统称为贝叶斯分类。而朴素贝叶斯&#xff08;Naive Bayes&#xff09;分类是贝叶斯分类中最简单&#xff0c;也是常见的一种分类方法。 一些很常见的分类…

整理—计算机网络

目录 网络OSI模型和TCP/IP模型 应用层有哪些协议 HTTP报文有哪些部分 HTTP常用的状态码 Http 502和 504 的区别 HTTP层请求的类型有哪些&#xff1f; GET和POST的使用场景&#xff0c;有哪些区别&#xff1f; HTTP的长连接 HTTP默认的端口是什么&#xff1f; HTTP1.1怎…

哪科竞赛含金量更高?五大学科竞赛含金量排名

2024年五大学科竞赛赛事已经渐渐拉开帷幕&#xff0c;本月底国内不少地区即将举行生物竞赛预赛的赛事。今天我们一起来看看五大学科竞赛哪科竞赛含金量更高。 高中五大学科竞赛&#xff08;数物化生信&#xff09;是升学路上的硬通货&#xff0c;比如说在强基破格中需要五大竞赛…

揭秘提升3DMAX效率的6款必备神级插件!

对于3DMax新手来说,掌握一些高效、实用的插件能够大大提升工作效率和创作质量。以下是6个不能错过的神级插件推荐: 第1个:3DMAX造山地形插件Mountain是一款专为3dMax设计的插件,旨在帮助用户轻松快速地创建逼真的山脉地形。以下是对该插件的详细介绍: 一、插件概述 Mou…

Xilinx远程固件升级(一)——QuickBoot方案

Xilinx 7系FPGA远程更新方案——QuickBoot方式远程更新bit 一、远程更新背景和架构 对于非ZYNQ系列的常规FPGA来说&#xff0c;对于bit的更新一般使用JTAG进行烧录。而作为商用产品&#xff0c;想要进行OTA升级时&#xff0c;使用JTAG的升级方式显然不适合&#xff0c;因此&a…

Java | Leetcode Java题解之第486题预测赢家

题目&#xff1a; 题解&#xff1a; class Solution {public boolean PredictTheWinner(int[] nums) {int length nums.length;int[] dp new int[length];for (int i 0; i < length; i) {dp[i] nums[i];}for (int i length - 2; i > 0; i--) {for (int j i 1; j …

计算机毕业设计Python动漫视频分析可视化 动漫影视可视化 动漫情感分析 动漫爬虫 机器学习 深度学习 Tensorflow PyTorch LSTM模型

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系名片 &#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系名片 &#xff01; 温馨提示&#xff1a;文末有SDN 平台官方提供的学长联系名片 &#xff01; 基于Python的B站排行榜大数据分析与可视化系统…

最短路问题之dijikstra算法

//根据bfs修改而来 #include<stdio.h> #include<stdlib.h> typedef struct queue {int data;struct queue* next; }queue, * linklist; float dist_list[9]; //出发点为0 int forward_point_list[9] { -1 }; linklist front NULL; linklist rear NULL; float ma…

计算机的错误计算(一百二十五)

摘要 探讨算式 的计算精度问题。 例1. 已知 计算 不妨在 Excel 的单元格中计算&#xff0c;则有&#xff1a; 若在 Python 中计算&#xff0c;则似乎有更为精确的结果&#xff1a; 然而&#xff0c;16位的正确值是 0.3499999999999998e1&#xff08;ISRealsoft 提供&a…