ROS惯导数据发布(Python)

摘要:
1、 背景基本配置:ubuntu16.04,ROSDYNAMIC惯性导航模型:Vittek Intelligence WT61C提供的参考程序通过手动比较每个字节来正式确定数据包/数据帧。我个人认为它比较繁琐,因此使用Python的re和struct模块来简化其数据匹配和提取,并实现ROS中惯性导航数据的发布。

一、背景

  基本配置:ubuntu 16.04,ROS Kinetic

  惯导型号:维特智能 WT61C(六轴惯导)

  维特智能官方提供的参考程序是通过手动比较各个字节来确定数据包/数据帧的,个人认为比较繁琐,因此采用Python的re(正则表达式)和struct(字节处理)模块简化其数据匹配和提取,并实现惯导数据在ROS中的发布。

二、程序

  惯导程序如下:

#!/usr/bin/env python


import math
import re
import serial
import struct
import time

import rospy
from geometry_msgs.msg import Quaternion, Vector3
from sensor_msgs.msg import Imu


cov_orientation = [0.00174533, 0, 0, 0, 0.00174533, 0, 0, 0, 0.00174533]
cov_angular_velocity, cov_linear_acceleration = [0.00104720, 0, 0, 0, 0.00104720, 0, 0, 0, 0.00104720], [0.0049, 0, 0, 0, 0.0049, 0, 0, 0, 0.0049]


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


accCali = "xffxaax67"
feature = "UQ(.{6,6}).{3,3}UR(.{6,6}).{3,3}US(.{6,6}).{3,3}"
fmt_B, fmt_h = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", "<hhh"


if __name__ == "__main__":
    rospy.init_node("imu")

    port = rospy.get_param("~port", "/dev/imu")
    imuHandle = serial.Serial(port=port, baudrate=115200, timeout=0.5)
    
    if imuHandle.isOpen():
        rospy.loginfo("SUCCESS")
    else:
        rospy.loginfo("FAILURE")

    # Accelerometer Calibration
    time.sleep(0.5)
    imuHandle.write(accCali) 
    time.sleep(0.5)

    imuPub = rospy.Publisher("imu", Imu, queue_size=10)

    while True:
        data = imuHandle.read(size=65)
        stamp = rospy.get_rostime()
        result = re.search(feature, data)

        if result:
            # check and get data
            frame = struct.unpack(fmt_B, result.group())
            sum_Q, sum_R, sum_S = 0, 0, 0
            for i in range(0, 10):
                sum_Q, sum_R, sum_S = sum_Q+frame[i], sum_R+frame[i+11], sum_S+frame[i+22]
            sum_Q, sum_R, sum_S = sum_Q&0x000000ff, sum_R&0x000000ff, sum_S&0x000000ff

            if (sum_Q==frame[10]) and (sum_R==frame[21]) and (sum_S==frame[32]):
                af, wf, ef = struct.unpack(fmt_h, result.group(1)), struct.unpack(fmt_h, result.group(2)), struct.unpack(fmt_h, result.group(3))

                af_l, wf_l, ef_l = [], [], []
                for i in range(0, 3):
                    af_l.append(af[i]/32768.0*16*-9.8), wf_l.append(wf[i]/32768.0*2000*math.pi/180), ef_l.append(ef[i]/32768.0*math.pi)

                imuMsg = Imu()
                imuMsg.header.stamp, imuMsg.header.frame_id = stamp, "base_link"
                imuMsg.orientation = eul_to_qua(ef_l)
                imuMsg.orientation_covariance = cov_orientation
                imuMsg.angular_velocity.x, imuMsg.angular_velocity.y, imuMsg.angular_velocity.z = wf_l[0], wf_l[1], wf_l[2]
                imuMsg.angular_velocity_covariance = cov_angular_velocity
                imuMsg.linear_acceleration.x, imuMsg.linear_acceleration.y, imuMsg.linear_acceleration.z = af_l[0], af_l[1], af_l[2]
                imuMsg.linear_acceleration_covariance = cov_linear_acceleration

                imuPub.publish(imuMsg)

        time.sleep(0.01)

  完整的ROS包地址:https://gitee.com/xjEzekiel/imu

三、分析

  1、time.sleep(0.01)对应于原始数据频率100Hz;

  2、WT61C一个数据包33字节,程序一次读取65字节,必然包含一个完整的数据包;

    1)导致惯导数据发布频率降为100/2=50Hz,对于一般应用毫无问题;

    2)结合1、可知,程序绝大多数时间在等待原始数据到来,因此在读取原始数据之后获取时间戳较为准确;

    3)Python的串口读取内部采用select,不会堵塞;

  3、Python中字节数组=str,UQRS对应于x55x51x52x53;

  4、变量accCali是WT61C的加计校准指令;

  5、函数eul_to_qua用于欧拉角(RPY)转四元数;

  6、变量cov_*是*的协方差;

以上。

免责声明:文章转载自《ROS惯导数据发布(Python)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Jenkins部署git+python项目实现持续集成pytest框架(四)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【Python学习笔记】之格式化输入输出

1. python3设置print输出不换行 函数原型 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) 对应参数含义如下 objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。 sep -- 用来间隔多个对象,默认值是一个空格。 end...

ROS launch 文件的编写

ROS提供了一个同时启动节点管理器(master)和多个节点的途径,即使用启动文件(launch file)。事实上,在ROS功能包中,启动文件的使用是非常普遍的。任何包含两个或两个以上节点的系统都可以利用启动文件来指定和配置需要使用的节点。通常的命名方案是以.launch作为启动文件的后缀,启动文件是XML文件。一般把启动文件存储在取名为launch的目...

python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底懵逼。所以写一篇总结讲讲yield的东西。 分成四块来讲, 这篇先说yield基本用法,后面会重点将yield from的牛逼之处 一, 生成器中使用yiel...

使用Python爬虫爬取网络美女图片

代码地址如下:http://www.demodashi.com/demo/13500.html 准备工作 安装python3.6 略 安装requests库(用于请求静态页面) pip install requests -i https://mirrors.ustc.edu.cn/pypi/web/simple 安装lxml库(用于解析html文件) p...

python科学计算_scipy_常数与优化

scipy在numpy的基础上提供了众多的数学、科学以及工程计算中常用的模块;是强大的数值计算库; 1. 常数和特殊函数 scipy的constants模块包含了众多的物理常数: import scipy.constants as CC.c  #真空中的光速C.h  #普朗克常数C.pi #圆周率  在C.physical_constants字典中,通过物...

适合初学者的ROS机器人教程(2): Ubuntu下ROS使用Gazebo和Rviz对UR5机器人建模

作者:知乎@Ai酱 本文的前提是:默认你已安装ROS和Gazebo和Rviz,并且使用Ubuntu。Gazebo显示不出东西?检查下/home/用户名/.gazebo/models下面常见的模型有木有拷贝进去有数以百计的基本模型。 安装UR5的包 $ sudo apt-get install ros-kinetic-ur-gazebo ros-...