ROS2学习笔记(四)-- 用方向键控制小车行走

2023-05-16

        简介:在上一节的内容中,我们通过ROS2的话题发布功能将小车实时视频信息发布了出来,同时使用GUI工具进行查看,在这一节内容中,我们学习一下如何订阅话题并处理话题消息,具体实现的功能就是通过方向键控制小车行驶。


1、安装pynput

2、创建小车控制功能节点

3、修改duckiebot节点

1)配置文件

2)节点源码

4、编译并运行


1、安装pynput

        我们要通过键盘方向键控制小车行走,需要用python编码实现键盘事件监听,我这里使用了pynput库,默认系统时没有安装的,需要手动安装一下:

$ pip3 install pynput

安装后我们测试一下,源码如下:

from pynput import keyboard

def on_press(key):
    print('{0} pressed'.format(key))

def on_release(key):
    print('{0} released'.format(key))
    if key == keyboard.Key.esc:
        return False

with keyboard.Listener(on_press=on_press,on_release=on_release) as listener:
    listener.join()

        以上代码创建了一个阻塞式(with...as....)的键盘事件监听功能,监听了键盘所有按键的按下和释放事件,在程序中应用时,不能使用阻塞式编程,会影响程序其他线程的执行,可以换一个方式:

listener = keyboard.Listener(on_press=on_press,on_release=on_release)
listener.start()

2、创建小车控制功能节点

进入ROS2工作空间源码目录

$ cd ~/ros2_ws/src

创建小车控制功能包,包名control,编译类型选python,默认创建control_node节点,依赖rclpy、sensor_msgs、geometry_msgs

$ ros2 pkg create control --build-type ament_python --node-name control_node --dependencies rclpy sensor_msgs geometry_msgs

功能包目录结构如下图:

编辑源码文件control_node.py

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node

import cv2
import numpy as np
from pynput import keyboard #引入键盘监听功能库

from sensor_msgs.msg import Image 
from geometry_msgs.msg import TwistStamped
from cv_bridge import CvBridge

class ControlNode(Node):
    
    def __init__(self,name):
        super().__init__(name)
        #初始化控制消息,设置header.frame_id
        self.action = TwistStamped()
        self.action.header.frame_id = name
        #创建控制消息发布接口
        self.pub_action = self.create_publisher(TwistStamped, "control_node/action", 10)
        #创建图像消息接收接口(消息类型,话题名称,回调函数,消息队列长度)
        self.sub_img = self.create_subscription(Image, "duckiebot_node/image", self.cb_image, 10)
        #创建图像转换工具
        self.bridge = CvBridge()
        #创建键盘事件监听器,并启动
        self.listener = keyboard.Listener(on_press=self.on_press,on_release=self.on_release)
        self.listener.start()
    
    #图像处理回调函数
    def cb_image(self,imgmsg):
        #ROS图像消息转化为opencv格式,第二个参数指定图像颜色编码格式
        image = self.bridge.imgmsg_to_cv2(imgmsg, 'bgr8')
        #显示图像
        cv2.imshow("image", image)
        cv2.waitKey(1)       
    #键盘按键按下事件处理,按下方向键时设定线速度和角速度数据并发布
    def on_press(self, key):
        #判断是否是方向键,只处理方向键事件
        if key == keyboard.Key.up or key == keyboard.Key.down or key == keyboard.Key.left or key == keyboard.Key.right:
            if key == keyboard.Key.up:      #上:向前
                self.action.twist.linear.x = 0.44  #设置线速度
                self.action.twist.angular.x = 0.0  #设置角速度
            elif key == keyboard.Key.down:  #下:向后
                self.action.twist.linear.x = -0.44 #设置线速度
                self.action.twist.angular.x = 0.0  #设置角速度
            elif key == keyboard.Key.left:  #左:左转
                self.action.twist.linear.x = 0.2   #设置线速度
                self.action.twist.angular.x = 1.0  #设置角速度
            elif key == keyboard.Key.right: #右:右转
                self.action.twist.linear.x = 0.2   #设置线速度
                self.action.twist.angular.x = -1.0 #设置角速度
            #设置消息时间数据
            self.action.header.stamp = self.get_clock().now().to_msg()
            #发布消息
            self.pub_action.publish(self.action)
     #键盘按键松开事件处理,松开方向键时设定线速度和角速度为0并发布
    def on_release(self, key):
         #判断是否是方向键,只处理方向键事件
        if key == keyboard.Key.up or key == keyboard.Key.down or key == keyboard.Key.left or key == keyboard.Key.right:
            self.action.twist.linear.x = 0.0
            self.action.twist.angular.x = 0.0
            self.action.header.stamp = self.get_clock().now().to_msg()
            self.pub_action.publish(self.action)
    
