学校ROS培训项目记录

news2024/11/28 0:57:46

项目内容:

  1. 在linux上安装ROS(可以使用虚拟机)
  2. 编写ROS程序,实现话题的订阅和发布
  3. 基于松灵小车硬件,显示雷达数据、图像数据
  4. 移动松灵小车,绘制小车的运动轨迹

实现过程记录

1.ubuntu22.04上安装ros2

ubuntu22.04 安装ros操作系统(但这个方法在执行的時候出錯)
官方网站讲解手动安装(这个也是一直不出现opt/ros文件夹)

于是重新创建了一个ubuntu,成功了。。。。我真的不理解。FINE ubuntu22.04安装ROS2 详细教程

2.ros官方说明文档

ros1的文档
ros2的英文文档
ros2的中文文档 by鱼香ros

3.ros教学

动手学ROS2

4.ROS2节点相关CLI

  • ros2 run <package_name> <executable_name>:运行可执行文件。eg:要运行turtlesim,请打开一个新终端,然后输入以下命令ros2 run turtlesim turtlesim_node

  • ros2 node list查找正在运行的节点。

  • ros2 node info <node_name> :与该节点交互的订阅者、发布者、服务和动作 (ROS图连接) 的列表。

  • eg:ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle重新映射到my_turtle节点上

5.ROS2中的工作空间

一个工作空间里面有若干功能包,一个功能包有若干个节点。这个工作空间里面有一个src目录:

mkdir -p ~/code/ros/turtle_ws/src
cd ~/code/ros/turtle_ws/dev_ws/src

6.功能包

功能包的两种获取方式:

  • 安装获取:sudo apt install ros-<version>-package_name。eg:在我的ubuntu上为:sudo apt install ros-humble-turtlesim
  • 手动编译:下载源码然后进行编译生成相关文件。

功能包相关指令:
-ros2 create <package_name> --build-type {cmake,ament_cmake,ament_pythob选一个编译类型} --dependencies <依赖名字>:创建功能包 。
-ros2 pkg executables [功能包]:列出所有功能包或者某个功能包的可执行文件。
-res2 pkg list:列出所有的包。
-ros2 pkg prefix <package_name>:列出某个功能包的前缀。

  • ros pkg xml <package_name>:列出包的清单描述文件。

7.Colcon

功能包的构建工具,编译代码。

  • 安装:sudo apt-get install python3-colcon-common-extensions在这里插入图片描述

8.克隆功能包并使用colcon编译

  • 创建工作空间:mkdir -p turtle_ws/src cd turtle_ws/src
  • 下载源码功能包到工作空间的src文件夹下:sudo git clone https://github.com/ros2/examples.git src/examples -b humble
  • 进入工作空间上一级编译:cd ..sudo colcon build
  • source空间:echo "source ~/Documents/code/turtle_ws/install/setup.bash" >> ~/.bashrc~/.bashrc
  • 进入turtle_ws工作空间,启动订阅者者:ros2 run examples_rclcpp_minimal_subscriber subscriber_member_function
  • 启动发布者:ros2 run examples_rclcpp_minimal_publisher publisher_member_function
  • 查看节点数量:ros2 node list
    在这里插入图片描述

9.面向过程POP编写一个python节点

  • 创建工作空间,并进入。在工作空间中执行code ./打开vscode进行代码编写。
  • 创建一个功能包:ros2 pkg create village_li --build-type ament_python --dependencies rclpy如果在创建中,出现如下报错,请将src目录的权限改为可写sudo chmod 777 src
    在这里插入图片描述
  • 创建节点文件:在__init__.py同级别目录下创建一个叫做li4_pop.py的文件
  • 编写节点代码:
import rclpy
from rclpy.node import Node

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

rclpy是什么库?看看GPT如何回答:在这里插入图片描述

  • 接着修改setup.py,增加一句话,告诉ros2村庄来了一位新村民李四,要找这位村民去village_li.li4_pop:main路径下寻找:
 entry_points={
        'console_scripts': [
            "li4_pop_node = village_li.li4_pop:main"
        ],
    },
  • 编译运行节点:打开vscode终端,进入town_ws。sudo colcon buildsource install/setup.bashros2 run village_li li4_pop_noderos2 node list
    你的每一次修改之后激动重新执行上面这项的几个指令。

9.面向对象OOP编写一个python节点

  • 创建节点文件:在__init__.py同级别目录下创建一个叫做li4_oop.py的文件
  • 编写节点代码:
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node


