uuv_simulator是一个基于ROS1的属下机器人仿真包,具体详见其github主页,它可以安装在kinetic/lunar /melodic/noetic版本的ROS中。其中noetic版为其他开发者移植。作者使用的WSL2运行下的noetic版本,文中所列问题可能不具备普遍性。官方Wiki是最好的学习资料,在搭建仿真平台的过程中,也可参考Dave。
一、运行key_board_velocity.launch时报错
报错内容如下:
[rexrov/keyboard_uuv_velocity_teleop-4] process has died [pid 61583, exit code 255, cmd /home/lak/catkin_ws/src/uuv_simulator/uuv_teleop/scripts/vehicle_keyboard_teleop.py output:=/rexrov/cmd_vel __name:=keyboard_uuv_velocity_teleop __log:=/home/lak/.ros/log/3087991e-2dcb-11eb-82db-000c29a26e1a/rexrov-keyboard_uuv_velocity_teleop-4.log].
log file: /home/lak/.ros/log/3087991e-2dcb-11eb-82db-000c29a26e1a/rexrov-keyboard_uuv_velocity_teleop-4*.log
该问题在issue中有记录,简单来说就是vehicle_keyboard_teleop.py
文件没有找到.
解决办法:在/uuv_teleop/CMakeList.txt
中的catkin_install_python
一栏中,添加一行代码:scripts/vehicle_keyboard_teleop.py
,然后再进行编译即可。
二、PositionControl.py解析
-
没有节点发布
cmd_pose
话题,所以cmd_pose_callback
从未触发过(原因未知)。 -
当里程计信息更新时,触发
odometry_callback
回调函数,该函数的结构为:(ChatGPT所得)这段代码是一个回调函数,用于处理来自底盘系统的测量速度更新。首先,从消息中提取出位置和姿态信息,存储在变量 p 和 q 中。然后,将位置和姿态信息转换为 numpy 数组形式。如果系统尚未初始化(initialized = False),将当前的位置和姿态作为目标位置和目标姿态,并将 initialized 设置为 True,以便下次回调时不再执行此部分代码。
接下来,计算时间戳 t。然后,通过将目标位置与当前位置之差变换到机体坐标系下,得到在机体坐标系下的位置误差 e_pos_body。利用四元数进行姿态差计算,得到在机体坐标系下的姿态误差 e_rot_quat。如果位置误差的欧氏范数(仅考虑前两个维度)大于5.0,表示当前距离目标较远,此时将目标航向修正为朝向目标位置,并计算修正后的姿态误差。
接下来,利用位置误差和时间戳调用 pid_pos 的 regulate 方法计算线速度控制输出v_linear,再利用姿态误差和时间戳调用 pid_rot 的 regulate 方法计算角速度控制输出 v_angular。
最后,将计算得到的线速度和角速度转换为 Twist 消息格式,发布给底盘系统。 -
得到
e_pos_body
的过程:
trans.quaternion_matrix(q)
方法可以将四元数转换为变换矩阵T,再取T矩阵三阶子式即为旋转矩阵R。e_pos_world
为世界坐标系下机器人的位置误差,使它左乘旋转矩阵R,即R.dot(e_pos_world)
,即可得到机体坐标系下的位置误差。- 整理上述步骤代码,即可得到:
e_pos_body = trans.quaternion_matrix(q).transpose()[0:3,0:3].dot(e_pos_world)
- 得到
e_rot_quat
的过程:
- 使用
trans.quaternion_conjugate(q)
方法得到四元数q
的共轭q'
。 - 将
q'
与目标姿态quat_des
相乘得到机体姿态四元数的误差。(不是很懂四元数) - 整理上述步骤代码,即可得到:
e_rot_quat = trans.quaternion_multiply(trans.quaternion_conjugate(q), quat_des)
- 若在世界坐标系下的xy平面中,机体的实际位置与目标位置之间距离(范数)大于5,即
norm(e_pos_world[0:2])>5.0
时:
- 通过
arctan(Y之差/X之差)
计算实际机体坐标目标位置坐标之间的角度heading
,即heading = math.atan2(e_pos_world[1],e_pos_world[0])
- 按照计算所得的角度来更新目标四元数姿态,作为新的目标姿态四元数
quat_des
,使得机器人沿着[0,0,1]
即Z轴旋转heading
角度,朝着目标位置坐标方向前进。代码实现为:
quat_des = numpy.array([0, 0, math.sin(0.5*heading), math.cos(0.5*heading)])
- 最后计算新的机体姿态四元数误差。
- 整理上述步骤代码,即可得到:
if numpy.linalg.norm(e_pos_world[0:2]) > 5.0: heading = math.atan2(e_pos_world[1],e_pos_world[0]) quat_des = numpy.array([0, 0, math.sin(0.5*heading), math.cos(0.5*heading)]) e_rot_quat = trans.quaternion_multiply(trans.quaternion_conjugate(q), quat_des)
- 若在世界坐标系下的xy平面中,机体的实际位置与目标位置之间距离(范数)大于5,即