ABB机器人四元素处理

在用到ABB机器人时,姿态使用的是四元素的方式,如下
在这里插入图片描述
然后,选择几个需求实现一下,这基本上就把互转实现差不多了
1.四元素转旋转矩阵
q=w+xi+yj+zk 中 w x y z 也对应有些文档里写的q0 q1 q2 q3
在这里插入图片描述
2.旋转矩阵转四元素
在这里插入图片描述
在这里插入图片描述
3.四元素转俯仰角(pitch,θ\thetaθ)、滚转角(roll,ϕ\phiϕ)、偏航角(yaw,ψ\psiψ)
计算方法如下:
在这里插入图片描述
和这个也一样,所以公式应该没啥问题,直接套就行了
在这里插入图片描述
4.欧拉角转四元素
直接套下面公式即可:
在这里插入图片描述
测试代码,欢迎取用,留下点赞+收藏

struct Quaternion {
    double w, x, y, z;
};
void matrixToQuaternion(double R[3][3]) {
    Quaternion q;
    double trace = R[0][0] + R[1][1] + R[2][2]; // 矩阵的迹

    if (trace > 0.0) {
        double s = 0.5 / sqrt(trace + 1.0);
        q.w = 0.25 / s;
        q.x = (R[2][1] - R[1][2]) * s;
        q.y = (R[0][2] - R[2][0]) * s;
        q.z = (R[1][0] - R[0][1]) * s;
    } else {
        if (R[0][0] > R[1][1] && R[0][0] > R[2][2]) {
            double s = 2.0 * sqrt(1.0 + R[0][0] - R[1][1] - R[2][2]);
            q.w = (R[2][1] - R[1][2]) / s;
            q.x = 0.25 * s;
            q.y = (R[0][1] + R[1][0]) / s;
            q.z = (R[0][2] + R[2][0]) / s;
        } else if (R[1][1] > R[2][2]) {
            double s = 2.0 * sqrt(1.0 + R[1][1] - R[0][0] - R[2][2]);
            q.w = (R[0][2] - R[2][0]) / s;
            q.x = (R[0][1] + R[1][0]) / s;
            q.y = 0.25 * s;
            q.z = (R[1][2] + R[2][1]) / s;
        } else {
            double s = 2.0 * sqrt(1.0 + R[2][2] - R[0][0] - R[1][1]);
            q.w = (R[1][0] - R[0][1]) / s;
            q.x = (R[0][2] + R[2][0]) / s;
            q.y = (R[1][2] + R[2][1]) / s;
            q.z = 0.25 * s;
        }
    }
    qDebug()<<"四元素:"<<q.w<<" "<<q.x<<" "<<q.y<<" "<<q.z;
}
//先给一个点位姿XYZUVW
st_PosAttitude p1;
p1.dX = 1311.45;
p1.dY = -50.21;
p1.dZ = 979.57;
p1.dA = 0.24258;
p1.dB = 0.04898;
p1.dC = 0.96886;
p1.dD = 0.00833;
//对应的四元素值
//q=w+xi+yj+zk
double w = p1.dA;
double x = p1.dB;
double y = p1.dC;
double z = p1.dD;
//构建旋转矩阵
double a00 = 1.0 - 2.0 * y * y - 2.0 * z * z;
double a01 = 2.0 * x * y - 2.0 * w * z;
double a02 = 2.0 * x * z + 2.0 * w * y;
double a10 = 2.0 * x * y + 2.0 * w * z;
double a11 = 1.0 - 2.0 * x * x -2.0 * z * z;
double a12 = 2.0 * y * z - 2.0 * w * x;
double a20 = 2.0 * x * z - 2.0 * w * y;
double a21 = 2.0 * y * z + 2.0 * w * x;
double a22 = 1.0 - 2.0 * x * x - 2.0 * y * y;
Eigen::Matrix4d xyzdelt;
xyzdelt<<a00,a01,a02,0,
         a10,a11,a12,0,
         a20,a21,a22,0,
         0,0,0,1;
//旋转矩阵打印出来
qDebug()<<xyzdelt(0,0)<<" "<<xyzdelt(0,1)<<" "<<xyzdelt(0,2)<<" "<<xyzdelt(0,3);
qDebug()<<xyzdelt(1,0)<<" "<<xyzdelt(1,1)<<" "<<xyzdelt(1,2)<<" "<<xyzdelt(1,3);
qDebug()<<xyzdelt(2,0)<<" "<<xyzdelt(2,1)<<" "<<xyzdelt(2,2)<<" "<<xyzdelt(2,3);
qDebug()<<xyzdelt(3,0)<<" "<<xyzdelt(3,1)<<" "<<xyzdelt(3,2)<<" "<<xyzdelt(3,3);

//直接使用Eigen库中的四元素转旋转矩阵,做对比
Eigen::Quaterniond q_odom_curr_tmp;
q_odom_curr_tmp.x() = x;
q_odom_curr_tmp.y() = y;
q_odom_curr_tmp.z() = z;
q_odom_curr_tmp.w() =w;
Eigen::Matrix3d R_odom_curr_tmp;
R_odom_curr_tmp= q_odom_curr_tmp.normalized().toRotationMatrix();
qDebug()<<R_odom_curr_tmp(0,0)<<" "<<R_odom_curr_tmp(0,1)<<" "<<R_odom_curr_tmp(0,2);
qDebug()<<R_odom_curr_tmp(1,0)<<" "<<R_odom_curr_tmp(1,1)<<" "<<R_odom_curr_tmp(1,2);
qDebug()<<R_odom_curr_tmp(2,0)<<" "<<R_odom_curr_tmp(2,1)<<" "<<R_odom_curr_tmp(2,2);