class WriterNode(Node):
    """
    创建一个作家节点,并在初始化时输出一个话
    """
    def __init__(self,name):
        super().__init__(name)
        self.get_logger().info("大家好,我是%s,我是一名作家!" % name)


def main(args=None):
    """
    ros2运行该节点的入口函数
    1. 导入库文件
    2. 初始化客户端库
    3. 新建节点
    4. spin循环节点
    5. 关闭客户端库
    """
    rclpy.init(args=args) # 初始化rclpy
    node = WriterNode("li4")  # 新建一个节点
    rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
    rclpy.shutdown() # 关闭rclpy

  • 接着修改setup.py,增加一句话,告诉ros2村庄来了一位新村民李四,要找这位村民去village_li.li4_oop:main路径下寻找:
 entry_points={
        'console_scripts': [
            "li4_oop_node = village_li.li4_oop:main"
        ],
    },
  • 编译运行节点:打开vscode终端,进入town_ws。sudo colcon buildsource install/setup.bashros2 run village_li li4_oop_noderos2 node list

10.以POP创建CPP功能包和节点

  • 创建王家村功能包,src目录下执行:ros2 pkg create village_wang --build-type ament_cmake --dependencies rclcpp
  • 接着在village_wang/src下创建一个wang2.cpp文件
  • wang2.cpp中编写代码:
#include "rclcpp/rclcpp.hpp"


int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    /*产生一个Wang2的节点*/
    auto node = std::make_shared<rclcpp::Node>("wang2");
    // 打印一句自我介绍
    RCLCPP_INFO(node->get_logger(), "大家好,我是单身狗wang2.");
    /* 运行节点,并检测退出信号*/
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

  • 添加到CmakeLists最后一行:
//添加这两行代码的目的是让编译器编译wang2.cpp这个文件,不然不会主动编译。
add_executable(wang2_node src/wang2.cpp)
ament_target_dependencies(wang2_node rclcpp)
//需要手动将编译好的文件安装到install/village_wang/lib/village_wang下
install(TARGETS
  wang2_node
  DESTINATION lib/${PROJECT_NAME}
)

  • 编译运行节点:打开vscode终端,进入town_ws。sudo colcon buildsource install/setup.bashros2 run village_wang wang2_noderos2 node list

11.以OOP方式创建CPP

#include "rclcpp/rclcpp.hpp"

/*
    创建一个类节点,名字叫做SingleDogNode,继承自Node.
*/
class SingleDogNode : public rclcpp::Node
{

public:
    // 构造函数,有一个参数为节点名称
    SingleDogNode(std::string name) : Node(name)
    {
        // 打印一句自我介绍
        RCLCPP_INFO(this->get_logger(), "大家好,我是单身狗%s.",name.c_str());
    }

private:
   
};

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    /*产生一个Wang2的节点*/
    auto node = std::make_shared<SingleDogNode>("wang2");
    /* 运行节点,并检测退出信号*/
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

11.ROS2通信机制话题

11.1 话题的规则

  • 话题名字是关键,发布订阅接口类型要相同,发布的是字符串,接受也要用字符串来接收;
  • 同一个人(节点)可以订阅多个话题,同时也可以发布多个话题,就像一本书的作者也可以是另外一本书的读者;
  • 同一个小说不能有多个作者(版权问题),但跟小说不一样,同一个话题可以有多个发布者。

11.2 RQT工具之rqt_gragh

可以通过命令来看到节点和节点之间的数据关系的。

ros2 run demo_nodes_py listener
ros2 run demo_nodes_cpp talker
rqt_graph

11.3 ROS2话题相关命令行界面(CLI)工具

  • ros2 topic -h:topic帮助命令
  • ros2 topic list:返回系统中当前活动的所有主题的列表
  • ros2 topic list -t:增加消息类型
  • ros2 topic echo /<话题名>:打印实时话题内容
  • ros2 topic info /<话题名>:查看主题信息
  • ros2 interface show <某个话题的type名>:查看消息类型
  • ros2 topic pub /<话题名> <话题的type名> 'data: "xxx"':手动发布命令

