亚博microros小车-原生ubuntu支持系列:1 键盘控制

背景:电脑配置不太行,我在ubuntu再运行vmware,里面运行亚博官方的虚拟机镜像ubuntu,系统很卡。基本上8G内存给打满了。还是想把亚博官方的代码迁移出来,之前售后就说除了官方镜像虚拟机,需要自己摸索迁移。

先从键盘控制入手吧。这个模块就是发消息,类似于小海龟那个,比小海龟还要简化下,只是命令多一些,相对独立,依赖少,适合上手练习。

一 准备工作

启动代理:

复制代码
docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4

可以参考之前的文章:亚博microROS 机器人配置与控制-CSDN博客

小车的配置:要与电脑IP保持一致,不是虚拟机的IP

还要关注一点:检查node

bash 复制代码
bohu@bohu-TM1701:~$ ros2 node list
/YB_Car_Node

如果没有,请检查确认虚拟机/电脑上.bashrc文件的ROS DOMAIN ID与microROS控制板上配置的一致才可以搜索到节点信息。初次通常需要在.bashrc文件加一行:

export ROS_DOMAIN_ID=20

运行后小车开启电源效果如下:

bash 复制代码
bohu@bohu-TM1701:~$ docker run -it --rm -v /dev:/dev -v /dev/shm:/dev/shm --privileged --net=host microros/micro-ros-agent:humble udp4 --port 8090 -v4
[1737378512.062782] info     | UDPv4AgentLinux.cpp | init                     | running...             | port: 8090
[1737378512.063437] info     | Root.cpp           | set_verbose_level        | logger setup           | verbose_level: 4
[1737378512.532474] info     | Root.cpp           | create_client            | create                 | client_key: 0x2BEF9112, session_id: 0x81
[1737378512.532669] info     | SessionManager.hpp | establish_session        | session established    | client_key: 0x2BEF9112, address: 192.168.0.107:39455
[1737378512.677740] info     | ProxyClient.cpp    | create_participant       | participant created    | client_key: 0x2BEF9112, participant_id: 0x000(1)
[1737378512.690384] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x2BEF9112, topic_id: 0x000(2), participant_id: 0x000(1)
[1737378512.697153] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x2BEF9112, publisher_id: 0x000(3), participant_id: 0x000(1)
[1737378512.705426] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x2BEF9112, datawriter_id: 0x000(5), publisher_id: 0x000(3)
[1737378512.714186] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x2BEF9112, topic_id: 0x001(2), participant_id: 0x000(1)
[1737378512.725294] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x2BEF9112, publisher_id: 0x001(3), participant_id: 0x000(1)
[1737378512.800394] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x2BEF9112, datawriter_id: 0x001(5), publisher_id: 0x001(3)
[1737378512.813041] info     | ProxyClient.cpp    | create_topic             | topic created          | client_key: 0x2BEF9112, topic_id: 0x002(2), participant_id: 0x000(1)
[1737378512.822137] info     | ProxyClient.cpp    | create_publisher         | publisher created      | client_key: 0x2BEF9112, publisher_id: 0x002(3), participant_id: 0x000(1)
[1737378512.833437] info     | ProxyClient.cpp    | create_datawriter        | datawriter created     | client_key: 0x2BEF9112, datawriter_id: 0x002(5), publisher_id: 0x002(3)

这是前提,否则没法控制小车

二 控制代码

在src/yahboomcar_ctrl/yahboomcar_ctrl/目录下新建文件yahboom_keyboard.py,

代码如下:

python 复制代码
#!/usr/bin/env python
# encoding: utf-8
#import public lib
from geometry_msgs.msg import Twist # 消息
import sys, select, termios, tty #tty 设置终端模式。sys 系统模块,select  监听输入,termios 保存和恢复

#import ros lib
import rclpy
from rclpy.node import Node

msg = """
Control Your SLAM-Bot!
---------------------------
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%
t/T : x and y speed switch
s/S : stop keyboard control
space key, k : force stop
anything else : stop smoothly

CTRL-C to quit
"""

moveBindings = {
    'i': (1, 0),
    'o': (1, -1),
    'j': (0, 1),
    'l': (0, -1),
    'u': (1, 1),
    ',': (-1, 0),
    '.': (-1, 1),
    'm': (-1, -1),
    'I': (1, 0),
    'O': (1, -1),
    'J': (0, 1),
    'L': (0, -1),
    'U': (1, 1),
    'M': (-1, -1),
}

speedBindings = {
    'Q': (1.1, 1.1),
    'Z': (.9, .9),
    'W': (1.1, 1),
    'X': (.9, 1),
    'E': (1, 1.1),
    'C': (1, .9),
    'q': (1.1, 1.1),
    'z': (.9, .9),
    'w': (1.1, 1),
    'x': (.9, 1),
    'e': (1, 1.1),
    'c': (1, .9),
}



