ROS——下位机驱动节点:读取并发布单片机IMU、编码器速度数据(python)

因为下位机是拿micropython写的,所以需要自己写一下上位机ros驱动节点,同时也顺便熟悉一下ROS的驱动部分。

ROS下位机驱动节点

节点功能

ROS驱动节点包括以下三个功能:

1.获取串口数据
2.发布ROS节点数据
  • IMU数据
  • 角速度、线速度数据
3.接收ROS节点数据
  • 目标角速度和线速度数据

接收节点我们将使用键盘控制的方式控制小车运动。

驱动代码

1.IMU数据发布

在这里我的IMU的9轴数据已经在下位机处理成标准格式数据,并以元组格式向上位机发送:

#micropython下位机发送的是元组格式
(imu.accel.xyz, imu.gyro.xyz, imu.mag.xyz)
((0.03735352, 0.967041, 0.2568359), (0.09160305, 1.114504, -0.4656488), (19.85156, -0.3644531, 4.905469))

通信部分大家按照自己的上下位机情况自行改写即可。

节点代码编写
import rospy
import serial
from sensor_msgs.msg import Imu, MagneticField

if __name__ == '__main__':
    # 创建节点
    rospy.init_node('my_driver_node')

    # 串口创建
    ser = serial.Serial(port='/dev/ttyACM0', baudrate=9600)
    
    # 创建publisher
    imu_pub = rospy.Publisher('imu', Imu, queue_size=10)
    mag_pub = rospy.Publisher('mag', MagneticField, queue_size=10)

    # 和下位机进行通讯
    while not rospy.is_shutdown():
        # 阻塞式的函数
        # 读取并解码数据,变成元组
        data = ser.readline()
        data = data.decode("utf-8")
        data = str(data)[1:-3] # 将无关字符去除 “\n” 和 b'' 去除
        try:
            data = eval(data) # 转化回元组形式
        except SyntaxError:
            data = None

        if data != None:
            imu_data = data[1]
            # 采用IMU类型发布数据
            imu = Imu()
            imu.linear_acceleration.x = imu_data[0][0]
            imu.linear_acceleration.y = imu_data[0][1]
            imu.linear_acceleration.z = imu_data[0][2]
            imu.angular_velocity.x = imu_data[1][0]
            imu.angular_velocity.y = imu_data[1][1]
            imu.angular_velocity.z = imu_data[1][2]
            imu_pub.publish(imu)
			
            mag = MagneticField()
            mag.magnetic_field.x = imu_data[2][0]
            mag.magnetic_field.y = imu_data[2][1]
            mag.magnetic_field.z = imu_data[2][2]
            mag_pub.publish(mag)

    rospy.spin()
查看发布数据

执行driver_node节点:

# 给串口赋权限
chmod 777 /dev/ttyACM0
source /devel/setup.bash
rosrun driver driver_node.py

再打印一下imu发布的数据:

rostopic echo imu

在这里插入图片描述

2.角速度、线速度数据发布

在这里我的下位机本来是直接把编码器值传到上位机,但是为了上位机方便起见,直接在下位机处理成双轮的速度,然后再发到上位机,数据格式同样是元组:

#micropython下位机发送的是元组格式
(speed_A, speed_B)
(0.0, 0.0)

通信部分大家按照自己的上下位机情况自行改写即可。

将双轮速度数据处理为角速度和线速度数据

首先明确差分模型的机器人始终做的是以R为半径的圆弧运动。如下图所示,机器人的线速度V、角速度ω,左右轮速用VL和VR表示,用D表示轮间距,D=2d,右轮到旋转中心的距离为L。
图源https://blog.csdn.net/zhao_ke_xue/article/details/108425922?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control

ROS端给机器人底盘(STM32单片机端)发送的是机器人要达到的线速度V和角速度ω,而我们底盘控制板需要的是左右轮速VL和VR来进行速度控制。所以他们的关系如下:
在这里插入图片描述

用python代码实现:

