1 小车硬件结构
1 中控设备
上方的单片机用于控制电机运动,搭载wifi模块和电量显示屏。下方为树莓派,安装了ROS系统和Ubuntu系统,用于整个小车控制。显示屏和树莓派相连
2 传感器系统
激光雷达及转换器。激光雷达和转换器相连,再由转换器连接树莓派以控制激光雷达
摄像头系统,搭载深度摄像头和彩色摄像头
4 遥控系统
使用PS2遥控器,车身搭载PS2接收端
5
12V电池盒。小车只有在电压大于10V时才能工作
2 键盘控制移动
键盘控制节点:
roslaunch wheeltec_robot_rc keyboard_teleop.launch
控制说明:
U I O
J L
M .
控制各方向
k键和空格键为急停,立刻停止电机,按其他键为缓慢减速停止
Q/Z 增加/减少10%线速度和角速度
W/X 增加/减少10%线速度
E/C 增加/减少10%角速度
B 开关全向模式
键盘控制节点(turtlebot_teleop_key)
1
Omni = 0 #全向移动模式
#键值对应移动/转向方向
moveBindings = {
'i':( 1, 0),
'o':( 1,-1),
'j':( 0, 1),
'l':( 0,-1),
'u':( 1, 1),
',':(-1, 0),
'.':(-1, 1),
'm':(-1,-1),
}
#键值对应速度增量
speedBindings={
'q':(1.1,1.1),
'z':(0.9,0.9),
'w':(1.1,1),
'x':(0.9,1),
'e':(1, 1.1),
'c':(1, 0.9),
}
speed = 0.2 #默认移动速度 m/s
turn = 0.5 #默认转向速度 rad/s
移动键和速度控制键对应的值。最终速度为 (speed X 方向)和(turn X 方向)。在修改速度时为(speed X 修改幅度)和(turn X 修改幅度)
2
settings = termios.tcgetattr(sys.stdin) #获取键值初始化,读取终端相关属性
rospy.init_node('turtlebot_teleop') #创建ROS节点
pub = rospy.Publisher('~cmd_vel', Twist, queue_size=5) #创建速度话题发布者,'~cmd_vel'='节点名/cmd_vel'
x = 0 #前进后退方向
th = 0 #转向/横向移动方向
count = 0 #键值不再范围计数
target_speed = 0 #前进后退目标速度
target_turn = 0 #转向目标速度
target_HorizonMove = 0 #横向移动目标速度
control_speed = 0 #前进后退实际控制速度
control_turn = 0 #转向实际控制速度
control_HorizonMove = 0 #横向移动实际控制速度
创建ros节点和Twist消息发布者pub。pub的消息被wheeltec_robot类订阅。wheeltec类会通过串口通信将速度控制指令发给下位机。
这里速度变化由于都是平滑变化。方向控制指令只会直接影响目标速度target_turn和target_speed。真实速度会渐进到目标速度(见下方代码)
3 读取控制键信息
while(1):
key = getKey() #获取键值
#切换是否为全向移动模式,全向轮/麦轮小车可以加入全向移动模式
if key=='b':
Omni=~Omni
if Omni:
print("Switch to OmniMode")
moveBindings['.']=[-1,-1]
moveBindings['m']=[-1, 1]
else:
print("Switch to CommonMode")
moveBindings['.']=[-1, 1]
moveBindings['m']=[-1,-1]
#判断键值是否在移动/转向方向键值内
if key in moveBindings.keys():
x = moveBindings[key][0]
th = moveBindings[key][1]
count = 0
#判断键值是否在速度增量键值内
elif key in speedBindings.keys():
speed = speed * speedBindings[key][0]
turn = turn * speedBindings[key][1]
count = 0
print(vels(speed,turn)) #速度发生变化,打印出来
#空键值/'k',相关变量置0
elif key == ' ' or key == 'k' :
x = 0
th = 0
control_speed = 0
control_turn = 0
HorizonMove = 0
#长期识别到不明键值,相关变量置0
else:
count = count + 1
if count > 4:
x = 0
th = 0
if (key == '\x03'):
break
这里可以看到一点。对于k和空格键按下一次即可急停,而对于按其他键停止需要按至少5次
4 根据速度方向和大小计算最终速度值
#根据速度与方向计算目标速度
target_speed = speed * x
target_turn = turn * th
target_HorizonMove = speed*th
#平滑控制,计算前进后退实际控制速度
if target_speed > control_speed:
control_speed = min( target_speed, control_speed + 0.1 )
elif target_speed < control_speed:
control_speed = max( target_speed, control_speed - 0.1 )
else:
control_speed = target_speed
#平滑控制,计算转向实际控制速度
if target_turn > control_turn:
control_turn = min( target_turn, control_turn + 0.5 )
elif target_turn < control_turn:
control_turn = max( target_turn, control_turn - 0.5 )
else:
control_turn = target_turn
#平滑控制,计算横向移动实际控制速度
if target_HorizonMove > control_HorizonMove:
control_HorizonMove = min( target_HorizonMove, control_HorizonMove + 0.1 )
elif target_HorizonMove < control_HorizonMove:
control_HorizonMove = max( target_HorizonMove, control_HorizonMove - 0.1 )
else:
control_HorizonMove = target_HorizonMove
这里可以看到方向键只会立刻改变target_speed和target_turn。而真实速度和方向control_speed和control_turn会在每一轮循环中向目标速度改变0.1,实现平滑变速
5 创建并发布话题
#根据是否全向移动模式,给速度话题变量赋值
if Omni==0:
twist.linear.x = control_speed; twist.linear.y = 0; twist.linear.z = 0
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = control_turn
else:
twist.linear.x = control_speed; twist.linear.y = control_HorizonMove; twist.linear.z = 0
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0
pub.publish(twist) #ROS发布速度话题
判断当前状态是否为全向运动而选择不同话题。消息类型使用了ROS标准定义的geometry_msgs.msg/Twist接口,其中包含值:
linear.x
linear.y
linear.z
angular.x
angular.y
angular.z
代表三轴线速度和角速度文章来源:https://www.toymoban.com/news/detail-485179.html
键盘控制节点完整代码:文章来源地址https://www.toymoban.com/news/detail-485179.html
import rospy
from geometry_msgs.msg import Twist
import sys, select, termios, tty
msg = """
Control Your Turtlebot!
---------------------------
Moving around:
u i o
j k l
m , .
q/z : increase/decrease max speeds by 10%
w/x : increase/decrease only linear speed by 10%
e/c : increase/decrease only angular speed by 10%
space key, k : force stop
anything else : stop smoothly
b : switch to OmniMode/CommonMode
CTRL-C to quit
"""
Omni = 0 #全向移动模式
#键值对应移动/转向方向
moveBindings = {
'i':( 1, 0),
'o':( 1,-1),
'j':( 0, 1),
'l':( 0,-1),
'u':( 1, 1),
',':(-1, 0),
'.':(-1, 1),
'm':(-1,-1),
}
#键值对应速度增量
speedBindings={
'q':(1.1,1.1),
'z':(0.9,0.9),
'w':(1.1,1),
'x':(0.9,1),
'e':(1, 1.1),
'c':(1, 0.9),
}
#获取键值函数
def getKey():
tty.setraw(sys.stdin.fileno())
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
if rlist:
key = sys.stdin.read(1)
else:
key = ''
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
return key
speed = 0.2 #默认移动速度 m/s
turn = 0.5 #默认转向速度 rad/s
#以字符串格式返回当前速度
def vels(speed,turn):
return "currently:\tspeed %s\tturn %s " % (speed,turn)
#主函数
if __name__=="__main__":
settings = termios.tcgetattr(sys.stdin) #获取键值初始化,读取终端相关属性
rospy.init_node('turtlebot_teleop') #创建ROS节点
pub = rospy.Publisher('~cmd_vel', Twist, queue_size=5) #创建速度话题发布者,'~cmd_vel'='节点名/cmd_vel'
x = 0 #前进后退方向
th = 0 #转向/横向移动方向
count = 0 #键值不再范围计数
target_speed = 0 #前进后退目标速度
target_turn = 0 #转向目标速度
target_HorizonMove = 0 #横向移动目标速度
control_speed = 0 #前进后退实际控制速度
control_turn = 0 #转向实际控制速度
control_HorizonMove = 0 #横向移动实际控制速度
try:
print(msg) #打印控制说明
print(vels(speed,turn)) #打印当前速度
while(1):
key = getKey() #获取键值
#切换是否为全向移动模式,全向轮/麦轮小车可以加入全向移动模式
if key=='b':
Omni=~Omni
if Omni:
print("Switch to OmniMode")
moveBindings['.']=[-1,-1]
moveBindings['m']=[-1, 1]
else:
print("Switch to CommonMode")
moveBindings['.']=[-1, 1]
moveBindings['m']=[-1,-1]
#判断键值是否在移动/转向方向键值内
if key in moveBindings.keys():
x = moveBindings[key][0]
th = moveBindings[key][1]
count = 0
#判断键值是否在速度增量键值内
elif key in speedBindings.keys():
speed = speed * speedBindings[key][0]
turn = turn * speedBindings[key][1]
count = 0
print(vels(speed,turn)) #速度发生变化,打印出来
#空键值/'k',相关变量置0
elif key == ' ' or key == 'k' :
x = 0
th = 0
control_speed = 0
control_turn = 0
HorizonMove = 0
#长期识别到不明键值,相关变量置0
else:
count = count + 1
if count > 4:
x = 0
th = 0
if (key == '\x03'):
break
#根据速度与方向计算目标速度
target_speed = speed * x
target_turn = turn * th
target_HorizonMove = speed*th
#平滑控制,计算前进后退实际控制速度
if target_speed > control_speed:
control_speed = min( target_speed, control_speed + 0.1 )
elif target_speed < control_speed:
control_speed = max( target_speed, control_speed - 0.1 )
else:
control_speed = target_speed
#平滑控制,计算转向实际控制速度
if target_turn > control_turn:
control_turn = min( target_turn, control_turn + 0.5 )
elif target_turn < control_turn:
control_turn = max( target_turn, control_turn - 0.5 )
else:
control_turn = target_turn
#平滑控制,计算横向移动实际控制速度
if target_HorizonMove > control_HorizonMove:
control_HorizonMove = min( target_HorizonMove, control_HorizonMove + 0.1 )
elif target_HorizonMove < control_HorizonMove:
control_HorizonMove = max( target_HorizonMove, control_HorizonMove - 0.1 )
else:
control_HorizonMove = target_HorizonMove
twist = Twist() #创建ROS速度话题变量
#根据是否全向移动模式,给速度话题变量赋值
if Omni==0:
twist.linear.x = control_speed; twist.linear.y = 0; twist.linear.z = 0
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = control_turn
else:
twist.linear.x = control_speed; twist.linear.y = control_HorizonMove; twist.linear.z = 0
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0
pub.publish(twist) #ROS发布速度话题
#运行出现问题则程序终止并打印相关错误信息
except Exception as e:
print(e)
#程序结束前发布速度为0的速度话题
finally:
twist = Twist()
twist.linear.x = 0; twist.linear.y = 0; twist.linear.z = 0
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0
pub.publish(twist)
#程序结束前设置终端相关属性
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
到了这里,关于ROS小车研究笔记1/31/2023 小车硬件结构及键盘移动控制节点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!