机器人学之刚体运动
机器人学之刚体运动1. 刚体运动1.1 刚体变换三维空间中可以用坐标$(x,y,z)\in\mathcal{R}^3$来描述质点的位置,而质点的运动轨迹可以使用参数形式来进行表示:$p(t)=(x(t),y(t),z(t))\in\mathcal{R}^3$。在机器人学中,我们通常关心的问题通常不是一个质点的运动,而是一组质点共同的运动。如果一条杆上的质点保持相对距离不变,我们认为其是一个不变的形体,可以严格定义刚体如下:
刚体刚体(rigid body)是任意两质点之间距离保持不变的质点的集合,并与物体的任意运动和作用在物体上的任意力无关。用数学的表示即是:
$$||p(t) - q(t)|| = ||p(0) - q(0)||$$
刚体变换刚体变换(rigid body transformation),满足以下条件的变换$g:\mathcal{R}^3 \to \mathcal{R}^3$,被称为刚体变换:
长度不变,对于任意的点$p,q\in\mathcal{R}^3$,均有$||g(p)-g(q)|| = ||p-q||$;
叉积不变,对于任意的 ...
C++ STL简明教程
C++ STL简明教程C++ STL(standard template library)标准模板库,是一套强大的C++模板类,提供了通用了模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量vector,队列deque,和映射map等。
组件
描述
容器(Containers)
容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。
算法(Algorithms)
算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。
迭代器(Iterators)
迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。
1.1 std::vectorstd::vector(向量),是一种变长数组,类似于python中的list,是一种可以“自动改变数组长度的数组”。在要使用std::vector的时候,我们需要添加头文件
12#inlcude <vector>using namespace std; //如 ...
模型预测控制MPC详解(附带案例实现)
模型预测控制MPC详解(附带案例实现)写在前面本文是记录学习B站博主Dr.can的学习笔记,如有侵权请联系笔者删除此文。
1. 最优控制问题最优控制问题就是研究在约束条件下达到最优的系统表现,通常系统的表现是综合分析的结果。比如考虑一个单输入单输出的系统(SISO),状态变量$x$,输出为$y$,要求其输出能跟踪预设的参考值$r$,误差可以表示为$e=y-r$,那么最优控制的目标是
$$\min \int_0^t e^2 dt$$
如果同时希望输入量$u$也能越小越好(一般的目的是减少能耗),那最优控制的目标可以是
$$\min \int_0^t q\times e^2 dt + r\times u^2 dt$$
其中$q,r$分别是权重参数,用于调节两个目标的重要性。
考虑一个多输入多输出的系统(MIMO),系统的模型为:
$$\begin{align*}\frac{dX}{dt} & = AX + BU \Y & = CX\end{align*}$$
那么可以将上述的最优化目标改写为:
$$J = \int^t_0 E^T Q ...
控制障碍函数CBF详解(附带案例实现)
控制障碍函数CBF详解(附带案例实现)1. Control Affine System一个控制仿射系统的典型形式是
$$\dot{x} = F(x,u)$$
其中,$x\in \mathbb{R}^n$是系统的状态,$u\in\mathbb{R}^m$是系统的控制输入,$F$是Lipschitz连续的,这样就能保证给定一个初始状态$x(t_0)=x_0$的时候,动态系统的轨迹$x(t)$存在且唯一。
我们通常处理的是非线性系统,那么我们可以将非线性的仿射系统写成如下的形式
$$\dot{x} = f(x) + g(x) u$$
其中$f:\mathbb{R}^n \to \mathbb{R}^n$是系统的漂移向量场,它描述了系统在没有控制输入时的动态行为,$g:\mathbb{R}^n\to\mathbb{R}^{n\times m}$,是系统的控制向量场,它描述了系统的控制输入$u$是如何影响系统的。
2. Lyapunov Theory, Nagumo’s Theory, Invariance PrincipleLyapunov Theory
对于系统 ...
Cpp复习 Chapter 5 类的继承、虚函数、抽象基类
Cpp复习 Chapter 5 类的继承、虚函数、抽象基类
Cpp系列笔记目录
【Cpp筑基】一、内联函数、引用变量、函数重载、函数模板【Cpp筑基】二、声明 vs 定义、头文件、存储持续性作用域和链接性、名称空间【Cpp筑基】三、对象和类【Cpp筑基】四、重载运算符、友元、类的转换函数【Cpp筑基】五、类的继承、虚函数、抽象基类
1. 类的继承在C++中,类的继承(inheritance)是一种创建新类(派生类)的方式,该新类可以从现有的类(基类)中继承属性和方法。继承是面向对象编程的一个核心特性,允许代码复用并提供了实现多态性的基础。从一个类派生出另一个类时,原始类被称为基类,继承类被称为派生类。
1.1 基本语法C++中,继承使用的是冒号:来指明基类。派生类从基类继承成员(成员变量和成员函数)。语法如下:
1234567class BaseClass { // 基类成员};class DerivedClass : access-specifier BaseClass { // 派生类成员};
其中access-specifi ...
Cpp复习 Chapter 4 重载运算符、友元、类的转换函数
Cpp复习 Chapter 4 重载运算符、友元、类的转换函数
Cpp系列笔记目录
【Cpp筑基】一、内联函数、引用变量、函数重载、函数模板【Cpp筑基】二、声明 vs 定义、头文件、存储持续性作用域和链接性、名称空间【Cpp筑基】三、对象和类【Cpp筑基】四、重载运算符、友元、类的转换函数【Cpp筑基】五、类的继承、虚函数、抽象基类
1. 重载运算符在C++中,运算符重载(operator overloading)允许开发者定义或重新定义标准运算符的行为,使其可以用于自定义类型(例如类)。通过运算符重载,可以让用户定义的类型与内置类型一样自然地进行运算操作,提高代码的可读性和易用性。
运算符重载是在C++中提供的一种特性,允许为用户定义的类型(例如类或结构体)定义新的运算符行为。几乎所有的运算符都可以被重载,但是有一些例外,如::域解析运算符), .(成员访问运算符)和*(成员指针访问运算符)不能被重载。
运算符重载通过在类中定义特定的成员函数或友元函数来实现。重载的函数名是operator后跟要重载的运算符,例如要重载+(加号运算符),我们就写成operator+。举个例子:
...
Cpp复习 Chapter 3 对象和类
Cpp复习 Chapter 3 对象和类
Cpp系列笔记目录
【Cpp筑基】一、内联函数、引用变量、函数重载、函数模板【Cpp筑基】二、声明 vs 定义、头文件、存储持续性作用域和链接性、名称空间【Cpp筑基】三、对象和类【Cpp筑基】四、重载运算符、友元、类的转换函数【Cpp筑基】五、类的继承、虚函数、抽象基类
1. 类Cpp相比于C语言新增了类的概念,因此Cpp是一种面向对象的编程语言而C语言只是一种面向过程的编程语言。类是一种将抽象转换为用于自定义的Cpp工具,它将数据表示和操纵数据的方法组合成一个整洁的包。
一般来说,类规范由两部分组成:
类声明:以数据成员的方式描述数据部分,以成员函数(被称为方法)的方式描述公有接口。
类的方法定义:描述如何实现类成员函数。
1.1 类的一个简单示例简单来说,类声明提供了类的蓝图,而方法定义则提供了类实现的细节。举一个例子:
my_class.h文件中存放了类的声明
1234567891011121314151617181920212223// my_class.h#ifndef MY_CLASS_H#define MY_CLASS_ ...
Cpp复习 Chapter 2 声明vs定义、头文件、存储持续性作用域和链接性、名称空间
Cpp复习 Chapter 2 声明vs定义、头文件、存储持续性作用域和链接性、名称空间
Cpp系列笔记目录
【Cpp筑基】一、内联函数、引用变量、函数重载、函数模板【Cpp筑基】二、声明 vs 定义、头文件、存储持续性作用域和链接性、名称空间【Cpp筑基】三、对象和类【Cpp筑基】四、重载运算符、友元、类的转换函数【Cpp筑基】五、类的继承、虚函数、抽象基类
1. 声明vs定义什么是声明?什么是定义?
在C++中,声明(Declaration)和定义(Definition)是两个重要的概念,它们在程序的组织和编译过程中起着不同的作用。声明是告诉编译器某个变量、函数、类或者其他标识符的名称及其类型,但不包含具体的实现或者初始化,声明的主要目的是让编译器知道这些标识符的存在及类型。
声明(Declaration):告诉编译器某个变量的名字和类型,但不分配存储空间(除非它也是一个定义)。
定义(Definition):不仅告诉编译器变量的名字和类型,还分配存储空间。
声明我们只需要告诉编译器变量的名字和类型即可,不需要为其分配存储空间,例如:
变量声明
1extern int ...
Cpp复习 Chapter 1 内联函数、引用变量、函数重载、函数模板
Cpp复习 Chapter 1 内联函数、引用变量、函数重载、函数模板
Cpp系列笔记目录
【Cpp筑基】一、内联函数、引用变量、函数重载、函数模板【Cpp筑基】二、声明 vs 定义、头文件、存储持续性作用域和链接性、名称空间【Cpp筑基】三、对象和类【Cpp筑基】四、重载运算符、友元、类的转换函数【Cpp筑基】五、类的继承、虚函数、抽象基类
【Cpp筑基】一、内联函数、引用变量、函数重载、函数模板1. 内联函数C++提供了一种内联函数,在 C++ 中,内联函数(inline function)是一种特殊的函数,其定义使用 inline 关键字来提示编译器将函数调用直接替换为函数体,以减少函数调用的开销。内联函数通常用于简短、频繁调用的函数。
要使用内联函数,必须:
在函数声明前加上关键字inline
在函数定义前加上关键字inline
注意内联函数不能递归。内联函数的基本语法:123inline return_type function_name(parameters){ // 函数体}举个例子:12345678910111213#include < ...
Hello Algo学习笔记 1. 复杂度分析 + 栈
Hello Algo学习笔记 1. 复杂度分析 + 栈递归 递归 recursion 和常用的循环迭代不一样,这种策略算法通过调用自身来解决问题,它主要包含两个方面:
递:程序不断深入调用自身,通常传入更下或更简化的参数,直到达到“终止条件”
归:出发“终止条件”之后,程序从最深处开始逐层返回,并且汇聚每一层的结果。
从实现的角度来说,设计递归算法主要需要三个主要的条件
终止条件:什么条件下终止“递”,从而开始“归”
递归调用:对应“递”,函数里应该不断调用自身,通常传入更小的参数
返回递归的结果:对应“归”,将当前递归层级的结果返回到上一级中。
虽然从计算的角度来看,迭代与递归可以获得相类似的结果,但是它们是两种完全不同的思考和解决问题的范式。
迭代:“自下而上”地解决问题,从基础的步骤开始,然后不断重复或者累加这些步骤,直到完成任务。
递归:”自上而下“地解决问题,如果问题和其子问题具有相同的形式,将原问题拆分为更小的部分,通过确定终止条件和返回结果来完成递归的调用。
调用栈 递归函数每次调用自身的时候,系统都会为其开启新的函数分配内存,来存储局部变量、调用地址和其 ...