def main(args=None):
    rclpy.init(args=args)
    node = ControlNode(name="control_node")
    rclpy.spin(node=node)
    rclpy.shutdown()

        实现代码完成后,可以先编译测试代码有没有错误,也可以等duckiebot节点修改完再编译测试,提前编译测试可以按以下步骤,运行时因为没有图像发布出来,不会显示图像,如需显示图像,新开一个终端,启动上一节的duckiebot节点。

返回工作空间

$ cd ~/ros2_ws
$ colcon build

或者单独编译

$ colcon build --packages-select control

设置环境变量

$ source install/setup.bash

启动节点

$ ros2 run control control_node

3、修改duckiebot节点

        上一节的duckiebot节点仅仅是发布了图像话题,小车动作是随机生成的,我们现在有了动作指令话题,就需要修改duckiebot节点,实现动作指令话题数据的接收和处理,需要修改内容有以下几点:

1)配置文件

        动作指令话题control_node/action发布的是geometry_msgs.msg的TwistStamped类型,duckiebot节点创建时没有设置依赖这种消息类型,需要手动添加:

2)节点源码

        节点源码duckiebot_node.py中需要添加几何数据消息类型的引入,control_node/action话题的订阅以及消息处理,另外为了方便消息传递,需要定义一个action数据,详见下文源码注释:

#!/usr/bin/env python3

import rclpy
from rclpy.node import Node

import gym
from pyglet.window import key
from gym_duckietown.envs import DuckietownEnv

import cv2
import numpy as np

from sensor_msgs.msg import Image  #发布图像使用Image消息类型
from geometry_msgs.msg import TwistStamped #控制消息类型
from cv_bridge import CvBridge #opencv和ros图像数据转换工具
 
class DuckiebotNode(Node):
 
    def __init__(self, name):
        super().__init__(name)
        self.env = DuckietownEnv(seed=1,map_name="udem1",draw_curve=False,draw_bbox=False,domain_rand=False,frame_skip=1,distortion=False,camera_rand=False,dynamics_rand=False)
        self.env.reset()
        #定义图像发布接口
        self.pub_img = self.create_publisher(Image,"duckiebot_node/image",10)
        self.timer = self.create_timer(0.05, self.timer_callback)
        #创建图像转换工具
        self.bridge = CvBridge()
        #定义全局动作变量,默认线速度和角速度都是0,车辆停止
        self.action = np.array([0.0,0.0])
        #订阅控制指令话题
        self.sub_action = self.create_subscription(TwistStamped, "control_node/action", self.cb_action, 10)
    
    def timer_callback(self):
        #这里不再生成随机动作指令,直接使用全局动作变量
        obs, reward, done, info = self.env.step(self.action)
        #发布图像数据,obs是rgb编码,转化时指定编码,解码时就有据可查
        self.pub_img.publish(self.bridge.cv2_to_imgmsg(obs, 'rgb8'))
        if done:
            self.env.reset()
    #控制指令处理函数
    def cb_action(self, msg):
        v = msg.twist.linear.x       #线速度
        omega = msg.twist.angular.x  #角速度
        self.action[0] = v
        self.action[1] = omega
 
def main(args=None):
    rclpy.init(args=args)
    node = DuckiebotNode(name="duckiebot_node")
    rclpy.spin(node=node)
    rclpy.shutdown()

4、编译并运行

返回工作空间

$ cd ~/ros2_ws

编译所有节点

$ colcon build

设置环境变量

$ source install/setup.bash

启动duckiebot节点

$ ros2 run duckiebot duckiebot_node

新建终端启动control节点

$ cd ~/ros2_ws
$ source install/setup.bash
$ ros2 run control control_node