//旋转矩阵转四元素,这个可能会遇到w1为0的情况,但是大部分情况下不用管,和下面那种方法结果一致,如果遇到为0,换下面那种方法试一下
double w1 = 1.0/2.0*(sqrt(1.0  + a00 + a11 + a22));
double x1 = (a21 - a12) / (4.0 * w1);
double y1 = (a02 - a20) / (4.0 * w1);
double z1 = (a10 - a01) / (4.0 * w1);
qDebug()<<"四元素:"<<w1<<" "<<x1<<" "<<y1<<" "<<z1;

//旋转矩阵转四元素,直接用的是以下链接的函数,主要做对比使用
//https://blog.csdn.net/qq_44339029/article/details/142431407?ops_request_misc=%257B%2522request%255Fid%2522%253A%252282244049b96523ad4d78ccf477e67b26%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=82244049b96523ad4d78ccf477e67b26&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~baidu_landing_v2~default-4-142431407-null-null.nonecase&utm_term=%E6%97%8B%E8%BD%AC%E7%9F%A9%E9%98%B5%E8%BD%AC%E5%9B%9B%E5%85%83%E7%B4%A0&spm=1018.2226.3001.4450
double R[3][3];
R[0][0] = xyzdelt(0,0);R[0][1] = xyzdelt(0,1);R[0][2] = xyzdelt(0,2);
R[1][0] = xyzdelt(1,0);R[1][1] = xyzdelt(1,1);R[1][2] = xyzdelt(1,2);
R[2][0] = xyzdelt(2,0);R[2][1] = xyzdelt(2,1);R[2][2] = xyzdelt(2,2);
matrixToQuaternion(R);

//四元素转UVW 即 θ ϕ ψ
//俯仰角(pitch):θ\thetaθ   x轴
//滚转角(roll):ϕ\phiϕ   y轴
//偏航角(yaw):ψ\psiψ   z轴
double pitch = asin(2.0 * (w1 * y1 - x1 * z1));
double roll = atan2((2.0 * (w1 * x1 + y1 * z1)),(1.0 - 2.0*(x * x + y * y)));
double yaw = atan2((2.0 * (w1 * z1 + x1 * y1)),(1.0 - 2.0*(z * z + y * y)));
qDebug()<<"rxryrz:"<<pitch<<" "<<roll<<" "<<yaw;
qDebug()<<"rxryrz:"<<pitch*180.0/M_PI<<" "<<roll*180.0/M_PI<<" "<<yaw*180.0/M_PI;

//欧拉角到四元素
double w2 = cos(roll/2.0) * cos(pitch/2.0) * cos(yaw/2.0) + sin(roll/2.0) * sin(pitch/2.0) * sin(yaw/2.0);
double x2 = sin(roll/2.0) * cos(pitch/2.0) * cos(yaw/2.0) - cos(roll/2.0) * sin(pitch/2.0) * sin(yaw/2.0);
double y2 = cos(roll/2.0) * sin(pitch/2.0) * cos(yaw/2.0) + sin(roll/2.0) * cos(pitch/2.0) * sin(yaw/2.0);
double z2 = cos(roll/2.0) * cos(pitch/2.0) * sin(yaw/2.0) - sin(roll/2.0) * sin(pitch/2.0) * cos(yaw/2.0);
qDebug()<<"四元素:"<<w2<<" "<<x2<<" "<<y2<<" "<<z2;

打印出来的结果:

//自己组的旋转矩阵 xyzdelt输出
-0.877518   0.0908681   0.470868   0
0.0989509   0.995063   -0.00762193   0
-0.469236   0.0399043   -0.882177   0
0   0   0   1
//调用Eigen库的输出结果,发现结果是一致的
-0.877512   0.0908679   0.470867
0.0989506   0.995063   -0.0076219
-0.469235   0.0399042   -0.882171
//调用其他博文输出的四元素结果
四元素: 0.24258   0.04898   0.96886   0.00833
//通过公式计算的结果,基本一致
四元素: 0.242573   0.0489813   0.968886   0.00833023
//通过四元素计算的欧拉角
rxryrz: 0.488425   3.09639   3.0293
rxryrz: 27.9847   177.41   173.566
//通过欧拉角计算的四元素,和ABB机器人示教器端显示的一模一样,说明准确
四元素: 0.24258   0.0489824   0.968858   0.00832969

有些公式借鉴该博客:https://blog.csdn.net/weixin_45784125/article/details/144908718?ops_request_misc=%257B%2522request%255Fid%2522%253A%252268b949e6f6310d7a6aa2379907f888f2%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=68b949e6f6310d7a6aa2379907f888f2&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-16-144908718-null-null.142v102pc_search_result_base7&utm_term=%E6%97%8B%E8%BD%AC%E7%9F%A9%E9%98%B5&spm=1018.2226.3001.4187

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值