【ROS2学习记录】—— 参考鱼香ROS

1 回顾Linux基础

(1)打开终端:Ctrl + Alt + T
(2)ls
(3)cd

cd ~
cd /

(4)pwd
(5)mkdir -p catkin_ws/src
(6)rm -rf
(7)mv
(8)cp
(9)gedit
python:解释性语言

python3 test.py

C++:编译性语言

g++ ().cpp
./a.out

2 ROS2介绍

需要ROS
轮式移动机器人:感知、决策、控制

感知:激光雷达、深度相机、IMU、里程计、碰撞感知、建图
决策:路径规划算法、定位算法
控制:轮子驱动

ROS将上面的部分整合到一起

ROS2 vs ROS1

在这里插入图片描述(1)OS层:ROS2相比ROS1支持的平台更多
(2)中间件层:ROS2相比ROS1去中心化master、通信更换为DDS实现
(3)应用层:ROS2支持的python版本更高、编译系统改进、c++11、可以使用相同的API进程间和进程内通信

ROS2入门操作
一、你说我听
打开两个终端

ros2 run demo_nodes_py listener
ros2 run demo_nodes_cpp talker

二、海龟

ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key

三、rqt:选择插件

3 ROS2节点

编程基础
gcc编译ROS2节点
make编译ROS2节点
CMakeList.txt编译ROS2节点

遇到undefined reference to xxxxxNo such file or directory参考:ROS2

在这里插入图片描述
启动一个节点:

ros2 run <package_name> <executable_name>

查看节点列表(常用):

ros2 node list

查看节点信息(常用):

ros2 node info <node_name>

重映射节点名称:

ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle

运行节点时设置参数:

ros2 run example_parameters_rclcpp parameters_basic --ros-args -p rcl_log_level:=10

工作空间找包,包里面去找节点(可执行文件)
与功能包相关的指令 ros2 pkg

create       Create a new ROS2 package
executables  Output a list of package specific executables
list         Output a list of available packages
prefix       Output the prefix path of a package
xml          Output the XML of the package manifest or a specific tag

colcon:类似于ROS中的catkin

colcon build
source install/setup.bash

只编译一个包

colcon build --packages-select YOUR_PKG_NAME

不编译测试单元

colcon build --packages-select YOUR_PKG_NAME --cmake-args -DBUILD_TESTING=0

运行编译的包的测试

colcon test

允许通过更改src下的部分文件来改变install(重要)
每次调整 python 脚本时都不必重新build

colcon build --symlink-install

使用RCLCPP编写节点
面向对象的编程方法OOP
人身上有大脑、有手有脚这些部分,人还能通过这些部分做出一系列行为
对象=属性+行为
五个重要概念:类与对象、封装、继承、多态

mkdir -p catkin_ws/src
cd catkin_ws
ros2 pkg create test1 --build-type ament_cmake --dependencies rclcpp

在功能包的src上新建node.cpp

#include "rclcpp/rclcpp.hpp"

class Node01 : public rclcpp::Node {
public:
	Node01(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);
	
	auto node = std::make_shared<Node01>("node_01");
	
	rclcpp::spin(node);
	rclcpp::shutdown();
	return 0;
}

CMakeList.txt

cmake_minimum_required(VERSION 3.8)
project(test1)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)

add_executable(node_01 src/node.cpp)
ament_target_dependencies(node_01 rclcpp)

install(TARGETS node_01 DESTINATION lib/${PROJECT_NAME})



if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

test1.cpp

#include "rclcpp/rclcpp.hpp"

int main(int argc, char **argv)
{
    /* 初始化rclcpp  */
    rclcpp::init(argc, argv);
    /*产生一个node_01的节点*/
    auto node = std::make_shared<rclcpp::Node>("node_01");
    // 打印一句自我介绍
    RCLCPP_INFO(node->get_logger(), "node_01节点已经启动.");
    /* 运行节点,并检测退出信号 Ctrl+C*/
    rclcpp::spin(node);
    /* 停止运行 */
    rclcpp::shutdown();
    return 0;
}

colcon使用进阶

4 订阅者发布者

rqt_graph
ros2 topic -h
ros2 topic list # 返回系统中当前活动的所有主题的列表
ros2 topic list -t # 增加消息类型
ros2 topic echo <topic_name> # 打印实时话题内容
ros2 interface show # 查看消息类型
ros2 topic pub /chatter std_msgs/msg/String 'data: "123"'

publisher.cpp

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

