TinyMPC 使用教程(二)

news2024/12/28 23:59:07

系列文章目录


前言


 一、如何使用 TinyMPC

1.1 加载程序库

import tinympc
import numpy as np

tinympc_python_dir = "/path/to/tinympc-python"
tinympc_dir = tinympc_python_dir + "/tinympc/TinyMPC"

prob = tinympc.TinyMPC()
prob.compile_lib(tinympc_dir)

os_ext = ".so" # 
lib_dir = tinympc_dir + "/build/src/tinympc/libtinympcShared" + os_ext  # Path to the compiled library
prob.load_lib(lib_dir)

1.2 设置问题

        查看模型,学习如何获得 A 和 B 矩阵。

        对于车杆,我们使用离散车杆动力学的线性化模型来稳定直立位置。

n = 4  # states: x, xdot, theta, thetadot
m = 1  # controls: force on cart
N = 10  # horizon

A = [ # row-major order 
    1, 0, 0, 0, 
    0.01, 1, 0, 0, 
    2.2330083403-5, 0.0044662105, 1.0002605176, 0.0521057900,
    7.4430379746-8, 2.2330083403-5, 0.0100008683, 1.0002605176
]
B = [ # row-major order
    7.4683685627-5,
    0.0149367653,
    3.7976332318-5,
    0.0075955962
]

Q = [10.0, 1, 10, 1]  # diagonal elements in row-major order
R = [1.0]  # diagonal elements in row-major order
rho = 0.1  # ADMM penalty parameter

x_min = [-5.0] * n * N  # state constraints
x_max = [5.] * n * N  # state constraints
u_min = [-5.] * m * (N - 1)  # force constraints
u_max = [5.] * m * (N - 1)  # force constraints

abs_pri_tol = 1.0e-3  # absolute primal tolerance
abs_dual_tol = 1.0e-3  # absolute dual tolerance
max_iter = 100  # maximum number of iterations
check_termination = 1  # how often termination conditions are checked

# Setup problem data
prob.setup(n, m, N, A, B, Q, R, x_min, x_max, u_min, u_max, rho,
    abs_pri_tol, abs_dual_tol, max_iter, check_termination)

1.3 生成求解器代码

        我们生成了可在嵌入式硬件上部署的低级 C++ 代码。

output_dir = tinympc_python_dir + "/generated_code"  # Path to the generated code
prob.tiny_codegen(tinympc_dir, output_dir)
prob.compile_lib(output_dir)

prob.load_lib(output_dir + "/build/tinympc/libtinympcShared" + os_ext)  # Load the library

1.4 与求解器代码交互

        在部署之前,我们还可以通过高级语言交互来验证程序。这自然为软件在环 (SIL) 测试提供了便利。以下是在仿真中运行 MPC 的示例,您可以使用任何仿真器。

x = [0.0] * n * N  # Initial state
u = [0.0] * m * (N - 1)  # List of control inputs in horizon
x_all = []  # List of all stored states
x_noise = x * 1
# Matrices for simulation
Anp = np.array(A).reshape((n, n)).transpose()
Bnp = np.array(B).reshape((n, m))

print("=== START INTERACTIVE MPC ===")

NSIM = 300
for i in range(NSIM):
    # 1. Set initial state from measurement    
    prob.set_x0(x_noise, 0)  # Set initial state to C code

    # 2. Set the reference state if needed    

    # 3. Solve the problem
    prob.solve(0)  # Call the solve in C code

    # 4. Get the control input
    prob.get_u(u, 0)  # Get the control input from C code

    # 5. Simulate the dynamics    
    x = Anp@np.array(x).reshape((n, 1))+ Bnp*np.array(u[0]) 

    noise = np.random.normal(0, 0.01, (n, 1))
    x_noise = x + noise
    # print(f"X = {x}")
    x = x.reshape(n).tolist() 
    x_noise = x_noise.reshape(n).tolist() 
    # print(f"X = {x}")
    x_all.append(x)

print((x_all))

二、获取模型

2.1 线性化

        TinyMPC 原型只能处理线性动力学,这意味着在求解器使用之前,系统必须围绕一个平衡点进行线性化。TinyMPC 的扩展功能允许用户通过存储多个线性化来近似系统的非线性动力学,但我们将只从一个开始。

        离散线性化系统的形式为 x_{k+1}=Ax_k+Bu_k,其中 x_ku_k 分别为当前时间步的状态和控制,A 为状态转换矩阵,B 为控制或输入矩阵,x_{k+1} 为下一时间步的状态。在上一页给出的每个示例中,状态转换矩阵 A 和输入矩阵 B 都是根据系统的连续非线性动力学计算得出的。