12.python编写话题发布和订阅

  • 进入空间的src目录执行: ros2 pkg create py_pubsub --build-type ament_python --dependencies rclpy
  • 在与__init__.py同级目录下创建一个publisher.py和subscriber.py文件
  • 发布者代码如下:
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class WriterNode(Node):
    def __init__(self,name):
        super().__init__(name)
        self.name=name
        self.get_logger().info("I am a publisher, my name is %s"%name)
        self.publisher=self.create_publisher(String,"TOPIC",10)

        self.i=0
        self.timer_period=5
        self.timer=self.create_timer(self.timer_period,self.time_callback)
    
    def time_callback(self):
        msg=String()
        container="qwertyuiopasdfghjklzxcvbnm-=[];',./"
        msg.data=f"{container[self.i%34]}"
        self.get_logger().info(f"This is my {self.i} times publish the message for you. And please save the message below:{msg.data}") 
        self.publisher.publish(msg)
        self.i+=1


def main(args=None):
    rclpy.init(args=args)
    node=WriterNode("wjy")
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
 
# 鱼香ROS的代码
# import rclpy
# from rclpy.node import Node

# """
# 导入消息类型

# 声明并创建发布者

# 编写发布逻辑发布数据 
# """
# from std_msgs.msg import String

# class WriterNode(Node):
#     """
#     创建一个李四节点,并在初始化时输出一个话
#     """
#     def __init__(self,name):
#         super().__init__(name)
#         self.get_logger().info("大家好,我是%s,我是一名作家!" % name)
#         # 2.创建并初始化发布者成员属性pubnovel
#         self.pub_novel = self.create_publisher(String,"sexy_girl", 10) 
#         #create_publisher has 3 params:method type,topic name,message length
#         # use this cli to see all the message type in std_msg   :   ros2 interface package std_msgs
#         # use this cli to see all the message type in ros2   :   ros2 interface list


#         #3. 编写发布逻辑
#         # 创建定时器成员属性timer
#         self.i = 0 # i 是个计数器,用来算章节编号的
#         timer_period = 5  #每5s写一章节话
#         self.timer = self.create_timer(timer_period, self.timer_callback)  #启动一个定时装置,每 timer_period s,调用一次time_callback函数


#     def timer_callback(self):
#         """
#         定时器回调函数
#         """
#         msg = String()
#         msg.data = '第%d回:潋滟湖 %d 次偶遇胡艳娘' % (self.i,self.i)
#         self.pub_novel.publish(msg)  #将小说内容发布出去
#         self.get_logger().info('李四:我发布了艳娘传奇:"%s"' % msg.data)    #打印一下发布的数据,供我们看
#         self.i += 1 #章节编号+1

# def main(args=None):
#     """
#     ros2运行该节点的入口函数
#     1. 导入库文件
#     2. 初始化客户端库
#     3. 新建节点
#     4. spin循环节点
#     5. 关闭客户端库
#     """
#     rclpy.init(args=args) # 初始化rclpy
#     node = WriterNode("publisher")  # 新建一个节点
#     rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
#     rclpy.shutdown() # 关闭rclpy
  • 订阅者代码如下:
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class ReceiveNode(Node):
    def __init__(self,name):
        super().__init__(name)
        self.get_logger().info(f"Hi, i am a subscriber, my name is {name}.")
        self.subscription=self.create_subscription(String,"TOPIC",self.listener_callback,10)
        # self.subscription #prevent unused variable warning
    
    def listener_callback(self,msg):
        print(msg)
        self.get_logger().info(f"I have already receive the message:{msg.data}")


def main(args=None):
    rclpy.init(args=args)
    node=ReceiveNode("Larissa")
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
 
  • 还可以将发布订阅者写在一起,新建一个mergepubsub.py(代码来源于鱼香ROS):
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
# 导入话题消息类型
from std_msgs.msg import String,UInt32

class WriterNode(Node):
    """
    创建一个李四节点,并在初始化时输出一个话
    """
    def __init__(self,name):
        super().__init__(name)
        self.get_logger().info("大家好,我是%s,我是一名作家!" % name)
        # 创建并初始化发布者成员属性pubnovel
        self.pubnovel = self.create_publisher(String,"sexy_girl", 10) 


        # 创建定时器成员属性timer
        self.i = 0 # i 是个计数器,用来算章节编号的
        timer_period = 5  #每5s写一章节话
        self.timer = self.create_timer(timer_period, self.timer_callback)  #启动一个定时装置,每 1 s,调用一次time_callback函数


        # 账户钱的数量
        self.account = 80
        # 创建并初始化订阅者成员属性submoney
        self.submoney = self.create_subscription(UInt32,"sexy_girl_money",self.recv_money_callback,10)
        

    def timer_callback(self):
        """
        定时器回调函数
        """
        msg = String()
        msg.data = '第%d回:潋滟湖 %d 次偶遇胡艳娘' % (self.i,self.i)
        self.pubnovel.publish(msg)  #将小说内容发布出去
        self.get_logger().info('李四:我发布了艳娘传奇:"%s"' % msg.data)    #打印一下发布的数据,供我们看
        self.i += 1 #章节编号+1


    def recv_money_callback(self,money):
        """
        4. 编写订阅回调处理逻辑
        """
        self.account += money.data
        self.get_logger().info('李四:我已经收到了%d的稿费' % self.account)


