ROS2学习笔记(humble)

ROS2学习笔记(humble)

1、工作空间

工作空间包括
build
install
log(日志)
src(用户代码编写空间)
工作空间创建流程:

1.1、 创建工作目录:

mkdir -p TOWN_WS/src #创建TOWN_WS的工作目录,并且创建src的代码编写空间

1.2、创建功能包:

ros2 pkg create --build-type {cmake或ament_cmake或ament_python} --dependencies <依赖名字>
ros2 pkg create village_li --build-type ament_python --dependencies rclpy

1.3、编译功能包

注意:应该回到工作空间目录下执行colcon build命令
编译单个指定功能包colcon build --packages-select

2、节点

2.1面向过程创建方式

import rclpy
from rclpy.node import Node

def main(args=None):
   """
   编写ROS2节点的一般步骤
   1. 导入库文件
   2. 初始化客户端库
   3. 新建节点对象
   4. spin循环节点
   5. 关闭客户端库
   """
   rclpy.init(args=args) # 初始化rclpy
   node = Node("node_02")  # 新建一个节点
   ###################################
   ############节点执行的功能############
   node.get_logger().info("大家好,我是node_02.")
   ###############################################
   rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
   rclpy.shutdown() # 关闭rclpy

2.2面向对象创建方式

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node


class Node(Node):
   """
   创建一个Node02_class节点,并在初始化时输出一个话
   """
   def __init__(self,name):
       super().__init__(name)
       self.get_logger().info(f"大家好,我是{name}")


def main(args=None):
   rclpy.init(args=args) # 初始化rclpy
   node = Node("node_02_class")  # 新建一个节点
   rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
   rclpy.shutdown() # 关闭rclpy

2.3、添加节点到setup.py文件

节点名称 = 功能包.节点所在文件:main
"li4= village_li.li4:main",

2.4 、节点相关命令(后续继续补充)

列出所以正在运行节点
ros2 node list
运行节点
ros2 run <功能包名称> <节点名称>
查看节点信息
ros2 node info

2.5、rclpy相关函数的补充

rclpy.spin(node):循环节点,主要是循环(timer、话题)的回调函数,按ctrl+C退出循环
rclpy.spin_once(node):循环一次节点
node.destroy_node() # 销毁节点对象 :销毁指定节点

3、话题

3.1 topic相关的终端命令

ros2 topic list 列出当下正在运行的话题
ros2 topic echo /<话题名> 截获指定话题的内容
ros2 topic info /<话题名> 查看话题信息
ros2 topic pub /<话题名> std_masgs/msg/<消息类型> "{data: <对应数据>}" 发布数据

3.2话题发布

  1. 定义发布消息的功能
    主要调用Node类下的create_publisher(消息类型,话题名称,缓存长度)方法,例如:
    self.Pub_novel = self.create_publisher(String,"sey_girl",10) ###定义发送功能
    定义一个话题名称为“sey_girl"的话题,类型为String,缓存长度为10.
  2. 发布消息(一般需要循环发送)
    2.1 使用Node类下的create_timer(秒数,回调函数)创建一个定时器
    self.timer = self.create_timer(5,self.pub_mag)
    2.2 编写回调函数
    使用定义的发布消息的功能下的pubilsh(消息)
    消息类型为String,所以必须要使用String()接口传递参数
       def pub_mag(self):
       msg=String()
       msg.data = self.msg_crate()
       #self.get_logger().info(msg.data)
       self.Pub_novel.publish(msg)
    
  3. 使用终端命令发布消息

3.3 话题订阅

  1. 使用Node类下的create_subscription(消息类型,话题名称,回调函数,缓存长度) 方法定义订阅者功能。
    self.Sub_money=self.create_subscription(UInt32,"sey_girl_money",self.Sub_money_callback,10) ###定义接受消息
    
  2. 编写回调函数
    从形参msg.data中读取受到的数据
       def Sub_money_callback(self,msg):#回调函数的格式,形参为受到的数据
       self.account += msg.data
       self.get_logger().info(f"收到{msg.data}元,账户余额{self.account}元。")    
    

3.4 例子

li4和wang5对话的例子
li4.py如下:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String,UInt32
import time

class Node(Node):
   def __init__(self,name):
       super().__init__(name)
       self.get_logger().info(f"大家好,我是{name}") 
       self.account = 0
       self.Z = 0#章节号
       self.H = 0#章回号
       #########rclpy.spin()控制的线程,这里相当于开了两个线程    
       self.Sub_money = self.create_subscription(UInt32,"sey_girl_money",self.Sub_money_callback,10) ###定义接受消息
       self.Pub_novel = self.create_publisher(String,"sey_girl",10)                                  ###定义发送功能
       self.timer = self.create_timer(5,self.pub_mag)                                                ###定时发布消息
    
   

   def Sub_money_callback(self,msg):#回调函数的格式,形参为受到的数据
      self.account += msg.data
      self.get_logger().info(f"收到{msg.data}元,账户余额{self.account}元。")
   
   ########发送String类型的消息################
   def pub_mag(self):
      msg=String()
      msg.data = self.msg_crate()
      self.get_logger().info(msg.data)
      self.Pub_novel.publish(msg)
   
   ############实际上这里不用这样写,只是为了搭建一个格式##############
   def msg_crate(self):
      self.Z = self.Z + 1
      self.H = self.H + 1
      data = f'艳娘传奇:第{self.Z}章,第{self.H}回'
      return str(data)
   


def main(args=None):
   rclpy.init(args=args) # 初始化rclpy
   li4 = Node("li4")
   rclpy.spin(li4)
   li4.destroy_node() # 销毁节点对象  
   rclpy.shutdown() # 关闭rclpy   

wang5.py如下:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String,UInt32


class Node(Node):
   """
   创建一个Node02_class节点,并在初始化时输出一个话
   """
   def __init__(self,name):
       super().__init__(name)
       self.get_logger().info(f"大家好,我是{name}")

       self.money = 1
       self.Sub_Novel = self.create_subscription(String,"sey_girl",self.Sub_Novel_callback,10) ###定义接受消息

       self.Pub_money = self.create_publisher(UInt32,"sey_girl_money",10)                            ###定义发送功能
       self.timer = self.create_timer(5,self.pub_msg)                                                ###定时发布消息

   def Sub_Novel_callback(self,msg):
      self.get_logger().info(f"{msg.data}")

   def pub_msg(slef):
      msg=UInt32()
      msg.data = slef.msg_creat()
      slef.get_logger().info(f"我支付了:{msg.data}元")
      slef.Pub_money.publish(msg)
   
   def msg_creat(self):
      self.money += 1
      return int(self.money)



def main(args=None):
   rclpy.init(args=args) # 初始化rclpy
   wang5 = Node("wang5")  # 新建一个节点
   rclpy.spin(wang5) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
   wang5.destroy_node() # 销毁节点对象 
   rclpy.shutdown() # 关闭rclpy

你可能感兴趣的:(linux,python)