class Yahboom_Keybord(Node):
	def __init__(self,name):#初始化
		super().__init__(name)
		self.pub = self.create_publisher(Twist,'cmd_vel',1000)
		self.declare_parameter("linear_speed_limit",1.0) #声明参数-线速度
		self.declare_parameter("angular_speed_limit",5.0) #声明参数-角速度
		self.linenar_speed_limit = self.get_parameter("linear_speed_limit").get_parameter_value().double_value
		self.angular_speed_limit = self.get_parameter("angular_speed_limit").get_parameter_value().double_value
		self.settings = termios.tcgetattr(sys.stdin)
	def getKey(self):#读取键盘
		tty.setraw(sys.stdin.fileno())#原始模式,不用回车读取
		rlist, _, _ = select.select([sys.stdin], [], [], 0.1)# 监听输入,超时时间0.1秒
		if rlist: key = sys.stdin.read(1) #读取输入
		else: key = '' #没有输入设置为空串
		termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.settings) #恢复终端属性
		return key
	def vels(self, speed, turn):#输出速度和朝向
		return "currently:\tspeed %s\tturn %s " % (speed,turn)		
	
def main():
	rclpy.init()
	yahboom_keyboard = Yahboom_Keybord("yahboom_keyboard_ctrl")
	xspeed_switch = True
	(speed, turn) = (0.2, 1.0)
	(x, th) = (0, 0)
	status = 0
	stop = False
	count = 0
	twist = Twist()
	try:
		print(msg)
		print(yahboom_keyboard.vels(speed, turn))
		while (1):
			key = yahboom_keyboard.getKey()
			if key=="t" or key == "T": xspeed_switch = not xspeed_switch
			elif key == "s" or key == "S":
				print ("stop keyboard control: {}".format(not stop))
				stop = not stop
			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
				if speed > yahboom_keyboard.linenar_speed_limit: 
					speed = yahboom_keyboard.linenar_speed_limit
					print("Linear speed limit reached!")
				if turn > yahboom_keyboard.angular_speed_limit: 
					turn = yahboom_keyboard.angular_speed_limit
					print("Angular speed limit reached!")
				print(yahboom_keyboard.vels(speed, turn))
				if (status == 14): print(msg)
				status = (status + 1) % 15
			elif key == ' ': (x, th) = (0, 0)
			else:
				count = count + 1
				if count > 4: (x, th) = (0, 0)
				if (key == '\x03'): break
			if xspeed_switch: twist.linear.x = speed * x
			else: twist.linear.y = speed * x
			twist.angular.z = turn * th
			if not stop: yahboom_keyboard.pub.publish(twist) #发话题消息
			if stop:yahboom_keyboard.pub.publish(Twist())
	except Exception as e: print(e)
	finally: yahboom_keyboard.pub.publish(Twist())
	termios.tcsetattr(sys.stdin, termios.TCSADRAIN, yahboom_keyboard.settings) #恢复终端属性
	yahboom_keyboard.destroy_node()
	rclpy.shutdown()

代码我加了注释,从依赖上看,就是依赖了ros2基础的话题消息,剩下就是读取键盘的getKey()。

退出标识:\x03 就是ctrl+C 组合。

处理逻辑就是根据根据键盘输入调用话题发布。

三 测试:

重新构建下,再次运行节点

ros2 run yahboomcar_ctrl yahboom_keyboard

补充下相关信息

rqt看node:

bash 复制代码
bohu@bohu-TM1701:~$ ros2 node info /YB_Car_Node 
/YB_Car_Node
  Subscribers:
    /beep: std_msgs/msg/UInt16
    /cmd_vel: geometry_msgs/msg/Twist
    /servo_s1: std_msgs/msg/Int32
    /servo_s2: std_msgs/msg/Int32
  Publishers:
    /battery: std_msgs/msg/UInt16
    /imu: sensor_msgs/msg/Imu
    /odom_raw: nav_msgs/msg/Odometry
    /scan: sensor_msgs/msg/LaserScan
  Service Servers:

  Service Clients:

  Action Servers:

  Action Clients:

从节点信息来看,/YB_Car_Node

订阅了话题:包含刚才的cmd_vel,用于接受指令。消息接口:

geometry_msgs/msg/Twist

发布的话题:battery 电池、imu 惯性测量数据,odom:里程计数据、scan:激光雷达的数据。

控制话题具体信息


linear:

x: 0.26620000000000005

y: 0.0

z: 0.0

angular:

x: 0.0

y: 0.0

z: 0.0


真的很感谢之前小鱼老师那本《ros2机器人开发》那本书,要是没有这本书作为入门指导,直接看亚博的源码会很吃力。这是第一步,期待后面能逐步学习完亚博的完整功能,把小车玩起来。

相关推荐
Joker Zxc6 分钟前
【Django】多个APP设置独立的URL
python·django·django的url
圣道寺15 分钟前
审计文件标识作为水印打印在pdf页面边角
java·前端·python·pdf·学习方法
荣--22 分钟前
Windows 快速启动器
python·alias
Edward-tan35 分钟前
【玩转全栈】----Django模板的继承
后端·python·django
安替-AnTi41 分钟前
淘宝关键词页面爬取&绘图进行数据分析
python·信息可视化·关键词·爬取·tb
Q_27437851091 小时前
django应急物资管理系统
后端·python·django
程序员一诺1 小时前
【Python使用】嘿马头条项目从到完整开发教程第10篇:APScheduler定时任务,1. 什么是RPC【附代码文档】
后端·python
喜-喜2 小时前
Python学习之旅:入门阶段(七)数据结构
数据结构·python·学习
C7211BA2 小时前
UMAP(Uniform Manifold Approximation and Projection)算法
python·算法·信息可视化
莲动渔舟2 小时前
PyTest自学 - pytest的各种执行方式
开发语言·python·pytest