Ardupilot倾转分离函数thrust_heading_rotation_angles
- 什么是轴角分离
- 源码分析
- 一些细节补充
- 效果显示及进一步修改
本文主要写一下自己对于APM倾转分离(轴角分离)函数的一些学习笔记及思考。
ZING已经很好地分析了APM轴角分离函数,以下是我参考的他的一些博文。
[飞控]姿态误差(四)-APM如何计算姿态误差
[飞控]倾转分离(一)-APM的倾转分离竟然没有效果?
[飞控]倾转分离(补充)-等效旋转矢量(轴角)与旋转矩阵
后续分析过程会主要引用来自上面三篇,侵删。
什么是轴角分离
引文来源:https://zinghd.gitee.io/tilt_torsion_3/
1.起源
姿态中,roll 和 pitch 的改变来自于靠桨直接的力矩调整,调整很快,十几个毫秒就能到位。
而yaw的改变是靠桨速度差产生的旋转力矩来调整的调整比较慢,要快一百个毫秒才能到位。
2.问题
通常旋翼飞机的80%的能量用于油门控制抵抗重力,20%的能量用于控制姿态。
当 roll pitch yaw 都有较大误差时,20%的能量由三个控制器共同使用,但是由于 yaw 响应较慢,会导致 yaw 的误差一直都比较大,占用大部分姿态控制的能量,反而影响了整个姿态控制。
3.思路
因为旋翼稳定飞行的第一要素是保证桨平面( roll pitch )的精确控制,即保证桨平面没有误差 ,
yaw是不是没有误差并不重要。那么我们计算出真实姿态误差时,把误差分成两个部分tilt(pitch和roll)和 torsion(yaw),
但是呢,不直接把 torsion 给控制器
做一点限制,比如,「限幅」或者「衰减」
然后重新合成一个处理后的误差。
这样控制器就好认为,yaw 的误差并不大 ,大部分能量可以留给 tilt(pitch和roll)。
4.算法步骤
① 通过对齐 当前机体坐标系 z 轴 和 期望机体坐标系 z 轴 得到 tilt 误差
② 把 tilt 误差 转到 地理系 或者 转到 机体系
③ 总误差 - tilt 误差 = torsion 误差
④ 限制 torsion 误差 可以使用「限幅」方法 或者「衰减」方法
⑤ 把限制后的 torsion 和 tilt 组合成新的总误差
源码分析
以下内容备注来自我自己的一些考虑
void AC_AttitudeControl::thrust_heading_rotation_angles(Quaternion& att_to_quat, const Quaternion& att_from_quat, Vector3f& att_diff_angle, float& thrust_vec_dot)
{
Matrix3f att_to_rot_matrix;
att_to_quat.rotation_matrix(att_to_rot_matrix);
Vector3f att_to_thrust_vec = att_to_rot_matrix * Vector3f(0.0f, 0.0f, 1.0f);
Matrix3f att_from_rot_matrix;
att_from_quat.rotation_matrix(att_from_rot_matrix);
Vector3f att_from_thrust_vec = att_from_rot_matrix * Vector3f(0.0f, 0.0f, 1.0f);
Vector3f thrust_vec_cross = att_from_thrust_vec % att_to_thrust_vec;
thrust_vec_dot = acosf(constrain_float(att_from_thrust_vec * att_to_thrust_vec, -1.0f, 1.0f));
float thrust_vector_length = thrust_vec_cross.length();
if (is_zero(thrust_vector_length) || is_zero(thrust_vec_dot)) {
thrust_vec_cross = Vector3f(0, 0, 1);
thrust_vec_dot = 0.0f;
} else {
thrust_vec_cross /= thrust_vector_length;
}
Quaternion thrust_vec_correction_quat;
thrust_vec_correction_quat.from_axis_angle(thrust_vec_cross, thrust_vec_dot);
thrust_vec_correction_quat = att_from_quat.inverse() * thrust_vec_correction_quat * att_from_quat;
Quaternion yaw_vec_correction_quat = thrust_vec_correction_quat.inverse() * att_from_quat.inverse() * att_to_quat;
Vector3f rotation;
thrust_vec_correction_quat.to_axis_angle(rotation);
att_diff_angle.x = rotation.x;
att_diff_angle.y = rotation.y;
yaw_vec_correction_quat.to_axis_angle(rotation);
att_diff_angle.z = rotation.z;
if (!is_zero(_p_angle_yaw.kP()) && fabsf(att_diff_angle.z) > AC_ATTITUDE_ACCEL_Y_CONTROLLER_MAX_RADSS / _p_angle_yaw.kP()) {
att_diff_angle.z = constrain_float(wrap_PI(att_diff_angle.z), -AC_ATTITUDE_ACCEL_Y_CONTROLLER_MAX_RADSS / _p_angle_yaw.kP(), AC_ATTITUDE_ACCEL_Y_CONTROLLER_MAX_RADSS / _p_angle_yaw.kP());
yaw_vec_correction_quat.from_axis_angle(Vector3f(0.0f, 0.0f, att_diff_angle.z));
att_to_quat = att_from_quat * thrust_vec_correction_quat * yaw_vec_correction_quat;
}
}
一些细节补充
关于数学原理部分,我之前已经有一篇博文汇总过了:APM姿态旋转理论基础。因此其中一些数学原理的函数如轴角与四元数、四元数与旋转矩阵之间的相互转换此处不再补充。
另外关于叉乘和点乘的定义,可以参看这篇:向量内积(点乘)和外积(叉乘)概念及几何意义
Quaternion thrust_vec_correction_quat;
thrust_vec_correction_quat.from_axis_angle(thrust_vec_cross, thrust_vec_dot);
关于上面这段函数,参考的博文:姿态误差(四)-APM如何计算姿态误差,认为轴角转换到四元数后旋转方向改变,轴角旋转:当前->期望,而转换成四元数后:期望->当前。理由是轴角法描述的是向量的旋转,而四元数描述的是坐标系的旋转。
具体可以参照这篇解释博文:[飞控]倾转分离(补充)-等效旋转矢量(轴角)与旋转矩阵
然而参照轴角转换为四元数以及四元数表示旋转的公式(懒得打了),我个人依旧认为旋转方向是不变的(望打脸)。
不过此处相对来说并不那么重要,先了解姿态误差计算流程即可。
效果显示及进一步修改
MATLAB代码来自:[飞控]倾转分离(一)-APM的倾转分离竟然没有效果?
如上图所示,期望姿态欧拉角表示为(60, 60, 25),att_diff_angle误差为(0.8194, 1.0325, -0.2072)
绿色表示当前姿态,与黑色NED坐标系重合,红色表示期望姿态,蓝色表示APM中轴角分离之后得到的att_diff_angle误差,然而可以看到其与期望姿态的Z轴并没有对齐,但是APM程序中明明是按照对齐Z轴进行姿态误差计算的,这是为什么呢?
因为APM程序中并没有对倾转分离后的z轴误差做处理,忽略处理了倾斜时产生的z轴误差,抑制效果不好。
正确做法是对torsion误差(YAW)按一定的比例进行缩小,限制旋转,然后用四元数乘法,重新叠加两个旋转,得到新的总旋转。
在att_diff_angle.z = rotation.z;
这段代码后面,可添加如下更新
att_diff_angle.z = 0.5 * att_diff_angle.z;
yaw_vec_correction_quat.from_axis_angle(att_diff_angle.z);
Quaternion att_diff_angle_quat = thrust_vec_correction_quat * yaw_vec_correction_quat;
att_diff_angle_quat.to_axis_angle(rotation);
att_diff_angle.x = rotation.x;
att_diff_angle.y = rotation.y;
att_diff_angle.z = rotation.z;
MATLAB实现效果如下,黑色部分为经过torsion误差衰减之后的att_diff_angle。误差表示为(0.7651, 1.0740, -0.0881)
结果对比可发现经调整之后的黑色坐标系相对于蓝色坐标系,Z轴已经完成对准。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)