先修:矩阵与秩 、状态空间 、Taylor 线性化 。
零基础桥梁:模型、状态、测量分别回答什么问题
模型 是对现实保留哪些规律的明确选择,不是逼真的三维外观。SDF 是描述仿真世界、刚体连接、参数和插件的文件格式;link 是刚体部件,joint 是连接,plugin 是向仿真添加力或传感器等行为的程序。看见八个桨叶网格,只证明画面里有八个形状;本章还要检查八条施力路径,才知道它们真能推动模型。
状态 保存预测未来所需的记忆;输入 是能够施加的控制;输出/测量 是实际能读到的量。两艘艇当前都在原点,一艘静止、一艘正以 1 1 1 m/s 向前:即使未来都不施力,下一秒位置也不同,所以只用位置当状态不够。对于简化单轴模型,状态可选 x = [ p , v ] T x=[p,v]^T x = [ p , v ] T ,位置 p p p 用 m、速度 v v v 用 m/s;并不要求两个分量单位相同。测量可能只有 y = p y=p y = p ,它不是完整状态,速度要借助一段位置历史与模型估计。
状态空间的目的是把“记忆怎样更新”和“传感器看见什么”分开写:x ˙ = A x + B u \dot x=Ax+Bu x ˙ = A x + B u 描述变化率,y = C x y=Cx y = C x 描述理想测量。A A A 表示状态之间的影响,B B B 表示输入影响哪些变化率,C C C 表示测到哪些状态组合。最简单的无阻力轴,输入 u u u 取加速度时,p ˙ = v \dot p=v p ˙ = v 、v ˙ = u \dot v=u v ˙ = u ;若 p = 2 p=2 p = 2 m、v = 0.3 v=0.3 v = 0.3 m/s、u = 0 u=0 u = 0 ,经过 0.1 0.1 0.1 s 位置变为 2.03 2.03 2.03 m,速度不变。若输入改用牛顿,必须通过质量换成加速度,不能继续沿用同一个 B B B 。
可控制 问输入能改变哪些运动,可观测 问测量历史能区分哪些状态。八推冗余并不能让未知位置自动可观测;增加传感器也不能让坏掉的推进器恢复施力。模型课先确定状态和输入,下一课再用测量矩阵检查可观测性。
为什么先悬停,再线性化
工作点 是要在其附近研究的状态和输入;平衡点 要求各变化率为零;线性化 是在该点用局部斜率近似非线性关系。悬停不是“把推进器设零”,而是合力和力矩先平衡。若净向上浮力为 2 2 2 N,就需先用合计向下 2 2 2 N 抵消;线性控制输入表示在这个基准上的增减,不能漏掉基准推力。
斜率为何只局部有效?设一个教学阻力大小关系为 F D = 10 ∣ v ∣ v F_D=10|v|v F D = 10∣ v ∣ v ,v v v 单位 m/s,系数单位为 N·s²/m²。在 v 0 = 0.2 v_0=0.2 v 0 = 0.2 m/s 附近,阻力为 0.4 0.4 0.4 N、斜率为 4 4 4 N·s/m;速度增加 0.01 0.01 0.01 m/s 时,线性预测阻力增加 0.04 0.04 0.04 N,精确增加为 0.041 0.041 0.041 N,差异很小。在零速点斜率却是零,不能因为非零速度有阻力,就在零速线性模型中凭空写入常数阻尼。后文会区分 SDF 的严格线性化与教学设计假设。
基础在线练习: 二维分配 先练矩阵把输入映成合力及限幅;它不替代本章六维八推秩检验。坐标变换 先练同一物理向量如何换分量。
本章要交付什么
学习路径是一条可检验的链:模型文件 → 力学方程 → 工作点 → 状态空间 → 可观测性 → 观测器 → 状态反馈 → 稳定性证明 → C++ 数值实验 → Gazebo/SITL 接口实验 。先回答每一层为什么存在,再写下一层代码。
本章选 BlueROV2 Heavy 的八推进器模型 作几何与软件接线基线,不把原有实艇的 ArduSub 4.1.1 升级当作前提。新建学习工作区,仿真固件、参数、端口与实艇完全分开。第一轮只做悬停附近低速实验,不同时解决视觉、航迹规划、强流、推进器故障与非线性全局稳定性。
1. 先验证“八推六自由度”,不要从项目标题猜
选用 clydemcqueen/bluerov2_gz ,锁定源码提交 4451a5d1b15d204581d43ef7d93df4a0508eddbb。检查的核心不是截图,而是:
这个模型的 base_link 质量为 13 k g 13\,\mathrm{kg} 13 kg ;另有八个各 0.002 k g 0.002\,\mathrm{kg} 0.002 kg 的推进器 link,组装质量为 13.016 k g 13.016\,\mathrm{kg} 13.016 kg 。教学刚体近似忽略这些小 link 的质量与惯量;质心处惯量对角项为 ( 0.26 , 0.23 , 0.37 ) k g m 2 (0.26,0.23,0.37)\,\mathrm{kg\,m^2} ( 0.26 , 0.23 , 0.37 ) kg m 2 。几何原点下质心为 ( 0 , 0 , 0.011 ) m (0,0,0.011)\,\mathrm m ( 0 , 0 , 0.011 ) m ,浮心为 ( 0 , 0 , 0.06 ) m (0,0,0.06)\,\mathrm m ( 0 , 0 , 0.06 ) m 。这些是该仿真模型的参数 ,不是所有 Heavy 实艇的辨识结果。模型的附加质量项和线性阻力项设为零;二次平动阻力系数绝对值为 ( 58.42 , 55.137 , 124.818 ) (58.42,55.137,124.818) ( 58.42 , 55.137 , 124.818 ) ,转动项为 ( 4 , 4 , 4 ) (4,4,4) ( 4 , 4 , 4 ) 。SDF 采用负的稳定导数;写成阻力放在方程左边时采用正的耗散系数。注意不能把符号直接抄反。
坐标是模型的一部分
本课推导先使用 Gazebo 机体 FLU :前、左、上;世界使用 ENU :东、北、上。这样几何直接来自 SDF。需要送入 ArduPilot 时才转换到 FRD/NED,不能只改字段名。
p N = T N E p E , T N E = [ 0 1 0 1 0 0 0 0 − 1 ] , v F R D = T B F v F L U , T B F = diag ( 1 , − 1 , − 1 ) . p_N=T_{NE}p_E,\qquad T_{NE}=\begin{bmatrix}0&1&0\\1&0&0\\0&0&-1\end{bmatrix},\qquad
v_{FRD}=T_{BF}v_{FLU},\qquad T_{BF}=\operatorname{diag}(1,-1,-1). p N = T N E p E , T N E = 0 1 0 1 0 0 0 0 − 1 , v F R D = T B F v F LU , T B F = diag ( 1 , − 1 , − 1 ) .
p E , p N p_E,p_N p E , p N 是同一个位置向量的 ENU、NED 分量;v v v 是同一个机体速度的两套分量。两个 T T T 都是旋转矩阵。力、力矩、角速度也须做相同的相应旋转;姿态矩阵则必须同时转换世界端和机体端。上游 SDF 已为 ArduPilot 插件指定这些转换;外部 ROS 节点不要再重复一次。
2. 从八股力推导六维输入矩阵
令第 i i i 个推进器相对机体原点的位置为 r i ∈ R 3 r_i\in\mathbb R^3 r i ∈ R 3 ,其正推力单位方向为 q i ∈ R 3 q_i\in\mathbb R^3 q i ∈ R 3 ,有符号推力为 f i f_i f i ,单位 N。它产生的力是 q i f i q_i f_i q i f i ,力矩是杠杆与力的叉积。
τ = B f f , B f = [ q 1 ⋯ q 8 r 1 × q 1 ⋯ r 8 × q 8 ] ∈ R 6 × 8 , f = [ f 1 , … , f 8 ] T . \tau= B_f f,\qquad
B_f=\begin{bmatrix}q_1&\cdots&q_8\\r_1\times q_1&\cdots&r_8\times q_8\end{bmatrix}\in\mathbb R^{6\times8},\qquad
f=[f_1,\ldots,f_8]^T. τ = B f f , B f = [ q 1 r 1 × q 1 ⋯ ⋯ q 8 r 8 × q 8 ] ∈ R 6 × 8 , f = [ f 1 , … , f 8 ] T .
τ = [ F x , F y , F z , M x , M y , M z ] T \tau=[F_x,F_y,F_z,M_x,M_y,M_z]^T τ = [ F x , F y , F z , M x , M y , M z ] T 的前三项单位 N,后三项 N·m。矩阵上半部分无量纲,下半部分单位 m。八个输入不是八个自由度:艇的刚体运动只有六维,多出的输入使分配有冗余。
方向来自 joint axis 与 link pose,不来自桨叶外观。 此模型每个 joint 的轴为局部 ( 0 , 0 , − 1 ) (0,0,-1) ( 0 , 0 , − 1 ) 。令 R i R_i R i 是由该 link 的 roll、pitch、yaw 得到的旋转,先计算 q i = R i ( 0 , 0 , − 1 ) T q_i=R_i(0,0,-1)^T q i = R i ( 0 , 0 , − 1 ) T 。把源码中三位小数角度理想化为精确的 π / 2 \pi/2 π /2 、π / 4 \pi/4 π /4 ,得到下表。c = 1 / 2 c=1/\sqrt2 c = 1/ 2 。
编号 r i r_i r i ,mq i q_i q i ,FLU1 ( 0.14 , − 0.092 , 0 ) (0.14,-0.092,0) ( 0.14 , − 0.092 , 0 ) ( − c , − c , 0 ) (-c,-c,0) ( − c , − c , 0 ) 2 ( 0.14 , 0.092 , 0 ) (0.14,0.092,0) ( 0.14 , 0.092 , 0 ) ( − c , c , 0 ) (-c,c,0) ( − c , c , 0 ) 3 ( − 0.14 , − 0.092 , 0 ) (-0.14,-0.092,0) ( − 0.14 , − 0.092 , 0 ) ( c , − c , 0 ) (c,-c,0) ( c , − c , 0 ) 4 ( − 0.14 , 0.092 , 0 ) (-0.14,0.092,0) ( − 0.14 , 0.092 , 0 ) ( c , c , 0 ) (c,c,0) ( c , c , 0 ) 5 ( 0.118 , − 0.215 , 0.064 ) (0.118,-0.215,0.064) ( 0.118 , − 0.215 , 0.064 ) ( 0 , 0 , − 1 ) (0,0,-1) ( 0 , 0 , − 1 ) 6 ( 0.118 , 0.215 , 0.064 ) (0.118,0.215,0.064) ( 0.118 , 0.215 , 0.064 ) ( 0 , 0 , − 1 ) (0,0,-1) ( 0 , 0 , − 1 ) 7 ( − 0.118 , − 0.215 , 0.064 ) (-0.118,-0.215,0.064) ( − 0.118 , − 0.215 , 0.064 ) ( 0 , 0 , − 1 ) (0,0,-1) ( 0 , 0 , − 1 ) 8 ( − 0.118 , 0.215 , 0.064 ) (-0.118,0.215,0.064) ( − 0.118 , 0.215 , 0.064 ) ( 0 , 0 , − 1 ) (0,0,-1) ( 0 , 0 , − 1 )
例如第 5 列力矩为 ( 0.215 , 0.118 , 0 ) T f 5 (0.215,0.118,0)^T f_5 ( 0.215 , 0.118 , 0 ) T f 5 。一个向下推的右前推进器同时产生 roll 与 pitch 力矩,这正是“四个竖推”可以独立组合升沉、横滚、俯仰的原因。水平四推则组合纵荡、横荡、偏航。
f ⋆ = B f T ( B f B f T ) − 1 τ d . f^\star=B_f^T(B_fB_f^T)^{-1}\tau_d. f ⋆ = B f T ( B f B f T ) − 1 τ d .
这里 τ d \tau_d τ d 是期望六维力/力矩,f ⋆ f^\star f ⋆ 是无约束最小二范数解;成立条件是 rank B f = 6 \operatorname{rank} B_f=6 rank B f = 6 。本章 C++ 程序对理想几何实际算出秩 6,并检验 B f B f + = I 6 B_f B_f^+=I_6 B f B f + = I 6 ,最大误差约 2.22 × 10 − 16 2.22\times10^{-16} 2.22 × 1 0 − 16 。直接裁剪 f ⋆ f^\star f ⋆ 会破坏力矩平衡;下一步应解带推进器上下限的最小二乘,并记录残差 B f f − τ d B_f f-\tau_d B f f − τ d 。这不是“秩满所以任何力都能实现”:有限推力仍限定了可行力集合。
3. 为什么状态选位姿和速度,而不是把所有量塞进向量
状态是“给定现在与未来输入,就足够预测未来”的最小记忆。刚体受到力以后先改变速度,速度再改变位置,因此只保存位置不足以预测。选择 η = [ p T , Θ T ] T ∈ R 6 \eta=[p^T,\Theta^T]^T\in\mathbb R^6 η = [ p T , Θ T ] T ∈ R 6 和 ν = [ v T , ω T ] T ∈ R 6 \nu=[v^T,\omega^T]^T\in\mathbb R^6 ν = [ v T , ω T ] T ∈ R 6 ;Θ \Theta Θ 是局部欧拉角,ω \omega ω 是机体角速度,两者一般不相等。
η ˙ = J ( η ) ν , M ν ˙ + C ( ν ) ν + D ( ν r ) ν r + g ( η ) = B f f + τ e x t . \dot\eta=J(\eta)\nu,\qquad
M\dot\nu+C(\nu)\nu+D(\nu_r)\nu_r+g(\eta)=B_f f+\tau_{ext}. η ˙ = J ( η ) ν , M ν ˙ + C ( ν ) ν + D ( ν r ) ν r + g ( η ) = B f f + τ e x t .
这是海洋刚体的常用结构:Fossen 的原始模型说明 。M M M 是刚体与附加质量组成的 6 × 6 6\times6 6 × 6 惯性矩阵;C C C 描述旋转坐标与耦合惯性;D D D 是相对水体运动的阻力;g g g 是重力浮力恢复项;ν r \nu_r ν r 是相对水速度;τ e x t \tau_{ext} τ e x t 是未显式建模的外力/力矩。上述紧凑写法在静水下使用;本章所选 SDF 的附加质量为零时也可按相对流速计算阻力。若一般模型含附加质量且有海流,应区分 M R B ν ˙ + C R B ( ν ) ν M_{RB}\dot\nu+C_{RB}(\nu)\nu M R B ν ˙ + C R B ( ν ) ν 与 M A ν ˙ r + C A ( ν r ) ν r M_A\dot\nu_r+C_A(\nu_r)\nu_r M A ν ˙ r + C A ( ν r ) ν r ,不能把两种速度混写成同一个项。若已用相对流速算了海流阻力,就不要把同一海流效果再重复加入 τ e x t \tau_{ext} τ e x t 。
原点不在质心时,刚体惯性不能只写成对角块:
M R B = [ m I 3 − m S ( r g ) m S ( r g ) I G − m S ( r g ) 2 ] , S ( r ) a = r × a . M_{RB}=\begin{bmatrix}mI_3&-mS(r_g)\\mS(r_g)&I_G-mS(r_g)^2\end{bmatrix},\qquad S(r)a=r\times a. M R B = [ m I 3 m S ( r g ) − m S ( r g ) I G − m S ( r g ) 2 ] , S ( r ) a = r × a .
r g r_g r g 是原点到质心的向量,I G I_G I G 是质心惯量;S ( r ) S(r) S ( r ) 是叉积的反对称矩阵。下右块是平行轴定理,上下非对角块是平移与转动的耦合。也可把所有推进器位置、浮心位置都平移到质心重新建模,这时 r g = 0 r_g=0 r g = 0 ,但不能只移动惯性、不移动力臂。
4. 在悬停点把非线性模型拆成可设计的线性模型
先求平衡:ν 0 = 0 \nu_0=0 ν 0 = 0 ,并选 f 0 f_0 f 0 满足 B f f 0 = g ( η 0 ) − τ e x t , 0 B_f f_0=g(\eta_0)-\tau_{ext,0} B f f 0 = g ( η 0 ) − τ e x t , 0 。正浮力艇悬停时通常并非零推力。定义偏差 δ η = η − η 0 \delta\eta=\eta-\eta_0 δ η = η − η 0 、δ ν = ν − ν 0 \delta\nu=\nu-\nu_0 δ ν = ν − ν 0 、δ f = f − f 0 \delta f=f-f_0 δ f = f − f 0 ,才谈“小信号”。
x = [ δ η δ ν ] , x ˙ = A x + B δ f + E δ τ e x t , x=\begin{bmatrix}\delta\eta\\\delta\nu\end{bmatrix},\qquad
\dot x=Ax+B\delta f+E\delta\tau_{ext}, x = [ δ η δ ν ] , x ˙ = A x + B δ f + E δ τ e x t ,
A = [ 0 J 0 − M − 1 G 0 − M − 1 D 0 ] , B = [ 0 M − 1 B f ] , E = [ 0 M − 1 ] . A=\begin{bmatrix}0&J_0\\-M^{-1}G_0&-M^{-1}D_0\end{bmatrix},\quad
B=\begin{bmatrix}0\\M^{-1}B_f\end{bmatrix},\quad
E=\begin{bmatrix}0\\M^{-1}\end{bmatrix}. A = [ 0 − M − 1 G 0 J 0 − M − 1 D 0 ] , B = [ 0 M − 1 B f ] , E = [ 0 M − 1 ] .
x x x 有 12 个分量;J 0 = J ( η 0 ) J_0=J(\eta_0) J 0 = J ( η 0 ) 是运动学变换;G 0 G_0 G 0 是恢复力对位姿的雅可比;D 0 D_0 D 0 是速度阻力的局部雅可比。这里只写静水静止平衡的形式;非零航速、旋转或海流下还应保留相应雅可比项。在水平零航向且一致坐标下 J 0 = I 6 J_0=I_6 J 0 = I 6 。不要因为角度小就把有明显浮心偏置的 roll、pitch 恢复项全部删除。
特别重要:F D = c D ∣ v ∣ v F_D=c_D|v|v F D = c D ∣ v ∣ v 在 v = 0 v=0 v = 0 的导数是零。因此这个上游纯二次阻力模型的严格零速线性化没有线性阻尼 。为控制器设置 a = 0.4 s − 1 a=0.4\,\mathrm{s^{-1}} a = 0.4 s − 1 是下一课的教学假设,不是从该 SDF 推出来的数字。实际设计可在指定非零相对流速线性化,或通过受控小幅试验辨识等效阻尼,并标明工作范围。
参数辨识的第一轮实验
先单轴施加小推力,记录加速度、速度与稳态速度;重复正负方向,逐步拟合 F = m e f f v ˙ + d 1 v + d 2 ∣ v ∣ v F=m_{eff}\dot v+d_1v+d_2|v|v F = m e f f v ˙ + d 1 v + d 2 ∣ v ∣ v 。m e f f m_{eff} m e f f 是有效质量,d 1 , d 2 d_1,d_2 d 1 , d 2 是阻力系数。若只有速度测量,不应直接用噪声差分计算 v ˙ \dot v v ˙ ;使用滤波回归或积分形式。训练区间和验证区间分开,报告未用于拟合的轨迹误差。否则“在仿真里拟合很好”只说明重现了同一组数据。
小结与练习
把原点从模型原点移到质心后,重算第 5 推进器力臂。为什么 F x , F y , F z F_x,F_y,F_z F x , F y , F z 不变而力矩表示会变?
只保留两个竖推时,重新计算输入矩阵秩;说明不能独立控制哪些轴。
设置 d 1 = 0 d_1=0 d 1 = 0 后,再使用“模型里有 0.4 v 0.4v 0.4 v 阻尼”的控制器,会产生什么未建模项?下一课会把它与外扰一起看作总扰动 ,而不是宣称观测器能识别每种物理原因。
下一课:从测量选择到可证明的抗扰反馈 。