2.2 车杆示例

        车杆的连续时间动力学已被多次推导。在本例中,我们将使用该推导中的惯例,即杆在 \theta=0 处直立。如果我们忽略该模型中的摩擦力,那么在该推导中我们唯一关心的方程就是 (23) 和 (24)。
        让我们把它们写成一个动力学函数

mc = 0.2 # mass of the cart (kg)
mp = 0.1 # mass of the pole (kg)
ℓ = 0.5 # distance to the center of mass (meters)
g = 9.81
# 

def cartpole_dynamics(x, u):
    r       = x[0] # cart position
    theta   = x[1] # pole angle
    rd      = x[2] # change in cart position
    theta_d = x[3] # change in pole angle
    F       = u[0] # force applied to cart

    theta_dd = (g*np.sin(theta) + np.cos(theta) * ((-F - mp*l*(theta_d**2) * \
                    np.sin(theta))/(mc + mp))) / (l*(4/3 - (mp*(np.cos(theta)**2))/(mc + mp)))
    rdd = (F + mp*l*((theta_d**2)*np.sin(theta) - theta_dd*np.cos(theta))) / (mc + mp)

    return np.array([rd, theta_d, rdd, theta_dd])

        该函数描述了系统的连续(非线性)动力学,即 \dot{x}=\text{cartpole}\_\text{dynamics}(x,u)
        在线性化之前,我们先用积分器将连续动力学离散化。RK4(Runge-Kutta 四阶)是一种常见的显式积分器,但也可以随意写入。

def cartpole_rk4(x, u, dt):
    f1 = dt*cartpole_dynamics(x, u)
    f2 = dt*cartpole_dynamics(x + f1/2, u)
    f3 = dt*cartpole_dynamics(x + f2/2, u)
    f4 = dt*cartpole_dynamics(x + f3, u)
    return x + (1/6)*(f1 + 2*f2 + 2*f3 + f4)

        我们的积分器接收当前时间步的状态和控制,并将状态向前积分 \Delta t 秒(RK4 函数中的 dt 参数)。现在我们有了由 x_{k+1}=\text{cartpole\_rk}4(x_k,u_k,dt) 定义的系统离散(非线性)动力学。现在,我们围绕平衡位置进行线性化,以获得前面描述的状态转换矩阵 A 和输入矩阵 B。手工微分 \text{cartpole\_rk4} 会很麻烦,但幸运的是,我们可以使用自动微分工具来完成这项工作。

import autograd as AG

xgoal = np.array([0.0, np.pi, 0.0, 0.0])
ugoal = np.array([0.0])

dt = 0.01

A = AG.jacobian(lambda x_: cartpole_rk4(x_, ugoal))(xgoal)
B = AG.jacobian(lambda u_: cartpole_rk4(xgoal, u_))(ugoal)

        现在要做的就是保存 AB,并将它们传递给 TinyMPC,如示例页面的问题设置部分所示。

三、求解器

        TinyMPC 的核心是利用 MPC 问题的结构来加速和压缩 ADMM 算法。

3.1 问题表述

        TinyMPC 可求解形式如下的凸二次模型预测控制程序

\begin{aligned} &\text{minimize}&& \sum_{k=0}^{N-1}\frac12(x_k-\bar{x}_k)^TQ(x_k-\bar{x}_k)+\frac12(u_k-\bar{u}_k)^TR(u_k-\bar{u}_k) \\ &\text{subject to}&& x_0=x_\text{init}, \\ &&&x_{k+1}=Ax_k+Bu_k, \\ &&&u_k^l\leq u_k\leq u_k^u, \\ &&&x_k^l\leq x_k\leq x_k^u, \\ &&&u_k\in\mathcal{K}_u, \\ &&&x_k\in\mathcal{K}_x \end{aligned}

        其中,x_k\in\mathbb{R}^n,u_k\in\mathbb{R}^m 为时间步长 k 时的状态和控制输入,N 为时间步长数(也称为视平线),A\in\mathbb{R}^{n\times n}B\in\mathbb{R}^{n\times m} 定义了系统动力学,Q\succeq0,R\succ0Q_f\succeq0 为对称成本权重矩阵,\bar{x}_{k}\bar{u}_k 为状态和输入参考轨迹。约束条件包括状态和输入的下限和上限以及二阶锥 \mathcal{K}

