涉及机器人调度工作的一些基本概念整理理解
目录
- 什么是欧拉角和四元数 ?
- 相关工具网站
- 相关工具代码
什么是欧拉角和四元数 ?
这里画了一张图,简明方便理解:
欧拉角 (Euler Angles) 是一种描述物体在三维空间旋转姿态的方法,涉及3个旋转角度:偏航(Yaw)、俯仰(Pitch)和滚转(Roll)。
欧拉角和四元数可以相互转换,
四元数 (Quaternion) 是用于描述三维旋转的一种数学工具,具有避免万向节锁(Gimbal Lock)的问题。
四元数由一个标量部分和一个矢量部分组成,通常表示为q=w+xi+yj+zk ,其中x,y,z ,w 是实数
再次大白话理解:假设空间上的一个点 A点(X1,Y1,Z1) 现在开始要求 它先绕着X轴旋转90度,然后再绕着Y轴旋转30度,最后绕着Z轴旋转80度
那么此时用一组向量来表示A点当前的空间位置(X2,Y2,Z2),这组向量为: (滚转角Roll=90度,俯仰角Pitch=30度,偏航角Yaw=80度)
也就是说:
Roll=90 表示A点已经围绕X轴翻转了四分之一圈
Pitch=30 表示A点已经相对于水平面抬起30度
Yaw=80 表示A点从北向顺时针转至80度处
再来看下正负角度数值表示的含义,在右手坐标系中(如上图所示):
- 当Pitch 正值时
绕水平轴(通常为Y轴)
顺时针旋转,例如飞机起飞上升;负值则逆时针旋转,例如飞机俯冲下降 - 当Roll 正值时
绕前进方向轴(通常为X轴)
顺时针旋转,例如飞机右侧机翼下降,左侧机翼上升;负值则逆时针旋转,例如飞机左侧机翼下降,右侧机翼上升 - 当Yaw 正值时
绕垂直轴(通常为Z轴)
顺时针旋转,例如飞机右转向;负值则逆时针旋转,例如飞机左转向
相关工具网站
四元数和欧拉角之间转换
相关工具代码
这里记录一下,方便后面参考:
import cn.hutool.core.util.NumberUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
/**
* <p>
* 四元数与欧拉角转换工具类
* </p>
*
* @author admin
*/
@Slf4j
public class EulerAngleQuaternionConverterUtil {
/**
* <p>
* 四元数转为欧拉角
* </p>
*
* @param q 四元数
* @return {@link double[]} 欧拉角
*/
public static double[] quaternionToEulerAngles(Quaternion q) {
// 规范化四元数,即使它已经是一个单位四元数,也确保绝对安全
double qw = q.w, qx = q.x, qy = q.y, qz = q.z;
double norm = Math.sqrt(qw * qw + qx * qx + qy * qy + qz * qz);
// 防止除以零
if (norm > 1e-6) {
qw /= norm;
qx /= norm;
qy /= norm;
qz /= norm;
}
// 计算欧拉角
double roll = Math.atan2(2.0 * (qw * qx + qy * qz), 1.0 - 2.0 * (qx * qx + qy * qy));
double pitch = Math.asin(2.0 * (qw * qy - qz * qx));
double yaw = Math.atan2(2.0 * (qw * qz + qx * qy), 1.0 - 2.0 * (qy * qy + qz * qz));
return new double[]{yaw, pitch, roll};
}
/**
* <p>
* 欧拉角 Yaw (偏航角) 转为 四元数
* </p>
*
* @param yaw Yaw (偏航角) 单位:度
* @param pitch Pitch (俯仰角) 单位:度
* @param roll Roll (翻滚角) 单位:度
* @return {@link Quaternion} 四元数
*/
public static Quaternion yawToQuaternion(double yaw, double pitch, double roll) {
// 将角度转换为弧度
double cy = Math.cos(Math.toRadians(yaw) * 0.5);
double sy = Math.sin(Math.toRadians(yaw) * 0.5);
double cp = Math.cos(Math.toRadians(pitch) * 0.5);
double sp = Math.sin(Math.toRadians(pitch) * 0.5);
double cr = Math.cos(Math.toRadians(roll) * 0.5);
double sr = Math.sin(Math.toRadians(roll) * 0.5);
// 计算四元数的各个分量
double w = cr * cp * cy + sr * sp * sy;
double x = sr * cp * cy - cr * sp * sy;
double y = cr * sp * cy + sr * cp * sy;
double z = cr * cp * sy - sr * sp * cy;
return new Quaternion(w, x, y, z);
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Quaternion {
private double w, x, y, z;
}
}
顺便记录下在表示转向时除了角度还可能使用弧度表示转换量,弧度和角度之间的换算如下:
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 角度弧度相互转换工具类
*
* @author admin
*/
public class AngleConverterUtil {
/**
* 将弧度值转换为度数
*
* @param radians 弧度值
* @return 对应的度数值, 保留4位小数
*/
public static double radiansToDegrees(double radians) {
double degrees = Math.toDegrees(radians);
return Double.parseDouble(String.format("%.4f", degrees));
}
/**
* 将度数值转换为弧度值
*
* @param degrees 度数值
* @return 对应的弧度值, 保留4位小数
*/
public static double degreesToRadians(double degrees) {
double radians = Math.toRadians(degrees);
return Double.parseDouble(String.format("%.4f", radians));
}
}