# 已知量,单位m
v = 0 # 机器人的线速度
w = 0 # 机器人的角速度
v_l = 0 # 左轮速度
v_r = 0 # 右轮速度
D = 0.2 # 轮间距
d = D/2

# 速度、角速度、左右轮速的关系式
v_l = v + wd
v_r = v - wd
v = (v_l + v_r)/2 
w = (v_l - v_r)/D

在知道了转换关系式后,我们就可以把角速度和线速度发布出去了。

节点代码编写
#!/usr/bin/env python
# coding:utf-8

import rospy
import serial
from sensor_msgs.msg import Imu, MagneticField
from geometry_msgs.msg import Twist

if __name__ == '__main__':
    # 参数初始化,单位m
    v = 0 # 机器人的线速度
    w = 0 # 机器人的角速度
    v_l = 0 # 左轮速度
    v_r = 0 # 右轮速度
    D = 0.2 # 轮间距
    d = D/2
    
    # 创建节点
    rospy.init_node('my_driver_node')

    # 串口通信
    ser = serial.Serial(port='/dev/ttyACM0', baudrate=115200)

    twist_pub = rospy.Publisher('get_vel', Twist, queue_size=10)

    # 和下位机进行通讯
    while not rospy.is_shutdown():
        # 阻塞式的函数
        # 读取并解码数据,变成元组
        data = ser.readline()
        data = data.decode("utf-8")
        data = str(data)[1:-3] # 将无关字符去除 “\n” 和 b'' 去除
        try:
            data = eval(data) # 转化回元组形式
        except SyntaxError:
            data = None
        
        if data != None:
            # 分别提取出速度和imu数据
            speed_data = data[0]
            print(data)
            try:
                # 发布角速度线速度数据
                twist = Twist()
                v_l = speed_data[0] # 获取左轮速度
                v_r = speed_data[1] # 获取右轮速度
                twist.linear.x =(v_l + v_r)/2
                twist.linear.y = 0
                twist.linear.z = 0
                twist.angular.x = 0
                twist.angular.y = 0
                twist.angular.z = (v_l - v_r)/D
                twist_pub.publish(twist)

            except TypeError:
                pass    
    
    rospy.spin()

查看发布数据

执行driver_node节点:

# 给串口赋权限
chmod 777 /dev/ttyACM0
source /devel/setup.bash
rosrun driver driver_node.py

再打印一下twist发布的数据:

rostopic echo twist

在这里插入图片描述

driver_node.py节点完整代码

#!/usr/bin/env python
# coding:utf-8

import rospy
import serial
from sensor_msgs.msg import Imu, MagneticField
from geometry_msgs.msg import Twist

if __name__ == '__main__':
    # 参数初始化,单位m
    v = 0 # 机器人的线速度
    w = 0 # 机器人的角速度
    v_l = 0 # 左轮速度
    v_r = 0 # 右轮速度
    D = 0.2 # 轮间距
    d = D/2
    
    # 创建节点
    rospy.init_node('my_driver_node')

    # 串口通信
    ser = serial.Serial(port='/dev/ttyACM0', baudrate=115200)
    
    # imu数据发布者
    imu_pub = rospy.Publisher('imu', Imu, queue_size=10)
    mag_pub = rospy.Publisher('mag', MagneticField, queue_size=10)

    twist_pub = rospy.Publisher('get_vel', Twist, queue_size=10)


    # 控制指令
    # rospy.Subscriber("cmd_vel", Twist, callback, Socket)

    # 和下位机进行通讯
    while not rospy.is_shutdown():
        # 阻塞式的函数
        # 读取并解码数据,变成元组
        data = ser.readline()
        data = data.decode("utf-8")
        data = str(data)[1:-3] # 将无关字符去除 “\n” 和 b'' 去除
        try:
            data = eval(data) # 转化回元组形式
        except SyntaxError:
            data = None
        
        if data != None:
            # 分别提取出速度和imu数据
            speed_data = data[0]
            imu_data = data[1]
            print(data)
            try:
                # 发布imu数据
                imu = Imu()
                imu.linear_acceleration.x = imu_data[0][0]
                imu.linear_acceleration.y = imu_data[0][1]
                imu.linear_acceleration.z = imu_data[0][2]
                imu.angular_velocity.x = imu_data[1][0]
                imu.angular_velocity.y = imu_data[1][1]
                imu.angular_velocity.z = imu_data[1][2]
                imu_pub.publish(imu)

                mag = MagneticField()
                mag.magnetic_field.x = imu_data[2][0]
                mag.magnetic_field.y = imu_data[2][1]
                mag.magnetic_field.z = imu_data[2][2]
                mag_pub.publish(mag)
            
                # 发布角速度线速度数据
                twist = Twist()
                v_l = speed_data[0] # 左轮速度
                v_r = speed_data[1] # 右轮速度
                twist.linear.x =(v_l + v_r)/2
                twist.linear.y = 0
                twist.linear.z = 0
                twist.angular.x = 0
                twist.angular.y = 0
                twist.angular.z = (v_l - v_r)/D
                twist_pub.publish(twist)

            except TypeError:
                pass    
    
    rospy.spin()