def main(args=None):
    """
    ros2运行该节点的入口函数,可配置函数名称
    """
    rclpy.init(args=args) # 初始化rclpy
    node = WriterNode("li4")  # 新建一个节点
    rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
    rclpy.shutdown() # rcl关闭

  • 同样别忘记在setup.py中添加代码:
 entry_points={
        'console_scripts': [
            "publisher_node=py_pubsub.publisher:main",
            "subscriber_node=py_pubsub.subscriber:main",
            "mergepubsub_node=py_pubsub.mergepubsub:main",
        ],
    },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/992588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cookie、Session、Token、JWT

文章目录 1. 认证(Authentication) & 授权(Authorization) & 凭证(Credentials)1.1 认证(Authentication)1.2 授权(Authorization)1.3 凭证(Credentials) 2. Cookie & Session2.1 什么是 Cookiecookie 重要的属性 2.2 什么是 Session2.3 Cookie 和 Session 的区别 …

来看看Python编码规范(PEP 8)

在讲解具体的​ Python 编 ​码规范之前&#xff0c;先来看看图 1 中的代码&#xff1a; 图 1 两段功能相同的 Python 代码 对比图 1 中的两段代码你会发现&#xff0c;它们所包含的代码时完全相同的&#xff0c;但很明显&#xff0c;右侧的代码编写格式看上去比左侧的代码段更…

VR桥梁应用:实现可视化的桥梁监控

在过去的几年中&#xff0c;虚拟现实(VR)技术已经在多个领域得到了广泛的应用。其中&#xff0c;桥梁巡检是一个特别有前景的应用领域。利用VR技术&#xff0c;我们可以创建一个安全、高效的桥梁巡检方式&#xff0c;帮助工程师和维护人员更好地理解和评估桥梁的状态。 通过VR设…

Mac电脑使用万能头文件教程(详细)

参考:https://blog.csdn.net/weixin_46522531/article/details/126292477 预计阅读操作时间&#xff1a;5分钟 Mac电脑由于使用的是苹果自己的编译器&#xff0c;很多头文件不支持&#xff0c;像万能头就是其中的一员。万能头可以为我们节省很多时间&#xff0c;减少很多不必要…

企业架构LNMP学习笔记28

企业架构LNMP高可用负载均衡服务器之Nginx&#xff1a; 1&#xff09;能够描述负载均衡的作用&#xff1b;loadbalance LB。 2&#xff09;能够了解负载均衡常见的实现方式&#xff1b; 3&#xff09;能够使用nginx实现负载均衡&#xff1b; 4&#xff09;能够描述nginx的常…

OpenCV DNN神经网络部署流程

&#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦 目录 前言 一、加载网络模型 二、构建输入 三、执行推理 四、解析输出 前言…

公开游戏、基于有向图的游戏

目录 〇&#xff0c;背景 一&#xff0c;公开游戏、策梅洛定理 1&#xff0c;公开游戏 2&#xff0c;策梅洛定理 二&#xff0c;有向图游戏 1&#xff0c;狭义有向图游戏 2&#xff0c;广义有向图游戏 3&#xff0c;狭义有向图游戏的SG数 4&#xff0c;Bash Game 力扣…

【List篇】使用Arrays.asList生成的List集合,操作add方法报错

早上到公司&#xff0c;刚到工位&#xff0c;测试同事就跑来说"功能不行了&#xff0c;报服务器异常了&#xff0c;咋回事";我一脸蒙&#xff0c;早饭都顾不上吃&#xff0c;要来了测试账号复现了一下&#xff0c;然后仔细观察测试服务器日志&#xff0c;发现报了一个…

【C语言】错题本(3)