class Publisher : public rclcpp::Node
{
public:
	Publisher(std::string name) : Node(name) {
		RCLCPP_INFO(this->get_logger(), "%s节点", name.c_str());	
		
		publisher_ = this->create_publisher<std_msgs::msg::String>("command", 10);
		
		timer_ = this->create_wall_timer(std::chrono::milliseconds(500), std::bind(&Publisher::timer_callback, this));
	}
private:
	void timer_callback()
	{
		std_msgs::msg::String message;
		message.data = "forward";
		RCLCPP_INFO(this->get_logger(), "Publishing:%s", message.data.c_str());
		publisher_->publish(message);	
	}
	rclcpp::TimerBase::SharedPtr timer_;
	rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
};

int main(int argc, char** argv) {
	rclcpp::init(argc, argv);
	auto node = std::make_shared<Publisher>("topic");
	rclcpp::spin(node);
	rclcpp::shutdown();
	return 0;	
}

subscriber.cpp

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

class TopicSubscribe01 : public rclcpp::Node
{
public:
    TopicSubscribe01(std::string name) : Node(name)
    {
        RCLCPP_INFO(this->get_logger(), "大家好,我是%s.", name.c_str());
          // 创建一个订阅者订阅话题
        command_subscribe_ = this->create_subscription<std_msgs::msg::String>("command", 10, std::bind(&TopicSubscribe01::command_callback, this, std::placeholders::_1));
    }

private:
     // 声明一个订阅者
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr command_subscribe_;
     // 收到话题数据的回调函数
    void command_callback(const std_msgs::msg::String::SharedPtr msg)
    {
        double speed = 0.0f;
        if(msg->data == "forward")
        {
            speed = 0.2f;
        }
        RCLCPP_INFO(this->get_logger(), "收到[%s]指令,发送速度 %f", msg->data.c_str(),speed);
    }
};

int main(int argc, char** argv)
{
	rclcpp::init(argc, argv);
	auto node = std::make_shared<TopicSubscribe01>("Subscribe01");
	rclcpp::spin(node);
	rclcpp::shutdown();
	return 0;	
}

CMakeList.txt

cmake_minimum_required(VERSION 3.8)
project(topicc)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

add_executable(publisher src/publisher.cpp)
ament_target_dependencies(publisher rclcpp std_msgs)

add_executable(subscriber src/subscriber.cpp)
ament_target_dependencies(subscriber rclcpp std_msgs)

install(TARGETS
	publisher
	subscriber
	DESTINATION lib/${PROJECT_NAME}
)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

package.xml

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>topicc</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="bigdavid@todo.todo">bigdavid</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>rclcpp</depend>
  <depend>std_msgs</depend>
  
  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

5 ROS2接口

字符串和32位二进制的整型数据

std_msgs/msg/String
std_msgs/msg/UInt32

ros2 interface package sensor_msgs
可以定义的接口三种类型
话题接口、服务接口、动作接口

话题接口格式:xxx.msg

int64 num

服务接口格式:xxx.srv

int64 a
int64 b
---
int64 sum

动作接口格式:xxx.action

int32 order
---
int32[] sequence
---
int32[] partial_sequence

接口数据类型:基础类型和包装类型

基础类型有(同时后面加上[]可形成数组)

bool
byte
char
float32, float64
int8 uint8
int16 uint16
int32 uint32
int64 uint64
string

包装类型
即在已有的接口类型上进行包含

uint32 id
string image_name
sensor_msgs/Image

自定义接口
机器人开发中的常见控制场景,设计满足要求的服务接口和话题接口

机器人节点:对外提供移动指定距离服务,移动完成后返回当前位置,同时对外发布机器人的位置和状态(是否在移动)
机器人控制节点:通过服务控制机器人移动指定距离,并实时获取机器人的当前位置和状态

服务接口MoveRobot.srv

float32 distance
---
float32 pose

话题接口,采用基础类型 RobotStatus.msg

uint32 STATUS_MOVING = 1
uint32 STATUS_STOP = 1
uint32 status
float32 pose

话题接口,混合包装类型 RobotPose.msg

uint32 STATUS_MOVING = 1
uint32 STATUS_STOP = 2
uint32 status
geometry_msgs/Pose pose

查看接口列表:ros2 interface list
查看某一个接口详细的内容:ros2 interface show std_msgs/msg/String

创建功能包:

ros2 pkg create example_ros2_interfaces --build-type ament_cmake --dependencies rosidl_default_generators geometry_msgs

修改CMakeList.txt

find_package(rosidl_default_generators REQUIRED)
find_package(geometry_msgs REQUIRED)
# 添加下面的内容
rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/RobotPose.msg"
  "msg/RobotStatus.msg"
  "srv/MoveRobot.srv"
  DEPENDENCIES geometry_msgs
)