启动后可以看到实时图像,通过方向键可以控制小车移动。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS2学习笔记(四)-- 用方向键控制小车行走 的相关文章

  • 快速排序算法

    快速排序 xff1a 代码 xff1a lt php 快速排序算法 1 在数组中找一个元素作为key 一般取数组第一个元素作为key 2 i 61 0 j 61 数组长度 1 3 j 当 arr j lt key arr i 与arr j
  • 利用Apache mod_expires 与 mod_headers 实现文件缓存及mod_deflate压缩输出

    1 使用mod deflate module 压缩输出 启动gzip 开启mod deflate sudo a2enmod deflate sudo etc init d apache2 restart 在httpd conf中添加 lt
  • HTML5 history API 介绍

    HTML5 history API介绍 history是个全局变量 xff0c 即window history 属性和方法如下 xff1a length xff1a 历史堆栈中的记录数 back xff1a 返回上一页 foward xff
  • 冒泡,二分法插入,快速排序算法

    1 冒泡排序算法 过程 xff1a 1 遍历整个数组 xff0c 每两两相邻的元素进行比较 xff0c 如 a i gt a i 43 1 则互换位置 xff0c 每次比较消除一个逆序 2 每一次循环后 xff0c 下次再需要循环的次数减少
  • PHP缩小png图片,保留透明色方法

    将图片缩成合适的尺寸 xff0c jpg图片缩小比较容易 xff0c png图片如果带了透明色 xff0c 按jpg方式来缩小 xff0c 会造成透明色丢失 保存透明色主要利用gd库的两个方法 xff1a imagecolorallocat
  • Ubuntu的常用快捷键

    Ubuntu Gnome的桌面技巧 xff1a 61 61 61 键盘类 61 61 61 1 先同时按住 Alt 43 Ctrl 键 xff0c 再按键盘上的左 右光标 键 可以切换工作区 2 web时按 键 等于 查找功能 桌面或者目录
  • 无人驾驶虚拟仿真(四)--通过ROS系统控制小车行走

    简介 xff1a 实现键盘控制虚拟仿真小车移动 xff0c w s a d 空格 xff0c 对应向前 向后 向左 向右 急停切换功能 xff0c q键退出 1 创建key control节点 进入工作空间源码目录 xff1a cd myr
  • error while loading shared libraries的解決方法

    error while loading shared libraries的解決方法 运行程式時 xff0c 如遇到像下列這種錯誤 xff1a tests error while loading shared libraries xxx so
  • imagemagick安装方法

    1 下载ImageMagick http www imagemagick org download 下载 ImageMagick 6 8 5 10 tar gz xff0c 下载完毕后开始进行安装 cd Downloads tar xzvf
  • ubuntu中安装apache ab命令进行简单压力测试

    1 安裝ab命令 sudo apt get install apache2 utils 2 ab命令参数说明 Usage ab options http s hostname port path Options are 总的请求数 n re
  • 如何查看当前Apache的连接数

    查看了连接数和当前的连接数 netstat ant grep ip 80 wc l netstat ant grep ip 80 grep EST wc l 查看IP访问次数 netstat nat grep 34 80 34 awk 39
  • php 获取页面中的指定内容类

    功能 xff1a 1 获取内容中的url xff0c email xff0c image 2 替换内容中的url xff0c email xff0c image url xff1a lt a href 61 34 url 34 gt xxx
  • memcached启动参数

    memcached启动参数 p 指定端口号 xff08 默认11211 xff09 U lt num gt UDP监听端口 默认 11211 0 时关闭 s lt file gt 用于监听的UNIX套接字路径 xff08 禁用网络支持 xf
  • mysql常用方法

    1 CONCAT str1 str2 mysql gt SELECT CONCAT 39 My 39 39 S 39 39 QL 39 gt 39 MySQL 39 mysql gt SELECT CONCAT 39 My 39 NULL
  • shell 监控网站是否异常的脚本

    shell 监控网站是否异常的脚本 xff0c 如有异常自动发电邮通知管理员 流程 xff1a 1 检查网站返回的http code 是否等于200 xff0c 如不是200视为异常 2 检查网站的访问时间 xff0c 超过MAXLOADT
  • 文件转base64输出

    Data URI scheme是在RFC2397中定义的 xff0c 目的是将一些小的数据 xff0c 直接嵌入到网页中 xff0c 从而不用再从外部文件载入 优点 xff1a 减少http连接数 缺点 xff1a 这种格式的文件不会被浏览
  • php 支持断点续传的文件下载类

    php 支持断点续传 xff0c 主要依靠HTTP协议中 header HTTP RANGE实现 HTTP断点续传原理 Http头 Range Content Range HTTP头中一般断点下载时才用到Range和Content Rang
  • 基于Linkit 7697的红绿灯控制系统

    1 硬件准备 LinkIt 7697 1 xff0c 继电器模块 1 xff0c 面包板 1 xff0c RGB LED灯 1 xff08 共阳极 xff0c 工作电流20mA xff0c 红灯压降2 2 2V xff0c 绿灯蓝灯压降3
  • shell 记录apache status并自动更新到数据库

    1 获取apache status monitor log sh bin bash 连接数 site connects 61 netstat ant grep ip 80 wc l 当前连接数 site cur connects 61 ne
  • php 缩略图生成类,支持imagemagick及gd库两种处理

    功能 1 按比例缩小 放大 2 填充背景色 3 按区域裁剪 4 添加水印 包括水印的位置 透明度等 使用imagemagick GD库实现 imagemagick地址 www imagemagick org 需要安装imagemagick

随机推荐