参考文章:

  • 8
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Ubuntu 18.04中读取IMU和GPS数据并将其作为节点信息发布出去,你可以按照以下步骤进行操作: 1. 安装所需的驱动程序和软件包:首先,确保你的IMU和GPS设备驱动程序已正确安装。如果需要,可以从设备制造商的官方网站下载并安装适当的驱动程序。此外,你还需要安装ROS(机器人操作系统)以及与IMU和GPS相关的ROS软件包,如`ros-melodic-imu-tools`和`ros-melodic-gps-common`。 2. 设置ROS工作区:创建一个ROS工作区来管理你的ROS项目。使用以下命令创建一个新的工作区目录,并切换到该目录: ```shell mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src ``` 3. 创建ROS软件包:在ROS工作区的src目录中创建一个ROS软件包。使用以下命令创建一个名为`my_robot`的软件包: ```shell catkin_create_pkg my_robot rospy roscpp std_msgs sensor_msgs nav_msgs ``` 4. 下载并编译相关ROS软件包:使用以下命令将之前提到的IMU和GPS相关的软件包下载到ROS工作区的src目录中: ```shell git clone https://github.com/ccny-ros-pkg/imu_tools.git git clone https://github.com/ros-drivers/nmea_navsat_driver.git ``` 5. 编译软件包:返回到ROS工作区目录并编译软件包: ```shell cd ~/catkin_ws catkin_make ``` 6. 配置和启动ROS节点:在配置文件中设置IMU和GPS传感器的参数,如设备的串口号、波特率等。然后,创建一个ROS节点,并发布IMU和GPS数据。你可以使用ROSPython或C++ API来实现逻辑。 以下是一个使用Python编写的示例节点文件,用于读取IMU和GPS数据并将其发布出去: ```python #!/usr/bin/env python import rospy from sensor_msgs.msg import Imu, NavSatFix def imu_gps_publisher(): rospy.init_node('imu_gps_publisher', anonymous=True) imu_pub = rospy.Publisher('imu', Imu, queue_size=10) gps_pub = rospy.Publisher('gps', NavSatFix, queue_size=10) # 读取IMU和GPS数据的逻辑 # 创建IMU消息并发布 imu_msg = Imu() imu_pub.publish(imu_msg) # 创建GPS消息并发布 gps_msg = NavSatFix() gps_pub.publish(gps_msg) rospy.spin() if __name__ == '__main__': try: imu_gps_publisher() except rospy.ROSInterruptException: pass ``` 你可以在该节点的逻辑部分添加读取IMU和GPS数据的实际代码,然后将数据填充到相应的ROS消息中,并通过发布器进行发布。 7. 运行ROS节点:运行ROS节点以开始发布IMU和GPS数据。在终端中输入以下命令: ```shell rosrun my_robot imu_gps_publisher.py ``` 现在,你的Ubuntu 18.04系统应该能够读取IMU和GPS数据,并将其作为节点信息发布出去。你可以使用ROS工具来验证发布数据是否正确到达。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值