修改package.xml

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>rosidl_default_generators</depend>
  <depend>geometry_msgs</depend>
  
  <member_of_group>rosidl_interface_packages</member_of_group> #添加这一行

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

6 Nav2

行为树:什么时候规划,什么时候脱困,用行为树来描述和管理机器人,Nav2用这个进行机器人行为调度

在这里插入图片描述通过输入的 XML 格式的行为树描述文件,调用下面三个服务器中中对应的模块完成对机器人的行为控制

Planner Server:全局路径规划
Controller Server:根据全局路径,结合实时障碍物和局部代价地图完成机器人的控制
Recovery Server:加载不同的恢复行为完成机器人的脱困

BT Navigation Server 收到目标点后,由规划器服务器进行 CP(ComputePathToPose)即计算路径 ,然后由控制器服务器进行 FP(FollowPath)即路径跟随,如果遇到卡住等困境则调用规划器服务器完成脱困。这三个模块协同工作,完成了整个 Navigation 2 的导航任务。


持续更新

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 198—— 打家劫舍

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 此题使用动态规划求解&#xff0c;假设 d p [ i ] [ 0 ] dp[i][0] dp[i][0] 代表不偷窃第 i i i 个房屋可以获得的最高金额&#xff0c;而 d p [ i ] [ 1 ] dp[i][1] dp[i][1] 代表偷窃第 i i i 个房屋可以获…

【右一的开发日记】全导航,持续更新...

文章目录 &#x1f4da;前端【跟课笔记】&#x1f407;核心技术&#x1f407;高级技术 &#x1f4da;捣鼓捣鼓&#x1f407;小小案例&#x1f407;喵喵大王立大功&#x1f407;TED自用学习辅助网站&#x1f407;世界top2000计算机科学家可视化大屏&#x1f407;基于CBDB的唐代历…

GitHub Copilot 简单使用

因为公司安全原因&#xff0c;并不允许在工作中使用GitHub Copilot&#xff0c;所以&#xff0c;一直没怎么使用。最近因为有一些其它任务&#xff0c;所以&#xff0c;试用了一下&#xff0c;感觉还是很不错的。&#xff08;主要是C和Python编程&#xff09; 一&#xff1a;常…

python中的进程线程和协程

目录 进程&#xff08;Process&#xff09;多进程代码实例 线程&#xff08;Thread&#xff09;多线程存在原因及其缺点多线程代码实例 协程&#xff08;Coroutine&#xff09;协程的优点协程代码实例 进程、线程和协程适合的任务性质和环境多进程更适合的场景多线程更适合的场…

LeetCode 11—— 盛最多水的容器

阅读目录 1. 题目2. 解题思路一3. 代码实现一4. 解题思路二5. 代码实现二 1. 题目 2. 解题思路一 暴力法&#xff0c;遍历所有可能的垂线对 ( i , j ) (i, j) (i,j)&#xff0c;求取最大面积&#xff1a; a r e a m i n ( h [ i ] , h [ j ] ) ∗ ( j − i ) area min(h[i]…

Node.js -- MongoDB

文章目录 1. 相关介绍2. 核心概念3. 命令行交互3.1数据库命令3.2 集合命令3.3 文档命令 4. 数据库应用场景4.1 新增4.2 删除4.3 更新4.4 查询 1. 相关介绍 一、简介 Mongodb是什么 MongoDB是一个基于分布式文件存储的数据库&#xff0c;官方地址https://www.mongodb.com/try/d…

一个C++小程序调试过程记录

Top 20 C Projects With Source Code [2024 Update]https://www.interviewbit.com/blog/cpp-projects/ 这个网页有一些简单的C程序的源码&#xff0c;闲来无事&#xff0c;把第一个程序&#xff08;Bookshop Management System Using C&#xff09;的源码下载了下来。 源文件…

第N1周:one-hot独热编码

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、OneHot独热编码原理 独热编码&#xff08;One-Hot Encoding&#xff09;是一种将分类数据转换为二进制向量的方法&#xff0c;其中每个类别对应一个唯一的…

如何下载AndroidStudio旧版本

文章目录 1. Android官方网站2. 往下滑找到历史版本归档3. 同意软件下载条款协议4. 下载旧版本Androidstudio1. Android官方网站 点击 Android官网AS下载页面 https://developer.android.google.cn/studio 进入AndroidStuido最新版下载页面,如下图: 2. 往下滑找到历史版本归…

Delta lake with Java--利用spark sql操作数据2