3.2 算法

        将很快提供!同时,请查阅我们的论文或背景资料,了解更多详情。

3.3 实现

        TinyMPC 库提供了上述算法的 C++ 实现,以及与几种高级语言的接口。通过这种集成,这些语言可以使用 TinyMPC 无缝地解决最优控制问题。

        此外,还有几种社区开发的算法实现: Rust

        在该资源库中可以找到与其他微控制器求解器的数值基准比较。

        该资源库提供了使用 TinyMPC 的 Crazyflie 固件。

四、背景知识

4.1 概述

        TinyMPC 的基础算法是交替方向乘法。TinyMPC 将基元更新步骤 —— 通常耗时最长的部分- —— 重新表述为一个 LQR 问题。这些问题已经研究了几十年,我们知道如何以封闭形式写出 LQR 问题:具体来说,就是使用里卡提递归法。我们重组了部分递归函数,以提取只需计算一次的大矩阵。在原型实现中,这限制了 TinyMPC 只能求解线性轨迹跟踪问题(只要能在线快速重线性化,各种约束条件均可求解)。不过,正如我们在演示视频中看到的那样,一次线性化就能解决很多问题。

4.2 交替方向乘法(ADMM)

        交替方向乘法算法开发于 20 世纪 70 年代,2011 年被斯坦福大学的研究人员用于更好地解决分布式凸优化问题。其中一些研究人员后来帮助开发了OSQP,即运算器分裂二次规划求解器。TinyMPC 的灵感主要来自这两个方面。

        我们希望解决成本函数 \text{f} 和有效状态集 \mathcal{C} 都是凸的优化问题:

\begin{aligned}\min_x\quad&f(x)\\\text{subject to}\quad&x\in\mathcal{C}.\end{aligned}

        我们为集合 \mathcal{C} 定义一个指标函数:

I_\mathcal{C}(x)=\begin{cases}0&x\in\mathcal{C}\\\infty&\text{otherwise.}\end{cases}

        指标函数简单地说,当 x 违反约束条件时(状态 x 在有效状态集合 \mathcal{C} 之外),额外成本为无限;而当 x 遵守约束条件时(x 在有效状态集合 \mathcal{C} 之内),额外成本为零。因此,我们需要确定一个状态是否在集合 \mathcal{C} 中,才能知道问题的所有约束条件是否都得到了满足。为了提高计算速度,通常采用 Hx\geq h(或 Hx\leq h,或 Hx\geq hGx\leq g 的组合(每种组合都可以重写为等价于其他组合))的形式。这种形式可以描述 x 中的任何一种线性约束。例如,为了避开障碍物,通常会将 Hh 安排为半空间约束,在三维空间中,整个空间被一个平面分割,只有一半在 \mathcal{C} 集内。对于任意维度,我们说空间被超平面分割。

        我们修改一般优化问题,将指标函数加入成本中。我们引入一个新的状态变量 z,称为松弛变量,用来描述原始状态变量 x 的受限版本,我们现在称其为原始变量。

\begin{aligned}\min_x&\quad f(x)+I_\mathcal{C}(z)\\\mathrm{subject~to}&\quad x=z.\end{aligned}

        在最小成本时,主变量 x 必须等于松弛变量 z,但在每次求解过程中,它们不一定相等。这是因为松弛变量 z 在算法中表现为原始变量 x 被投影到可行集 \mathcal{C} 上的版本,因此每当原始变量 x 违反任何约束条件时,该迭代的松弛变量就会被投影回 \mathcal{C} 上,从而与 x 不同。为了将原始变量 x 推回可行集 \mathcal{C},我们引入了第三个变量 \lambda,称为对偶变量。这种方法被称为增强拉格朗日法(原名乘数法),在引入对偶变量 \lambda 的同时引入一个标量惩罚参数 \rho(也称为拉格朗日乘数)。惩罚参数 \rho 是对上述约束优化问题的拉格朗日的增强。xz 的差值越大,增强拉格朗日的成本就越高,从而迫使 x 更接近 z

\mathcal{L}_A(x,z,\lambda)=f(x)+I_\mathcal{C}(z)+\lambda^\intercal(x-z)+\frac\rho2\|x-z\|_2^2.

        现在,我们的优化问题被分为两个变量:原始 x 和松弛 z,我们可以在保持所有其他变量不变的情况下,对每个变量单独进行优化。要使用 ADMM 算法,我们只需交替求解 x 和使我们的增强拉格朗日最小化的 z。每次求解后,我们都会根据 xz 的差异更新我们的对偶变量 \lambda