题目: 为了方便分析,我们将题目代码贴在下面: int main() {unsigned char puc[4];struct tagPIM{unsigned char ucPim1;unsigned char ucData0 : 1;unsigned char ucData1 : 2;unsigned char ucData2 : 3;}*pstPimData;pstPimData (struct tagPIM*)puc;memset(puc,0,4);pstPi…

【计算机网络】HTTP(上)

文章目录 1.HTTP概念2. URLurlencode 和 urldecode转义规则 3. HTTP的宏观理解HTTP的请求HTTP的响应 4. 见一见HTTP请求和响应请求报头 1. 模拟一个简单的响应response响应报头 2. 从路径中获取内容ReadFile函数的实现 3.不同资源进行区分反序列化的实现ReadOneLine函数的实现P…

VUE3+JAVA商城源码小程序APP商城

三勾小程序商城基于springbootelement-uiuniapp打造的面向开发的小程序商城&#xff0c;方便二次开发或直接使用&#xff0c;可发布到多端&#xff0c;包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。 软件架构 后端&a…

多维时序 | MATLAB实现GWO-LSTM灰狼算法优化长短期记忆神经网络的多变量时间序列预测

多维时序 | MATLAB实现GWO-LSTM灰狼算法优化长短期记忆神经网络的多变量时间序列预测 目录 多维时序 | MATLAB实现GWO-LSTM灰狼算法优化长短期记忆神经网络的多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现GWO-LSTM灰狼算法优化长短期记忆神…

深圳企业制作宣传片群体定位的重要性

相信众多企业都拍了自己公司的宣传片&#xff0c;尤其是在互联网高度发达的今天&#xff0c;宣传片可以说成为了我们企业对外宣传最主要的方式。看着企业多样式的宣传片种类&#xff0c;我们该如何评价一部宣传片的好坏呢&#xff1f;要知道宣传片的好坏是一个相对主观的问题&a…

Python多进程共享变量实现方法

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 话不多说&#xff0c;直接开搞&#xff0c;如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 一、错误的实现方式 最初以为是没添加global声明导致修改未生效&#xff0c;但实际操作发现global方式在多进程中也只能读…

【ccf-csp题解】第3次csp认证-第三题-集合竞价-枚举

题目描述 思路讲解 本题数据量较小&#xff0c;所以只需要让时间复杂度控制在O&#xff08;n^2&#xff09;就可以满分通过&#xff0c;难度较低 可以用结构体数组事先存下每一个记录的信息&#xff0c;结构体如下&#xff1a; 其中bool值del可以表示这份记录是否已经被删 如…

CSP 202212-1 现值计算

答题 主要就是 #include<iostream>using namespace std;float calculate(float x,float i,int n){float rate1i,ratio1;while(n--){ratioratio*rate;}ratio1/ratio;return x*ratio; }int main() {int n;float rate,x,result0;cin>>n>>rate;for(int i0;i<…

springboot整合mybatisPlus全技巧(2-常用开发技巧:通用字段插入)

本系列专题基于 springboot 整合 mybatisPlus 的各种文章早已烂大街的背景下&#xff0c;根据 整合过程&#xff0c;MP开发中的常见技巧&#xff0c;MP开发中遇到的各种坑 三个方面&#xff0c;来对这一专题做一个全面且实用的总结&#xff0c;基本上只要你吃透这篇文章&#x…

骨传导耳机十大品牌有哪个,骨传导耳机十大品牌排行榜分享

在这个信息爆炸的时代&#xff0c;确实很容易在市场上找到各种各样的骨传导耳机品牌和型号&#xff0c;对于没有相关经验的消费者来说&#xff0c;他们很难判断哪些产品是真正值得信赖的&#xff0c;哪些可能有质量问题或者不适合自己的需求&#xff0c;现如今骨传导耳机的市场…

长胜证券:缩量情绪冰点再现 震荡孕育中期机会

长胜证券指出&#xff0c;近期商场的调整&#xff0c;主要原因来自北向资金扰动和商场牛熊转化期间的信心不足。随着稳增加方针的密布出台&#xff0c;经济修复进程有望加快&#xff0c;增量资金或重回抓反弹阶段&#xff0c;重视量能同步放大水平。一起注册制全面落地后&#…

RLAIF:一个不依赖人工的RLHF替代方案

深度学习自然语言处理 原创作者&#xff1a;Winnie LLM可以标记人类偏好数据&#xff0c;用于强化学习吗&#xff1f;尽管之前有一些类似的研究&#xff0c;但从没有人系统地对比RLHF和RLAIF的性能。今天&#xff0c;我们为大家带来一项Google最新的研究&#xff0c;来看看LLM是…