上一篇文章尝试了建库&#xff0c;建表&#xff0c;插入数据&#xff0c;还差删除和更新&#xff0c;所以在这篇文章补充一下&#xff0c;代码很简单&#xff0c;具体如下&#xff1a; import org.apache.spark.sql.SaveMode; import org.apache.spark.sql.SparkSession;publi…

谈一谈电影《飞驰人生》

文章目录 1.概述2.电影情节3.观后感 1.概述 电影《飞驰人生》是一部关于赛车的电影&#xff0c;主要演员是沈腾&#xff0c;因此电影中有不少的喜剧片段&#xff0c;不过电影整体偏向于剧情类电影。该电影的导演是韩寒&#xff0c;就是哪个曾经写出高分高考作文的考生&#xf…

【跟我学RISC-V】(一)认识RISC-V指令集并搭建实验环境

写在前面 现在计算机的体系架构正是发展得如火如荼的时候&#xff0c;占领桌面端市场的x86架构、占领移动端市场的arm架构、在服务器市场仍有一定地位的mips架构、国产自研的指令集loongarch架构、还有我现在要讲到的新型开源开放的RISC-V指令集架构。 我先说一说我的学习经历…

十二、视觉内容生成模型

1 判别式模型和生成式模型 1. 判别式模型 学习策略函数 Y f ( X ) Yf(X) Yf(X)或者条件概率 P ( Y ∣ X ) P(Y|X) P(Y∣X)不能反映训练数据本身的特性学习成本低&#xff0c;需要的训练样本少无法转为生成式 2. 生成式模型 学习联合概率密度分布 P ( X ∣ Y ) P(X|Y) P(X∣…

C++ 矩阵

目录 了解矩阵的数学原理&#xff08;大学线性代数&#xff09; 矩阵及转置矩阵 矩阵乘法 矩阵快速幂 相伴矩阵模板 [相伴矩阵,快速矩阵幂]CSES1722 Fibonacci Numbers 了解矩阵的数学原理&#xff08;大学线性代数&#xff09; 矩阵及转置矩阵 这里A就是一个矩阵&…

动态数据结构中的表扩张性:摊还分析、伪代码与C语言实现

动态数据结构中的表扩张性&#xff1a;摊还分析、伪代码与C语言实现 引言表扩张性的概念摊还分析在表扩张性中的应用伪代码示例&#xff1a;TABLE-INSERT操作C语言实现结论 引言 在处理数据结构时&#xff0c;尤其是表&#xff08;或数组&#xff09;&#xff0c;我们经常面临…

Swift - 可选项(Optional)

文章目录 Swift - 可选项&#xff08;Optional&#xff09;1. 可选项&#xff08;Optional&#xff09;2. 强制解包&#xff08;Forced Unwrapping&#xff09;3. 判断可选项是否包含值4. 可选项绑定&#xff08;Optional Binding&#xff09;5. 等价写法6. while循环中使用可选…

DVWA 靶场命令注入通关解析

介绍 命令注入&#xff08;Command Injection&#xff09;是一种常见的安全漏洞&#xff0c;它允许攻击者通过在应用程序中执行恶意命令来获取系统权限或执行非授权操作。 命令注入通常发生在需要将用户输入作为命令执行的地方&#xff0c;例如Web应用程序的输入框、参数传递…

制作一个RISC-V的操作系统十五-软件定时器

文章目录 定时器分类定时器相关分类软件定时器设计初始化创建删除触发流程图形示意 优化代码 定时器分类 硬件定时器&#xff1a;由硬件频率和触发限制的大小决定&#xff0c;只有一个&#xff0c;精度高 软件定时器&#xff1a;基于硬件定时器实现&#xff0c;精度大于等于硬…

搭建vue3组件库(三): CSS架构之BEM

文章目录 1. 通过 JS 生成 BEM 规范名称1.1 初始化 hooks 目录1.2 创建 BEM 命名空间函数1.3 通过 SCSS 生成 BEM 规范样式 2. 测试 BEM 规范 BEM 是由 Yandex 团队提出的一种 CSS 命名方法论&#xff0c;即 Block&#xff08;块&#xff09;、Element&#xff08;元素&#xf…

AngularJS 的生命周期和基础语法

AngularJS 的生命周期和基础语法 文章目录 AngularJS 的生命周期和基础语法1. 使用步骤2. 生命周期钩子函数3. 点击事件4. if 语句1. if 形式2. if else 形式 5. for 语句6. switch 语句7. 双向数据绑定 1. 使用步骤 // 1. 要使用哪个钩子函数&#xff0c;就先引入 import { O…
最新文章