\begin{aligned}\text{primal update: }x^+&=\underset{x}{\operatorname*{\arg\min}}\mathcal{L}_A(x,z,\lambda),\\\text{slack update: }z^+&=\underset{z}{\operatorname*{\arg\min}}\mathcal{L}_A(x^+,z,\lambda),\\\text{dual update: }\lambda^+&=\lambda+\rho(x^+-z^+),\end{aligned}

        其中 x^+,z^+,\lambda^{+} 指的是下一次迭代中要用到的原始变量、松弛变量和对偶变量。

        现在我们要做的就是解决几个无约束优化问题!

TODO: 原始和松弛更新以及离散代数里卡蒂方程

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

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

相关文章

计算机网络:数据链路层 - CSMA/CD协议

计算机网络:数据链路层 - CSMA/CD协议 媒体接入控制CSMA/CD协议截断二进制指数退避算法帧长与帧间间隔信道利用率 媒体接入控制 如图所示,这是一根同轴电缆,有多台主机连接到这根同轴电缆上,他们共享这根传输媒体,形成…

又整新活,新版 IntelliJ IDEA 2024.1 有点东西!

就在上周,Jetbrains 又迎来了一波大版本更新,这也是 JetBrains 2024首个大动作! JetBrains 为其多款 IDE 发布了 2024 年度首个大版本更新 (2024.1)。 作为旗下重要的产品之一,IntelliJ IDEA当然也不例外。这不,现如今…

使用 Meltano 将数据从 Snowflake 导入到 Elasticsearch:开发者之旅

作者:来自 Elastic Dmitrii Burlutskii 在 Elastic 的搜索团队中,我们一直在探索不同的 ETL 工具以及如何利用它们将数据传输到 Elasticsearch,并在传输的数据上实现 AI 助力搜索。今天,我想与大家分享我们与 Meltano 生态系统以及…

矩阵链乘法问题

描述 输入 输入共n1行 第一行输入矩阵的总个数n[2,1000] 后n行分别输入矩阵的维数[1,100] 输出 最后一行输出少乘法次数 输入样例 1 6 30 35 35 15 15 5 5 10 10 20 20 25 输出样例1 15125 代码实现 #include<iostream> #include<vector> #include<…

设计模式之观察者模式讲解

概念&#xff1a;定义对象间一种一对多的依赖关系&#xff0c;使得当每一个对象改变状态&#xff0c;则所有依赖于它的对象都会得到通知并被自动更新。 抽象主题&#xff1a;或者叫被观察者&#xff0c;可以持有、增加、删除观察者对象。具体主题&#xff1a;实现抽象主题定义的…

yolov5旋转目标检测遥感图像检测-无人机旋转目标检测(代码和原理)

YOLOv5&#xff08;You Only Look Once version 5&#xff09;是一个流行且高效的实时目标检测深度学习模型&#xff0c;最初设计用于处理图像中的水平矩形边界框目标。然而&#xff0c;对于旋转目标检测&#xff0c;通常需要对原始YOLOv5架构进行扩展或修改&#xff0c;以便能…

【经典算法】LCR187:破冰游戏(约瑟夫问题,Java/C/Python3/JavaScript实现含注释说明,Easy)

目录 题目思路及实现方式一&#xff1a;迭代模拟&#xff08;用链表模拟这个游戏&#xff09;思路代码实现Java版本C语言版本Python3版本 复杂度分析 方式二&#xff1a;数学迭代思路代码实现Java版本C语言版本Python3版本 复杂度分析 方式三&#xff1a;递归思路代码实现Java版…

数字化智慧养老:引领老年人融入科技时代新生活

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 人类社会已经步入了一个全新的数字时代。在这个时代&#xff0c;互联网、大数据、人工智…

学习操作系统之单道批处理系统

较之前操作的改进&#xff1a; 在原先的工作基础上&#xff0c;扩大存储&#xff0c;一次放入多个作业再进行处理。 单道&#xff1a;内存中始终只有一道作业 批处理&#xff1a;磁带上有多道作业&#xff0c;安装一次磁带&#xff0c;可以处理一批作业 1953年诞生了第一代…

【C语言】指针篇(指针数组,数组指针,函数指针,一级、二级指针)

