Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University
This document will introduce how to use RT-Thread and ROS to connect to realize a remote control car with a camera.
But in fact, the RT-Thread part of the code has been introduced in this document: RT-Thread connects to ROS to control the car . On this basis, we only need to modify the ROS code.
Here is a diagram of the entire system, so that if you want to make a car like this yourself, you can try it out:
We first create a node to monitor keyboard keys and publish the received keys to the topic /keys (communication between ROS nodes is achieved by publishing and subscribing to topics). We create a new file key_publisher.py in the telebot_ws/src/telebot/src directory
Now there is a node publishing our key messages. The next step is to convert the key messages into motion instructions for the robot, that is, publish them to /cmd_vel. We create a new file keys_to_twist_with_ramps.py in the telebot_ws/src/telebot/src directory:
#!/usr/bin/python
# 导入软件包
import rospy
import math
from std_msgs.msg import String
from geometry_msgs.msg import Twist
# 键盘和速度映设 w a s d
key_mapping = { 'w': [ 0, 1], 'x': [ 0, -1],
'a': [ -1, 0], 'd': [1, 0],
's': [ 0, 0] }
g_twist_pub = None
g_target_twist = None
g_last_twist = None
g_last_send_time = None
g_vel_scales = [0.1, 0.1] # default to very slow
g_vel_ramps = [1, 1] # units: meters per second^2
# 防止速度突变
def ramped_vel(v_prev, v_target, t_prev, t_now, ramp_rate):
# compute maximum velocity step
step = ramp_rate * (t_now - t_prev).to_sec()
sign = 1.0 if (v_target > v_prev) else -1.0
error = math.fabs(v_target - v_prev)
if error < step: # we can get there within this timestep. we're done.
return v_target
else:
return v_prev + sign * step # take a step towards the target
def ramped_twist(prev, target, t_prev, t_now, ramps):
tw = Twist()
tw.angular.z = ramped_vel(prev.angular.z, target.angular.z, t_prev,
t_now, ramps[0])
tw.linear.x = ramped_vel(prev.linear.x, target.linear.x, t_prev,
t_now, ramps[1])
return tw
# 发布控制指令到 /cmd_vel
def send_twist():
global g_last_twist_send_time, g_target_twist, g_last_twist,\
g_vel_scales, g_vel_ramps, g_twist_pub
t_now = rospy.Time.now()
g_last_twist = ramped_twist(g_last_twist, g_target_twist,
g_last_twist_send_time, t_now, g_vel_ramps)
g_last_twist_send_time = t_now
g_twist_pub.publish(g_last_twist)
# 订阅 /keys 的回调函数
def keys_cb(msg):
global g_target_twist, g_last_twist, g_vel_scales
if len(msg.data) == 0 or not key_mapping.has_key(msg.data[0]):
return # unknown key.
vels = key_mapping[msg.data[0]]
g_target_twist.angular.z = vels[0] * g_vel_scales[0]
g_target_twist.linear.x = vels[1] * g_vel_scales[1]
# 获取传递进来的速度加速度比例
def fetch_param(name, default):
if rospy.has_param(name):
return rospy.get_param(name)
else:
print "parameter [%s] not defined. Defaulting to %.3f" % (name, default)
return default
if __name__ == '__main__':
rospy.init_node('keys_to_twist')
g_last_twist_send_time = rospy.Time.now()
g_twist_pub = rospy.Publisher('cmd_vel', Twist, queue_size=1)
rospy.Subscriber('keys', String, keys_cb)
g_target_twist = Twist() # initializes to zero
g_last_twist = Twist()
g_vel_scales[0] = fetch_param('~angular_scale', 0.1)
g_vel_scales[1] = fetch_param('~linear_scale', 0.1)
g_vel_ramps[0] = fetch_param('~angular_accel', 1.0)
g_vel_ramps[1] = fetch_param('~linear_accel', 1.0)
rate = rospy.Rate(20)
while not rospy.is_shutdown():
send_twist()
rate.sleep()copymistakeCopy Success
Similarly, we add executable permissions to this file:
The parameters passed in above are the ratio of the speed and acceleration of the car we want, so we can see that there is a /cmd_vel topic that will output the expected car speed:
Before connecting to the camera of the car, there is one very important point. The previous operations were all performed on the computer. Next, we want to use our ARM development board as the ROS master node, so we need to set the environment variables and replace the following IP address with the actual IP address of the ARM board on the car :
In fact, the code for publishing camera messages is only about 30 lines. We create a new my_publisher.cpp in the telebot_ws/src/telebot_image/src directory.
Before compiling, you need to install the OpenCV development environment first , because we use the OpenCV library function to obtain the camera data, and then publish it using the ROS library function. This is the CMakeLists.txt in the telebot_ws/src/telebot_image directory
If you already have a car that can be controlled by ROS, you only need to write about 30 lines of code in Part 3 for image publishing. You can use the OpenCV library to obtain camera information and then publish it using the ROS library.
Of course, if you just want to see the car's camera on your computer, there are actually many other ways that don't even require writing code. The advantage of using ROS to publish image data is that we can process the acquired images, such as target detection, which will be further introduced in subsequent documents.