赞
踩
最近在网上购买了ROS机器人IMU模块ARHS姿态传感器,购买的型号是HFI-B6,下面是官方给出的资料链接,这种信号的IMU是ROS操作系统专用的,能够直接读取当前模块的角度信息,并打印出来,而且传输速率非常快,相比较于传统的imu模块而言,使用起来更加的方便,因为官方已经完成了底层代码的编写,我们在使用上不需要考虑通信的问题
链接: https://gitee.com/HANDS-FREE/handsfree_ros_imu/blob/master/tutorials/doc.md.
如果你没有gitee账号的话,需要重新注册一个,才能下载gitee网站上的ROS驱动功能包
博主的linux系统是ubuntu16.04,安装的是ros-kinetic版本,对应的python版本是python2,点击python2右边的下载驱动软件压缩包,即可完成驱动软件压缩包的下载
打开一个终端,在终端中输入,这里是针对kinetic版本的命令,如果你们是其他版本的话,还是安装官方教程来进行下载安装
sudo apt-get install ros-kinetic-imu-tools ros-kinetic-rviz-imu-plugin
sudo apt-get install python-visual
在终端中输入以下指令
mkdir -p ~/handsfree/handsfree_ros_ws/src/
cd ~/handsfree/handsfree_ros_ws/src/
将之前下载好的软件驱动压缩包解压后,提取到 src 目录下,正常情况下提取出来的压缩包文件名是handsfree_ros_imu,如果不是请修改成 handsfree_ros_imu
cd ~/handsfree/handsfree_ros_ws/
catkin_make
cd ~/handsfree/handsfree_ros_ws/src/handsfree_ros_imu/scripts/
sudo chmod 777 *.py
echo “source ~/handsfree/handsfree_ros_ws/devel/setup.bash” >> ~/.bashrc
source ~/.bashrc
连接 IMU 的 USB,检查电脑能否识别到 ttyUSB0,检测到 ttyUSB0 后,给 ttyUSB0 赋权限
ls /dev/ttyUSB0
sudo chmod 777 /dev/ttyUSB0
在下载的驱动软件功能包中,我们可以看到,一共有6个.py文件,其中,有四个是对应于不同IMU模块的.py文件,get_imu_rpy.py文件是读取当前模块的角度信息值,包括Roll(翻滚角),Pitch(俯仰角)和Yaw(偏航角)
如果我们要在终端下实时读取当前模块的角度信息,我们先要将IMU模块与ubuntu系统连接上,打开终端,输入以下命令
ls /dev/ttyUSB0
sudo chmod 777 /dev/ttyUSB0
然后在终端中输入roscore,启动ros_master,重新打开一个终端,在终端中输入命令rosrun handsfree_ros_imu hfi_b6_ros.py,这里要根据你购买的IMU模块的型号进行选择,然后在重新打开一个终端,在终端中输入rosrun handsfree_ros_imu get_imu_rpy.py,你就会看到实时打印的角度信息了
rosrun handsfree_ros_imu hfi_b6_ros.py
rosrun handsfree_ros_imu get_imu_rpy.py
相比于其他的一些可视化界面,读取当前模块的角度信息是最重要的,其他相关部分功能的,大家可以自行去官网上进行查看,如果要使用rviz来进行查看IMU模块的变化信息的话,也可以roslaunch功能包中的其他launch文件,也很方便
#!/usr/bin/env python # -*- coding:utf-8 -*- import math import serial import struct import time import rospy import serial.tools.list_ports from geometry_msgs.msg import Quaternion from sensor_msgs.msg import Imu from sensor_msgs.msg import MagneticField cov_orientation = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] cov_angular_velocity = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] cov_linear_acceleration = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] def eul_to_qua(Eular): eular_div = [0, 0, 0] eular_div[0], eular_div[1], eular_div[2] = Eular[0] / 2.0, Eular[1] / 2.0, Eular[2] / 2.0 ca, cb, cc = math.cos(eular_div[0]), math.cos(eular_div[1]), math.cos(eular_div[2]) sa, sb, sc = math.sin(eular_div[0]), math.sin(eular_div[1]), math.sin(eular_div[2]) x = sa * cb * cc - ca * sb * sc y = ca * sb * cc + sa * cb * sc z = ca * cb * sc - sa * sb * cc w = ca * cb * cc + sa * sb * sc orientation = Quaternion() orientation.x, orientation.y, orientation.z, orientation.w = x, y, z, w return orientation # 在缓冲数据中找到第一个包的起始位置 def find_first_package(buffer): i = 0 while True: if buffer[i] == 0x55 and (buffer[i + 1] & 0x50) == 0x50: return i if i + 2 >= len(buffer): return -1 i += 1 # 检查校验和 def sb_sum_chech(byte_temp): # if(len(byte_temp)==11) : if (((byte_temp[0] + byte_temp[1] + byte_temp[2] + byte_temp[3] + byte_temp[4] + byte_temp[5] + byte_temp[6] + byte_temp[7] + byte_temp[8] + byte_temp[9]) & 0xff) == byte_temp[10]): # print('sum check ok!') return True else: # print('sum check false!') return False # 查找 ttyUSB* 设备 def find_ttyUSB(): count = 0 port_list = [] for ser in serial.tools.list_ports.comports(): if str(ser.name).find("USB") == 3: print("\033[32m找到了:" + str(ser.name) + " 设备\033[0m") port_list.append(str(ser.name)) else: count += 1 if count == len(list(serial.tools.list_ports.comports())): print("\033[31m没有找到相关的 ttyUSB* 设备\033[0m") exit(0) return port_list if __name__ == "__main__": port_list = find_ttyUSB() rospy.init_node("imu") port = rospy.get_param("~port", "/dev/ttyUSB0") baudrate = rospy.get_param("~baudrate", 921600) try: hf_imu = serial.Serial(port=port, baudrate=baudrate, timeout=0.5) if hf_imu.isOpen(): rospy.loginfo("\033[32m串口打开成功...\033[0m") else: hf_imu.open() rospy.loginfo("\033[32m打开串口成功...\033[0m") except Exception as e: print(e) rospy.loginfo("\033[31m串口错误,其他因素\033[0m") exit(0) else: imu_pub = rospy.Publisher("handsfree/imu", Imu, queue_size=10) receive_buffer = bytearray() linear_acceleration_x = 0 linear_acceleration_y = 0 linear_acceleration_z = 0 angular_velocity_x = 0 angular_velocity_y = 0 angular_velocity_z = 0 data_timeout = 0 while not rospy.is_shutdown(): if data_timeout < 1000: data_timeout += 1 else: print("\033[31m读取不到 imu 数据,当前 ttyUSB0 设备不是 imu\033[0m") exit(0) eul = [] try: count = hf_imu.inWaiting() except Exception as e: print(e) print ("\033[31mimu 失联\033[0m") exit(0) else: if count > 0: s = hf_imu.read(count) receive_buffer += s stamp = rospy.get_rostime() dataLen = len(receive_buffer) if dataLen >= 11: # 去掉第1个包头前的数据 headerPos = find_first_package(receive_buffer) if headerPos >= 0: if headerPos > 0: receive_buffer[0:headerPos] = b'' # 取 Config.minPackageLen 整数倍长度的数据 if dataLen - headerPos >= 11: packageCount = int((dataLen - headerPos) / 11) if packageCount > 0: cutLen = packageCount * 11 temp = receive_buffer[0:cutLen] # 按16进制字符串的形式显示收到的内容 receive_buffer[0:cutLen] = b'' # 解析数据,逐个数据包进行解析 for i in range(packageCount): beginIdx = int(i * 11) endIdx = int(i * 11 + 11) byte_temp = temp[beginIdx:endIdx] # 校验和通过了的数据包才进行解析 imu_msg = Imu() imu_msg.header.stamp = stamp imu_msg.header.frame_id = "base_link" mag_msg = MagneticField() mag_msg.header.stamp = stamp mag_msg.header.frame_id = "base_link" if sb_sum_chech(byte_temp): data_timeout = 0 Data = list(struct.unpack("hhhh", byte_temp[2:10])) # 加速度 if byte_temp[1] == 0x51: linear_acceleration_x = Data[0] / 32768.0 * 16 * -9.8 linear_acceleration_y = Data[1] / 32768.0 * 16 * -9.8 linear_acceleration_z = Data[2] / 32768.0 * 16 * -9.8 # 角速度 if byte_temp[1] == 0x52: imu_msg.orientation_covariance = cov_orientation angular_velocity_x = Data[0] / 32768.0 * 2000 * math.pi / 180 angular_velocity_y = Data[1] / 32768.0 * 2000 * math.pi / 180 angular_velocity_z = Data[2] / 32768.0 * 2000 * math.pi / 180 # 姿态角 if byte_temp[1] == 0x53: for i in range(3): eul.append(Data[i] / 32768.0 * math.pi) imu_msg.orientation = eul_to_qua(eul) imu_msg.linear_acceleration.x = linear_acceleration_x imu_msg.linear_acceleration.y = linear_acceleration_y imu_msg.linear_acceleration.z = linear_acceleration_z imu_msg.angular_velocity.x = angular_velocity_x imu_msg.angular_velocity.y = angular_velocity_y imu_msg.angular_velocity.z = angular_velocity_z imu_msg.angular_velocity_covariance = cov_angular_velocity imu_msg.linear_acceleration_covariance = cov_linear_acceleration imu_pub.publish(imu_msg) time.sleep(0.001)
#!/usr/bin/env python #coding=UTF-8 import rospy import tf from tf.transformations import * from sensor_msgs.msg import Imu def callback(data): #这个函数是tf中的,可以将四元数转成欧拉角 (r,p,y) = tf.transformations.euler_from_quaternion((data.orientation.x,data.orientation.y,data.orientation.z,data.orientation.w)) #由于是弧度制,下面将其改成角度制看起来更方便 rospy.loginfo("Roll = %f, Pitch = %f, Yaw = %f",r*180/3.1415926,p*180/3.1415926,y*180/3.1415926) def get_imu(): rospy.init_node('get_imu', anonymous=True) rospy.Subscriber("/handsfree/imu", Imu, callback) #接受topic名称 rospy.spin() if __name__ == '__main__': get_imu()
官方使用的是python,编写了一个发布者和订阅者,通过订阅IMU发布的信息,并将其转换为角度信息,就得到了当前模块的调度信息,这款模块对于ROS而言,使用起来很方便
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。