文章目录 一、指针基础1.什么是指针2.指针的定义和初始化3.指针的解引用4.野指针和空指针5.指针的类型6.指针的大小7.指针的运算8.指针和数组9.指针和字符串10.二级指针 二、指针数组和数组指针1.指针数组2.数组指针3.练习 三、数组传参和指针传参1.一维数组传参2.二维数组传参…

开源区块链系统/技术 总结(欢迎补充,最新)

1. FISCO BCOS FISCO BCOS 2.0 技术文档 — FISCO BCOS 2.0 v2.9.0 文档https://fisco-bcos-documentation.readthedocs.io/ 2. ChainMaker&#xff08;长安链&#xff09; 文档导航 — chainmaker-docs v2.3.2 documentationhttps://docs.chainmaker.org.cn/v2.3.2/html/in…

你们是如何保证消息不丢失的?

1、什么是死信 在 RabbitMQ 中充当主角的就是消息&#xff0c;在不同场景下&#xff0c;消息会有不同地表现。 死信就是消息在特定场景下的一种表现形式&#xff0c;这些场景包括&#xff1a; 1. 消息被拒绝访问&#xff0c;即 RabbitMQ返回 basicNack 的信号时 或者拒绝basi…

CKA 基础操作教程(五)

Kubernetes Ingress 理论学习 Ingress 提供从集群外部到集群内服务的 HTTP 和 HTTPS 路由。 流量路由由 Ingress 资源所定义的规则来控制。 Ingress 资源示例&#xff1a; apiVersion: networking.k8s.io/v1 # 指定 Kubernetes 中使用的 API 版本 kind: Ingress # 指定对象…

【日常记录】【JS】填充数组的三种方案

文章目录 1、for 循环填充2、new Array、fill、map 三者配合填充3、Array.from 填充数组参考链接 一般在开发中需要生成一个数组&#xff0c;用于测试等其他情况&#xff0c;以下介绍三种常见方案 1、for 循环填充 如果需要对这个数组的内容做一些特殊处理&#xff0c;写起来就…

Mysql底层原理七:InnoDB 行记录

1.行格式 1.1 Compact行格式 1.1.1 示意图 1.1.2 准备一下 1&#xff09;建表 mysql> CREATE TABLE record_format_demo (-> c1 VARCHAR(10),-> c2 VARCHAR(10) NOT NULL,-> c3 CHAR(10),-> c4 VARCHAR(10)-> ) CHARSETascii ROW_FORMATCOM…

企业网络安全运营能力的多维度评价及优化策略

网络安全是企业面临的一个日益重要的问题&#xff0c;安全运营能力的强弱直接关系到企业的健康可持续发展和综合竞争力的提升。为推动企业网络安全工作的标准化建设&#xff0c;提升企业的网络安全运营能力&#xff0c;本文从安全建设、安全应对和安全效果三个角度出发&#xf…

【迅为iTOP-4412-linux 系统制作(4)】ADB 或者 TF 卡烧写测试

准备工作 编译生成的内核镜像uImage 和设备树 dtb 文件“exynos4412-itop-elite.dtb”已经可以使用了。 把编译生成的uimage和dtb文件。拷贝fastboot工具。官方的u-boot-iTOP-4412.bin 也拷贝到 platform-tools 文件夹目录内。system.img 也拷贝到 platform-tools 文件夹目录…

阿里通义千问开源 320 亿参数模型;文字和音频自动翻译成手语Hand Talk拉近人与人的距离

✨ 1: Qwen1.5-32B Qwen1.5-32B是Qwen1.5系列中性能与效率兼顾的最新语言模型&#xff0c;内存占用低&#xff0c;运行速度快。 Qwen1.5-32B是Qwen1.5语言模型系列的最新成员&#xff0c;这个模型是基于先进的技术研发的&#xff0c;旨在提供一种既高效又经济的AI语言理解和生…

JS--demo2录入学生信息

实现学生信息录取。 效果图: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><meta http-equiv"X-U…

景联文科技:为AI大模型提供高质海量训练数据

在全球AI浪潮的推动下&#xff0c;大量训练数据已成为AI算法模型发展和演进中的关键一环。 艾瑞咨询数据显示&#xff0c;包括数据采集、数据处理&#xff08;标注&#xff09;、数据存储、数据挖掘等模块在内的AI基础数据服务市场&#xff0c;将在未来数年内持续增长。 预计到…