|
|
|
@ -1,7 +1,22 @@
|
|
|
|
|
#!/usr/bin/env python
|
|
|
|
|
# encoding: utf-8
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
"""
|
|
|
|
|
X3型机器人底盘驱动节点
|
|
|
|
|
X3 robot chassis driver node
|
|
|
|
|
|
|
|
|
|
#public lib
|
|
|
|
|
功能说明 (Functionality):
|
|
|
|
|
- X3型机器人底层运动控制
|
|
|
|
|
- IMU数据采集和发布
|
|
|
|
|
- 电池电压监控
|
|
|
|
|
- RGB灯光控制
|
|
|
|
|
- 蜂鸣器控制
|
|
|
|
|
- 关节状态发布
|
|
|
|
|
|
|
|
|
|
作者 (Author): UVPTCCS Team
|
|
|
|
|
日期 (Date): 2024
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# 通用库 (Common libraries)
|
|
|
|
|
import sys
|
|
|
|
|
import math
|
|
|
|
|
import random
|
|
|
|
@ -10,169 +25,282 @@ from math import pi
|
|
|
|
|
from time import sleep
|
|
|
|
|
from Rosmaster_Lib import Rosmaster
|
|
|
|
|
|
|
|
|
|
#ros lib
|
|
|
|
|
# ROS2相关库 (ROS2 related libraries)
|
|
|
|
|
import rclpy
|
|
|
|
|
from rclpy.node import Node
|
|
|
|
|
from std_msgs.msg import String,Float32,Int32,Bool
|
|
|
|
|
from std_msgs.msg import String, Float32, Int32, Bool
|
|
|
|
|
from geometry_msgs.msg import Twist
|
|
|
|
|
from sensor_msgs.msg import Imu,MagneticField, JointState
|
|
|
|
|
from sensor_msgs.msg import Imu, MagneticField, JointState
|
|
|
|
|
from rclpy.clock import Clock
|
|
|
|
|
|
|
|
|
|
#from dynamic_reconfigure.server import Server
|
|
|
|
|
car_type_dic={
|
|
|
|
|
'R2':5,
|
|
|
|
|
'X3':1,
|
|
|
|
|
'NONE':-1
|
|
|
|
|
# 机器人类型字典 (Robot type dictionary)
|
|
|
|
|
car_type_dic = {
|
|
|
|
|
'R2': 5, # R2型机器人 (R2 robot type)
|
|
|
|
|
'X3': 1, # X3型机器人 (X3 robot type)
|
|
|
|
|
'NONE': -1 # 无类型 (No type)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class yahboomcar_driver(Node):
|
|
|
|
|
def __init__(self, name):
|
|
|
|
|
super().__init__(name)
|
|
|
|
|
global car_type_dic
|
|
|
|
|
self.RA2DE = 180 / pi
|
|
|
|
|
self.car = Rosmaster()
|
|
|
|
|
self.car.set_car_type(1)
|
|
|
|
|
#get parameter
|
|
|
|
|
self.declare_parameter('car_type', 'X3')
|
|
|
|
|
self.car_type = self.get_parameter('car_type').get_parameter_value().string_value
|
|
|
|
|
print (self.car_type)
|
|
|
|
|
self.declare_parameter('imu_link', 'imu_link')
|
|
|
|
|
self.imu_link = self.get_parameter('imu_link').get_parameter_value().string_value
|
|
|
|
|
print (self.imu_link)
|
|
|
|
|
self.declare_parameter('Prefix', "")
|
|
|
|
|
self.Prefix = self.get_parameter('Prefix').get_parameter_value().string_value
|
|
|
|
|
print (self.Prefix)
|
|
|
|
|
self.declare_parameter('xlinear_limit', 1.0)
|
|
|
|
|
self.xlinear_limit = self.get_parameter('xlinear_limit').get_parameter_value().double_value
|
|
|
|
|
print (self.xlinear_limit)
|
|
|
|
|
self.declare_parameter('ylinear_limit', 1.0)
|
|
|
|
|
self.ylinear_limit = self.get_parameter('ylinear_limit').get_parameter_value().double_value
|
|
|
|
|
print (self.ylinear_limit)
|
|
|
|
|
self.declare_parameter('angular_limit', 5.0)
|
|
|
|
|
self.angular_limit = self.get_parameter('angular_limit').get_parameter_value().double_value
|
|
|
|
|
print (self.angular_limit)
|
|
|
|
|
|
|
|
|
|
#create subcriber
|
|
|
|
|
self.sub_cmd_vel = self.create_subscription(Twist,"cmd_vel",self.cmd_vel_callback,1)
|
|
|
|
|
self.sub_RGBLight = self.create_subscription(Int32,"RGBLight",self.RGBLightcallback,100)
|
|
|
|
|
self.sub_BUzzer = self.create_subscription(Bool,"Buzzer",self.Buzzercallback,100)
|
|
|
|
|
|
|
|
|
|
#create publisher
|
|
|
|
|
self.EdiPublisher = self.create_publisher(Float32,"edition",100)
|
|
|
|
|
self.volPublisher = self.create_publisher(Float32,"voltage",100)
|
|
|
|
|
self.staPublisher = self.create_publisher(JointState,"joint_states",100)
|
|
|
|
|
self.velPublisher = self.create_publisher(Twist,"vel_raw",50)
|
|
|
|
|
self.imuPublisher = self.create_publisher(Imu,"/imu/data_raw",100)
|
|
|
|
|
self.magPublisher = self.create_publisher(MagneticField,"/imu/mag",100)
|
|
|
|
|
|
|
|
|
|
#create timer
|
|
|
|
|
self.timer = self.create_timer(0.1, self.pub_data)
|
|
|
|
|
|
|
|
|
|
#create and init variable
|
|
|
|
|
self.edition = Float32()
|
|
|
|
|
self.edition.data = 1.0
|
|
|
|
|
self.car.create_receive_threading()
|
|
|
|
|
#callback function
|
|
|
|
|
def cmd_vel_callback(self,msg):
|
|
|
|
|
# 小车运动控制,订阅者回调函数
|
|
|
|
|
# Car motion control, subscriber callback function
|
|
|
|
|
if not isinstance(msg, Twist): return
|
|
|
|
|
# 下发线速度和角速度
|
|
|
|
|
# Issue linear vel and angular vel
|
|
|
|
|
vx = msg.linear.x*1.0
|
|
|
|
|
#vy = msg.linear.y/1000.0*180.0/3.1416 #Radian system
|
|
|
|
|
vy = msg.linear.y*1.0
|
|
|
|
|
angular = msg.angular.z*1.0 # wait for chang
|
|
|
|
|
self.car.set_car_motion(vx, vy, angular)
|
|
|
|
|
'''print("cmd_vx: ",vx)
|
|
|
|
|
print("cmd_vy: ",vy)
|
|
|
|
|
print("cmd_angular: ",angular)'''
|
|
|
|
|
#rospy.loginfo("nav_use_rot:{}".format(self.nav_use_rotvel))
|
|
|
|
|
#print(self.nav_use_rotvel)
|
|
|
|
|
def RGBLightcallback(self,msg):
|
|
|
|
|
# 流水灯控制,服务端回调函数 RGBLight control
|
|
|
|
|
if not isinstance(msg, Int32): return
|
|
|
|
|
# print ("RGBLight: ", msg.data)
|
|
|
|
|
for i in range(3): self.car.set_colorful_effect(msg.data, 6, parm=1)
|
|
|
|
|
def Buzzercallback(self,msg):
|
|
|
|
|
if not isinstance(msg, Bool): return
|
|
|
|
|
if msg.data:
|
|
|
|
|
for i in range(3): self.car.set_beep(1)
|
|
|
|
|
else:
|
|
|
|
|
for i in range(3): self.car.set_beep(0)
|
|
|
|
|
|
|
|
|
|
#pub data
|
|
|
|
|
def pub_data(self):
|
|
|
|
|
time_stamp = Clock().now()
|
|
|
|
|
imu = Imu()
|
|
|
|
|
twist = Twist()
|
|
|
|
|
battery = Float32()
|
|
|
|
|
edition = Float32()
|
|
|
|
|
mag = MagneticField()
|
|
|
|
|
state = JointState()
|
|
|
|
|
state.header.stamp = time_stamp.to_msg()
|
|
|
|
|
state.header.frame_id = "joint_states"
|
|
|
|
|
if len(self.Prefix)==0:
|
|
|
|
|
state.name = ["back_right_joint", "back_left_joint","front_left_steer_joint","front_left_wheel_joint",
|
|
|
|
|
"front_right_steer_joint", "front_right_wheel_joint"]
|
|
|
|
|
else:
|
|
|
|
|
state.name = [self.Prefix+"back_right_joint",self.Prefix+ "back_left_joint",self.Prefix+"front_left_steer_joint",self.Prefix+"front_left_wheel_joint",
|
|
|
|
|
self.Prefix+"front_right_steer_joint", self.Prefix+"front_right_wheel_joint"]
|
|
|
|
|
|
|
|
|
|
#print ("mag: ",self.car.get_magnetometer_data())
|
|
|
|
|
edition.data = self.car.get_version()*1.0
|
|
|
|
|
battery.data = self.car.get_battery_voltage()*1.0
|
|
|
|
|
ax, ay, az = self.car.get_accelerometer_data()
|
|
|
|
|
gx, gy, gz = self.car.get_gyroscope_data()
|
|
|
|
|
mx, my, mz = self.car.get_magnetometer_data()
|
|
|
|
|
mx = mx * 1.0
|
|
|
|
|
my = my * 1.0
|
|
|
|
|
mz = mz * 1.0
|
|
|
|
|
vx, vy, angular = self.car.get_motion_data()
|
|
|
|
|
'''print("vx: ",vx)
|
|
|
|
|
print("vy: ",vy)
|
|
|
|
|
print("angular: ",angular)'''
|
|
|
|
|
# 发布陀螺仪的数据
|
|
|
|
|
# Publish gyroscope data
|
|
|
|
|
imu.header.stamp = time_stamp.to_msg()
|
|
|
|
|
imu.header.frame_id = self.imu_link
|
|
|
|
|
imu.linear_acceleration.x = ax*1.0
|
|
|
|
|
imu.linear_acceleration.y = ay*1.0
|
|
|
|
|
imu.linear_acceleration.z = az*1.0
|
|
|
|
|
imu.angular_velocity.x = gx*1.0
|
|
|
|
|
imu.angular_velocity.y = gy*1.0
|
|
|
|
|
imu.angular_velocity.z = gz*1.0
|
|
|
|
|
|
|
|
|
|
mag.header.stamp = time_stamp.to_msg()
|
|
|
|
|
mag.header.frame_id = self.imu_link
|
|
|
|
|
mag.magnetic_field.x = mx*1.0
|
|
|
|
|
mag.magnetic_field.y = my*1.0
|
|
|
|
|
mag.magnetic_field.z = mz*1.0
|
|
|
|
|
|
|
|
|
|
# 将小车当前的线速度和角速度发布出去
|
|
|
|
|
# Publish the current linear vel and angular vel of the car
|
|
|
|
|
twist.linear.x = vx *1.0
|
|
|
|
|
twist.linear.y = vy *1.0
|
|
|
|
|
twist.angular.z = angular*1.0
|
|
|
|
|
self.velPublisher.publish(twist)
|
|
|
|
|
# print("ax: %.5f, ay: %.5f, az: %.5f" % (ax, ay, az))
|
|
|
|
|
# print("gx: %.5f, gy: %.5f, gz: %.5f" % (gx, gy, gz))
|
|
|
|
|
# print("mx: %.5f, my: %.5f, mz: %.5f" % (mx, my, mz))
|
|
|
|
|
# rospy.loginfo("battery: {}".format(battery))
|
|
|
|
|
# rospy.loginfo("vx: {}, vy: {}, angular: {}".format(twist.linear.x, twist.linear.y, twist.angular.z))
|
|
|
|
|
self.imuPublisher.publish(imu)
|
|
|
|
|
self.magPublisher.publish(mag)
|
|
|
|
|
self.volPublisher.publish(battery)
|
|
|
|
|
self.EdiPublisher.publish(edition)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
X3型机器人驱动节点类
|
|
|
|
|
X3 robot driver node class
|
|
|
|
|
|
|
|
|
|
功能 (Functions):
|
|
|
|
|
- 机器人底层运动控制
|
|
|
|
|
- 传感器数据采集和发布
|
|
|
|
|
- 外设控制(灯光、蜂鸣器)
|
|
|
|
|
- 实时状态监控
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, name):
|
|
|
|
|
"""
|
|
|
|
|
初始化X3机器人驱动节点
|
|
|
|
|
Initialize X3 robot driver node
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
name (str): 节点名称 (Node name)
|
|
|
|
|
"""
|
|
|
|
|
super().__init__(name)
|
|
|
|
|
global car_type_dic
|
|
|
|
|
|
|
|
|
|
# 角度转换常数 (Angle conversion constant)
|
|
|
|
|
self.RA2DE = 180 / pi # 弧度转角度 (Radians to degrees)
|
|
|
|
|
|
|
|
|
|
# 初始化机器人底层库 (Initialize robot low-level library)
|
|
|
|
|
self.car = Rosmaster()
|
|
|
|
|
self.car.set_car_type(1) # 设置为X3型机器人 (Set to X3 robot type)
|
|
|
|
|
|
|
|
|
|
# 声明和获取参数 (Declare and get parameters)
|
|
|
|
|
self.declare_parameter('car_type', 'X3') # 机器人类型 (Robot type)
|
|
|
|
|
self.car_type = self.get_parameter('car_type').get_parameter_value().string_value
|
|
|
|
|
print("Car type:", self.car_type)
|
|
|
|
|
|
|
|
|
|
self.declare_parameter('imu_link', 'imu_link') # IMU坐标系名称 (IMU frame name)
|
|
|
|
|
self.imu_link = self.get_parameter('imu_link').get_parameter_value().string_value
|
|
|
|
|
print("IMU link:", self.imu_link)
|
|
|
|
|
|
|
|
|
|
self.declare_parameter('Prefix', "") # 话题前缀 (Topic prefix)
|
|
|
|
|
self.Prefix = self.get_parameter('Prefix').get_parameter_value().string_value
|
|
|
|
|
print("Prefix:", self.Prefix)
|
|
|
|
|
|
|
|
|
|
self.declare_parameter('xlinear_limit', 1.0) # X轴线速度限制 (X-axis linear velocity limit)
|
|
|
|
|
self.xlinear_limit = self.get_parameter('xlinear_limit').get_parameter_value().double_value
|
|
|
|
|
print("X linear limit:", self.xlinear_limit)
|
|
|
|
|
|
|
|
|
|
self.declare_parameter('ylinear_limit', 1.0) # Y轴线速度限制 (Y-axis linear velocity limit)
|
|
|
|
|
self.ylinear_limit = self.get_parameter('ylinear_limit').get_parameter_value().double_value
|
|
|
|
|
print("Y linear limit:", self.ylinear_limit)
|
|
|
|
|
|
|
|
|
|
self.declare_parameter('angular_limit', 5.0) # 角速度限制 (Angular velocity limit)
|
|
|
|
|
self.angular_limit = self.get_parameter('angular_limit').get_parameter_value().double_value
|
|
|
|
|
print("Angular limit:", self.angular_limit)
|
|
|
|
|
|
|
|
|
|
# 创建订阅者 (Create subscribers)
|
|
|
|
|
self.sub_cmd_vel = self.create_subscription(Twist, "cmd_vel", self.cmd_vel_callback, 1) # 运动控制订阅 (Motion control subscription)
|
|
|
|
|
self.sub_RGBLight = self.create_subscription(Int32, "RGBLight", self.RGBLightcallback, 100) # RGB灯光控制订阅 (RGB light control subscription)
|
|
|
|
|
self.sub_BUzzer = self.create_subscription(Bool, "Buzzer", self.Buzzercallback, 100) # 蜂鸣器控制订阅 (Buzzer control subscription)
|
|
|
|
|
|
|
|
|
|
# 创建发布者 (Create publishers)
|
|
|
|
|
self.EdiPublisher = self.create_publisher(Float32, "edition", 100) # 版本信息发布 (Edition information publisher)
|
|
|
|
|
self.volPublisher = self.create_publisher(Float32, "voltage", 100) # 电池电压发布 (Battery voltage publisher)
|
|
|
|
|
self.staPublisher = self.create_publisher(JointState, "joint_states", 100) # 关节状态发布 (Joint state publisher)
|
|
|
|
|
self.velPublisher = self.create_publisher(Twist, "vel_raw", 50) # 原始速度发布 (Raw velocity publisher)
|
|
|
|
|
self.imuPublisher = self.create_publisher(Imu, "/imu/data_raw", 100) # IMU数据发布 (IMU data publisher)
|
|
|
|
|
self.magPublisher = self.create_publisher(MagneticField, "/imu/mag", 100) # 磁力计数据发布 (Magnetometer data publisher)
|
|
|
|
|
|
|
|
|
|
# 创建定时器 (Create timer)
|
|
|
|
|
self.timer = self.create_timer(0.1, self.pub_data) # 10Hz数据发布定时器 (10Hz data publishing timer)
|
|
|
|
|
|
|
|
|
|
# 创建和初始化变量 (Create and initialize variables)
|
|
|
|
|
self.edition = Float32()
|
|
|
|
|
self.edition.data = 1.0
|
|
|
|
|
|
|
|
|
|
# 创建接收线程 (Create receive thread)
|
|
|
|
|
self.car.create_receive_threading()
|
|
|
|
|
|
|
|
|
|
print("X3 robot driver initialized successfully")
|
|
|
|
|
|
|
|
|
|
def cmd_vel_callback(self, msg):
|
|
|
|
|
"""
|
|
|
|
|
运动控制回调函数
|
|
|
|
|
Motion control callback function
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
msg (Twist): 运动控制消息,包含线速度和角速度 (Motion control message with linear and angular velocities)
|
|
|
|
|
|
|
|
|
|
功能 (Functions):
|
|
|
|
|
- 接收运动控制命令
|
|
|
|
|
- 解析线速度和角速度
|
|
|
|
|
- 下发控制指令到底层
|
|
|
|
|
"""
|
|
|
|
|
if not isinstance(msg, Twist): return
|
|
|
|
|
|
|
|
|
|
# 提取速度信息 (Extract velocity information)
|
|
|
|
|
vx = msg.linear.x * 1.0 # X轴线速度 (X-axis linear velocity)
|
|
|
|
|
vy = msg.linear.y * 1.0 # Y轴线速度 (Y-axis linear velocity)
|
|
|
|
|
angular = msg.angular.z * 1.0 # 角速度 (Angular velocity)
|
|
|
|
|
|
|
|
|
|
# 下发运动控制指令 (Issue motion control command)
|
|
|
|
|
self.car.set_car_motion(vx, vy, angular)
|
|
|
|
|
|
|
|
|
|
# 调试输出 (Debug output)
|
|
|
|
|
# print("cmd_vx: ", vx)
|
|
|
|
|
# print("cmd_vy: ", vy)
|
|
|
|
|
# print("cmd_angular: ", angular)
|
|
|
|
|
|
|
|
|
|
def RGBLightcallback(self, msg):
|
|
|
|
|
"""
|
|
|
|
|
RGB灯光控制回调函数
|
|
|
|
|
RGB light control callback function
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
msg (Int32): RGB灯光控制消息 (RGB light control message)
|
|
|
|
|
|
|
|
|
|
功能 (Functions):
|
|
|
|
|
- 接收RGB灯光控制指令
|
|
|
|
|
- 控制机器人RGB灯光效果
|
|
|
|
|
"""
|
|
|
|
|
if not isinstance(msg, Int32): return
|
|
|
|
|
|
|
|
|
|
# 设置RGB灯光效果 (Set RGB light effect)
|
|
|
|
|
# 重复3次确保指令执行 (Repeat 3 times to ensure command execution)
|
|
|
|
|
for i in range(3):
|
|
|
|
|
self.car.set_colorful_effect(msg.data, 6, parm=1)
|
|
|
|
|
|
|
|
|
|
def Buzzercallback(self, msg):
|
|
|
|
|
"""
|
|
|
|
|
蜂鸣器控制回调函数
|
|
|
|
|
Buzzer control callback function
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
msg (Bool): 蜂鸣器控制消息 (Buzzer control message)
|
|
|
|
|
|
|
|
|
|
功能 (Functions):
|
|
|
|
|
- 接收蜂鸣器控制指令
|
|
|
|
|
- 控制机器人蜂鸣器开关
|
|
|
|
|
"""
|
|
|
|
|
if not isinstance(msg, Bool): return
|
|
|
|
|
|
|
|
|
|
if msg.data:
|
|
|
|
|
# 开启蜂鸣器 (Turn on buzzer)
|
|
|
|
|
for i in range(3):
|
|
|
|
|
self.car.set_beep(1)
|
|
|
|
|
else:
|
|
|
|
|
# 关闭蜂鸣器 (Turn off buzzer)
|
|
|
|
|
for i in range(3):
|
|
|
|
|
self.car.set_beep(0)
|
|
|
|
|
|
|
|
|
|
def pub_data(self):
|
|
|
|
|
"""
|
|
|
|
|
数据发布函数
|
|
|
|
|
Data publishing function
|
|
|
|
|
|
|
|
|
|
功能 (Functions):
|
|
|
|
|
- 采集传感器数据
|
|
|
|
|
- 发布IMU数据
|
|
|
|
|
- 发布磁力计数据
|
|
|
|
|
- 发布电池电压
|
|
|
|
|
- 发布版本信息
|
|
|
|
|
- 发布关节状态
|
|
|
|
|
- 发布原始速度
|
|
|
|
|
"""
|
|
|
|
|
# 获取当前时间戳 (Get current timestamp)
|
|
|
|
|
time_stamp = Clock().now()
|
|
|
|
|
|
|
|
|
|
# 初始化消息结构 (Initialize message structures)
|
|
|
|
|
imu = Imu()
|
|
|
|
|
twist = Twist()
|
|
|
|
|
battery = Float32()
|
|
|
|
|
edition = Float32()
|
|
|
|
|
mag = MagneticField()
|
|
|
|
|
state = JointState()
|
|
|
|
|
|
|
|
|
|
# 设置关节状态消息头 (Set joint state message header)
|
|
|
|
|
state.header.stamp = time_stamp.to_msg()
|
|
|
|
|
state.header.frame_id = "joint_states"
|
|
|
|
|
|
|
|
|
|
# 设置关节名称 (Set joint names)
|
|
|
|
|
if len(self.Prefix) == 0:
|
|
|
|
|
state.name = ["back_right_joint", "back_left_joint", "front_left_steer_joint", "front_left_wheel_joint",
|
|
|
|
|
"front_right_steer_joint", "front_right_wheel_joint"]
|
|
|
|
|
else:
|
|
|
|
|
state.name = [self.Prefix + "back_right_joint", self.Prefix + "back_left_joint",
|
|
|
|
|
self.Prefix + "front_left_steer_joint", self.Prefix + "front_left_wheel_joint",
|
|
|
|
|
self.Prefix + "front_right_steer_joint", self.Prefix + "front_right_wheel_joint"]
|
|
|
|
|
|
|
|
|
|
# 获取传感器数据 (Get sensor data)
|
|
|
|
|
edition.data = self.car.get_version() * 1.0 # 版本信息 (Version information)
|
|
|
|
|
battery.data = self.car.get_battery_voltage() * 1.0 # 电池电压 (Battery voltage)
|
|
|
|
|
|
|
|
|
|
# 获取IMU数据 (Get IMU data)
|
|
|
|
|
ax, ay, az = self.car.get_accelerometer_data() # 加速度计数据 (Accelerometer data)
|
|
|
|
|
gx, gy, gz = self.car.get_gyroscope_data() # 陀螺仪数据 (Gyroscope data)
|
|
|
|
|
mx, my, mz = self.car.get_magnetometer_data() # 磁力计数据 (Magnetometer data)
|
|
|
|
|
|
|
|
|
|
# 转换磁力计数据 (Convert magnetometer data)
|
|
|
|
|
mx = mx * 1.0
|
|
|
|
|
my = my * 1.0
|
|
|
|
|
mz = mz * 1.0
|
|
|
|
|
|
|
|
|
|
# 获取运动数据 (Get motion data)
|
|
|
|
|
vx, vy, angular = self.car.get_motion_data()
|
|
|
|
|
|
|
|
|
|
# 调试输出 (Debug output)
|
|
|
|
|
# print("vx: ", vx)
|
|
|
|
|
# print("vy: ", vy)
|
|
|
|
|
# print("angular: ", angular)
|
|
|
|
|
|
|
|
|
|
# 设置IMU消息 (Set IMU message)
|
|
|
|
|
imu.header.stamp = time_stamp.to_msg()
|
|
|
|
|
imu.header.frame_id = self.imu_link
|
|
|
|
|
imu.linear_acceleration.x = ax * 1.0 # X轴加速度 (X-axis acceleration)
|
|
|
|
|
imu.linear_acceleration.y = ay * 1.0 # Y轴加速度 (Y-axis acceleration)
|
|
|
|
|
imu.linear_acceleration.z = az * 1.0 # Z轴加速度 (Z-axis acceleration)
|
|
|
|
|
imu.angular_velocity.x = gx * 1.0 # X轴角速度 (X-axis angular velocity)
|
|
|
|
|
imu.angular_velocity.y = gy * 1.0 # Y轴角速度 (Y-axis angular velocity)
|
|
|
|
|
imu.angular_velocity.z = gz * 1.0 # Z轴角速度 (Z-axis angular velocity)
|
|
|
|
|
|
|
|
|
|
# 设置磁力计消息 (Set magnetometer message)
|
|
|
|
|
mag.header.stamp = time_stamp.to_msg()
|
|
|
|
|
mag.header.frame_id = self.imu_link
|
|
|
|
|
mag.magnetic_field.x = mx * 1.0 # X轴磁场强度 (X-axis magnetic field)
|
|
|
|
|
mag.magnetic_field.y = my * 1.0 # Y轴磁场强度 (Y-axis magnetic field)
|
|
|
|
|
mag.magnetic_field.z = mz * 1.0 # Z轴磁场强度 (Z-axis magnetic field)
|
|
|
|
|
|
|
|
|
|
# 设置速度消息 (Set velocity message)
|
|
|
|
|
twist.linear.x = vx * 1.0 # X轴线速度 (X-axis linear velocity)
|
|
|
|
|
twist.linear.y = vy * 1.0 # Y轴线速度 (Y-axis linear velocity)
|
|
|
|
|
twist.angular.z = angular * 1.0 # 角速度 (Angular velocity)
|
|
|
|
|
|
|
|
|
|
# 发布所有消息 (Publish all messages)
|
|
|
|
|
self.velPublisher.publish(twist) # 发布速度信息 (Publish velocity information)
|
|
|
|
|
self.imuPublisher.publish(imu) # 发布IMU数据 (Publish IMU data)
|
|
|
|
|
self.magPublisher.publish(mag) # 发布磁力计数据 (Publish magnetometer data)
|
|
|
|
|
self.volPublisher.publish(battery) # 发布电池电压 (Publish battery voltage)
|
|
|
|
|
self.EdiPublisher.publish(edition) # 发布版本信息 (Publish edition information)
|
|
|
|
|
|
|
|
|
|
# 调试输出 (Debug output)
|
|
|
|
|
# print("ax: %.5f, ay: %.5f, az: %.5f" % (ax, ay, az))
|
|
|
|
|
# print("gx: %.5f, gy: %.5f, gz: %.5f" % (gx, gy, gz))
|
|
|
|
|
# print("mx: %.5f, my: %.5f, mz: %.5f" % (mx, my, mz))
|
|
|
|
|
# print("battery: {}".format(battery.data))
|
|
|
|
|
# print("vx: {}, vy: {}, angular: {}".format(twist.linear.x, twist.linear.y, twist.angular.z))
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
rclpy.init()
|
|
|
|
|
driver = yahboomcar_driver('driver_node')
|
|
|
|
|
rclpy.spin(driver)
|
|
|
|
|
"""
|
|
|
|
|
主函数
|
|
|
|
|
Main function
|
|
|
|
|
|
|
|
|
|
初始化ROS节点并启动X3机器人驱动
|
|
|
|
|
Initialize ROS node and start X3 robot driver
|
|
|
|
|
"""
|
|
|
|
|
rclpy.init()
|
|
|
|
|
driver = yahboomcar_driver('driver_node')
|
|
|
|
|
print("X3 robot driver node started")
|
|
|
|
|
rclpy.spin(driver)
|
|
|
|
|
|
|
|
|
|
'''if __name__ == '__main__':
|
|
|
|
|
main()'''
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|