《Ubuntu22.04环境下的ROS2学习笔记2》

news2024/11/15 2:15:58

一、在ROS2环境下创建功能包

        如果您已经完成了上一小节的内容,那么接下来您一定渴望自己创建一个功能包来实现相应的功能。在ROS1中,您创建的功能包可以既写C/C++,又写python,但ROS2中不允许用户这么做,您的C/C++和python代码创建的功能包是不一样的。

二、创建功能包的流程

ros2 pkg create <package_name> --build-type ament_cmake 

ros2 pkg create <package_name> --build-type ament_python

这两句代码分别对应两种不同的功能包,我们创个C/C++的来看看怎么个事。

这里警告了,原因是咋们的许可证没选择在ROS2官方文档里面是带了这个参数项的

--license Apache-2.0

ros2 pkg create --build-type ament_cmake --license Apache-2.0 <package_name>

他的功能包名字放在最后,参数里除了提示了是C/C++语言还提到了许可证,但不填似乎问题不大,当然您不过看到警告就烦体质可以带上。方便复制下面。

ros2 pkg create <package_name> --build-type --license Apache-2.0 ament_cmake 

三、编写代码

        这次编写代码原本我是想用像大多数一样的class类继承rclcpp::Node的方式来写的,但是奈何技术不够,磕了几天感觉头疼换和ROS1类似的方式写了下面的代码,同时呢我想让本次的测试更有观赏性和参考性,我用了turtlesim功能包作为我的辅助,同时详细介绍下msg文件如何include。

a、首先我下载了turtlesim功能包

        您可以 ROS Package: turtlesim 先ros.index网站找到功能包,详细细节您可以看我之前的一篇文章《Ubuntu20.04环境下的ROS进阶学习0》_ubuntu下查看ros-CSDN博客

总而言之您只需要操作以下代码就可以下载该功能包:

cd ~/ros2_ws/src

git clone https://github.com/ros_tutorials.git

b、各种msg消息类型

        同样的操作搜索common_interfaces功能包,如下操作也行。

cd ~/ros2_ws/src

git clone https://github.com/ros2/common_interfaces.git

c、下载eigen3库

        这个和之前不一样,这个是一个C++的头文件集,用来处理向量、矩阵和线性代数相关的计算和转换。

cd ~/code        (没有记得建一个文件夹)

git clone https://gitlab.com/libeigen/eigen.git

git完后咱么那就要解压安装了。

cd eigen

mkdir build

cd build 

cmake ..

sudo make install

d、编写代码

 cd ~/ros2_ws/src

touch turtle_control.cpp 

        代码实现了turtle_control节点订阅turtle1/pose同时向turtle1/cmd_vel里面发送消息的功能。

所以在实际测试的时候得运行turtlesim节点。

#include <chrono>	//C++标准库,用于处理时间和日期的工具,特别是处理时间间隔和计数器
#include <memory>	//C++标准库,提供了智能指针,用于管理动态分配的内存,以避免内存泄漏
#include <string>	//C++标准库的头文件,提供了string类型的字符串相关操作函数
#include <eigen3/Eigen/Geometry> 	// C++ 用来提供向量和矩阵运算的头文件库

#include "rclcpp/rclcpp.hpp"          // ROS2 C++接口库
#include "std_msgs/msg/string.hpp"    // 字符串消息类型
#include "turtlesim/msg/pose.hpp"
#include "geometry_msgs/msg/twist.hpp"		//位置好像是 /ros2_ws/install/geometry_msgs/include/geometry_msgs/geometry_msgs/msg


class Turtle_Pose_Sub
{
	public:
		Turtle_Pose_Sub() : receive_flag_(false){}
		
		void Turtle_Pose_Callback(const turtlesim::msg::Pose::ConstPtr& msg)
		{
			turtle_pose_msgs_ = *msg;
			receive_flag_ = true;
		}
		
		bool Get_Turtle_Info(turtlesim::msg::Pose& msg)
		{
			if(receive_flag_)
			{
				msg = turtle_pose_msgs_;
				return true;
			}
			return false;
		}
	

	private:
		bool receive_flag_;
		turtlesim::msg::Pose turtle_pose_msgs_;
		
	
};

int main(int argc , char * argv[])
{
	rclcpp::init(argc , argv);	//初始化rclcpp
	rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("turtle_control");	//创建节点
	rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr turtle1_cmd_vel_pub = node->create_publisher<geometry_msgs::msg::Twist>("/turtle1/cmd_vel" , 10);
	
	Turtle_Pose_Sub Turtle_pose_sub_class;
	//rclcpp::Subscription<turtlesim::msg::Pose>::SharedPtr turtle1_pose_sub = node->create_subscription<turtlesim::msg::Pose>("/turtle1/pose" , 10 , &Turtle_Pose_Sub::Turtle_Pose_Callback , &Turtle_pose_sub_class);
	rclcpp::Subscription<turtlesim::msg::Pose>::SharedPtr turtle1_pose_sub = node->create_subscription<turtlesim::msg::Pose>("/turtle1/pose" , 10 , std::bind(&Turtle_Pose_Sub::Turtle_Pose_Callback , &Turtle_pose_sub_class , std::placeholders::_1));
	
	rclcpp::WallRate loop_rate(10);	// 创建时钟 并设置评率为1s 10次
	
	geometry_msgs::msg::Twist turtle1_cmd_vel_msg;
	turtlesim::msg::Pose turtle1_pose_msg;
	Eigen::Matrix<double, 2, 1> turtle_point;
	Eigen::Matrix<double, 2, 1> target_point;
	Eigen::Matrix<double, 2, 1> P;
	Eigen::Matrix<double, 2, 1> U;
	Eigen::Matrix<double, 2, 2> R_;
	double theta , distance;
	
	target_point << 6.0 , 7.0;
	
	std::cout << "i will go to while" << std::endl;
	while(rclcpp::ok())
	{
		rclcpp::spin_some(node);
		try
		{
			//std::cout << "i am trying it" << std::endl;
			if(Turtle_pose_sub_class.Get_Turtle_Info(turtle1_pose_msg))
			{
				//std::cout << turtle1_pose_msg.x << std::endl;
				turtle_point << turtle1_pose_msg.x , turtle1_pose_msg.y;
				theta = turtle1_pose_msg.theta;
			}
		}
		catch(const std::out_of_range& e)
		{
			continue;
		}
		
		R_ << cos(theta),sin(theta),-sin(theta),cos(theta);
		P << target_point(0) - turtle_point(0) , target_point(1) - turtle_point(1);
		distance = sqrt(P.transpose()*P);
		std::cout << "distance = " << distance << "\n" << std::endl;
		std::cout << "turtle_point = \n" << turtle_point << "\n" << std::endl;
		std::cout << "theta = " << theta << std::endl;
		U = R_ * P;
		turtle1_cmd_vel_msg.linear.x = U(0);
		turtle1_cmd_vel_msg.angular.z = U(1);
		
		//这个限幅写的好丑,我建议去掉{},但我不喜欢。
		if(turtle1_cmd_vel_msg.linear.x > 2)
		{
			turtle1_cmd_vel_msg.linear.x = 2;
		}
		if(turtle1_cmd_vel_msg.linear.x < -2)
		{
			turtle1_cmd_vel_msg.linear.x = -2;
		}
		if(turtle1_cmd_vel_msg.angular.z > 2)
		{
			turtle1_cmd_vel_msg.angular.z = 2;
		}
		if(turtle1_cmd_vel_msg.angular.z < -2)
		{
			turtle1_cmd_vel_msg.angular.z = -2;
		}
		
		if(distance < 0.3)
		{
			turtle1_cmd_vel_msg.linear.x = 0;
			turtle1_cmd_vel_msg.angular.z = 0;
		}
		turtle1_cmd_vel_pub->publish(turtle1_cmd_vel_msg);
		
		loop_rate.sleep();
	}
	
	
	return 0;
}

        值得注意的一点是,该代码并没有像官方示例一样使用继承节点的关系继承 : rclcpp_Node类,而是类似于C语言的方式面向过程写的,在之后的改进我将试着使用。

e、修改CMakeList.txt

        在ROS2中的CMakeList.txt 和ROS1中有一定的区别,而在本次的教程中您只需要修改以下部分。

首先本次程序需要一下功能包,其中参数分别是:功能包名 、 REQUIRED(必须,即缺少报错)。

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(turtlesim REQUIRED)

将我们写的CPP文件编译成可执行文件,同时添加依赖项。

add_executable(turtle_control src/turtle_control.cpp)
ament_target_dependencies(turtle_control rclcpp std_msgs geometry_msgs turtlesim)

指定可执行文件的位置。

install(TARGETS

  turtle_control
    
    DESTINATION lib/${PROJECT_NAME})

整体如下所示,之后为了篇幅将不再贴出。

cmake_minimum_required(VERSION 3.8)
project(turtle_control)

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)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(turtlesim REQUIRED)

add_executable(turtle_control src/turtle_control.cpp)
ament_target_dependencies(turtle_control rclcpp std_msgs geometry_msgs turtlesim)

#add_executable(turtle_control_useclass src/turtle_control_useclass.cpp)
#ament_target_dependencies(turtle_control_useclass rclcpp std_msgs geometry_msgs turtlesim)


install(TARGETS

  turtle_control
	#turtle_control_useclass
	
	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()

f、编译运行代码

cd ~/ros2_ws

colcon build        (运行这段代码的时间有时可达3分钟,编译真的超慢ROS2)

当然如果您已经编译过,您只需要编译您新写的代码就行

参数是--packages-select + 功能包名

source install/local_setup.bash  (添加到路径)

这里可以写到 .bashrc 里

source ~/ros2_ws/install/local_setup.sh

运行这里我们一共打开两个终端:

第一个终端输入:  ros2 run turtlesim turtlesim_node

第二个终端输入:  ros2 run turtle_control turtle_control

        可以看到,这里的终端里面的坐标和距离目标点的距离,我们代码里面设置的distance < 0.3则停,如果您设置太小,小海龟会在那一直打圈,这个和我们的控制律有关系,之后在解决这不是本次的重点。

四、参考

Creating a package — ROS 2 Documentation: Humble documentation

ROS2 发布/订阅Topic_ros2 发布订阅-CSDN博客

[Eigen中文文档] 从入门开始..._eigen库下载-CSDN博客  

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

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

相关文章

UniApp的神器-开启前端开发的全新篇章

本文介绍了DIYGW UniApp可视化工具作为一款低代码开发平台的特点和优势。该工具采用拖拽式设计和模块化开发&#xff0c;能够快速转化想法为可运行应用&#xff0c;并支持多种平台部署。它具有所见即所得的设计体验、丰富的组件库、前后台通信模块和跨平台兼容性等特点。使用该…

netsat -ano 详解

netsat -ano会输出一大堆端口&#xff0c;为什么nmap扫描出来的却只有两个 因为我们的服务器或者工作站有开启防火墙&#xff0c;过滤了nmap的流量&#xff0c;导致nmap扫描不到一些端口&#xff0c;再加上我们的开放端口有一些是只有本地才能访问的 怎么看哪些端口只有本地能…

基于Pytorch深度学习图像处理基础流程框架(以ResNetGenerator为例)

文章目录 - 模型搭建1. 搭建ResNetGenerator2. 网络实例化3.加载预训练模型权重文件4. 神经网络设置为评估模式 预测处理1. 定义图片的预处理方法2. 导入图片3. 预处理图片4. 调用模型5. 输出结果 - 模型搭建 1. 搭建ResNetGenerator import torch import torch.nn as nnclas…

go 调用C语言函数或者库

1.查看cgo是否开启 go env | grep CGO_ENABLED CGO_ENABLED1 2. go程序中加入 import "C" 通过 import “C” 语句启用 CGO 特性后&#xff0c;CGO 会将上一行代码所处注释块的内容视为 C 代码块 单行注释使用// 多行注释使用/* */ 3. go 与C 类型转换 在g…

HSL模型和HSB模型,和懒人配色的Color Hunt

色彩不仅仅是视觉上的享受&#xff0c;它在数据可视化中也扮演着关键角色。通过合理运用色彩模型&#xff0c;我们可以使数据更具可读性和解释性。在这篇文章将探讨HSL&#xff08;Hue, Saturation, Lightness&#xff09;和HSB&#xff08;Hue, Saturation, Brightness&#x…

【机器学习】深度学习实践

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言一、深度学习基础二、图像分类示例三、拓展思考结语 引言 在当今人工智能的浪潮中&#xff0c;深度学习作为其核心驱动力之一&#xff0c;正以前所未有的速度改变着我们的世界。从图像识别、语音…

c语言第18天笔记

构造类型 结构体类型 结构体数组 案例&#xff1a; 需求&#xff1a;对候选人得票的统计程序。设有3个候选人&#xff0c;每次输入一个得票的候选人的名字&#xff0c;要求最后输出 各人得票结果。 ​ /** * 结构体数组案例&#xff1a;对候选人得票的统计程序。设有3个候…

主机组装笔记

参考资源&#xff1a;B站【装机教程】全网最好的装机教程&#xff0c;没有之一&#xff0c;仅供探讨学习 9大部件一览 其中得到固态和机械&#xff0c;是硬盘&#xff0c;存储空间&#xff0c;可以只选固态 CPU&#xff0c;主要有 AMD 和 Intel (AMD&#xff0c;基板的背面布…

力扣 58. 最后一个单词的长度

题目描述 思路 下意识想到先以空格作为分割符对字符串进行分割得到若干个子字符串&#xff0c;然后用字符串长度计算函数计算最后一个子字符串的长度。 该思路代码如下&#xff1a; class Solution:def lengthOfLastWord(self, s: str) -> int:s_array s.split()last_le…

全新在线客服系统源码(pc+h5+uniapp+公众号小程序+抖音)附搭建接入教程

全新在线客服系统源码介绍 一、系统概述与优势 本系统是一款基于PHP的开源在线客服系统&#xff0c;支持PC端、移动端(小程序)、H5页面以及Uniapp多端接入。系统利用网络技术和人工智能技术&#xff0c;实现用户与客服人员的即时聊天沟通&#xff0c;有效提升服务质量和用户满意…

Python+Selenium+Pytest+POM自动化测试框架封装详解

1、测试框架简介 1&#xff09;测试框架的优点 代码复用率高&#xff0c;如果不使用框架的话&#xff0c;代码会显得很冗余。可以组装日志、报告、邮件等一些高级功能。提高元素等数据的可维护性&#xff0c;元素发生变化时&#xff0c;只需要更新一下配置文件。使用更灵活的…

透明加密软件排行榜前十名(2024年10大好用的透明加密软件推荐)

在当今数字化的时代&#xff0c;数据的安全性和保密性已经成为了企业和个人最为关注的问题之一。随着信息技术的飞速发展&#xff0c;各种数据泄露事件层出不穷&#xff0c;给企业和个人带来了巨大的损失。在这样的背景下&#xff0c;透明加密软件应运而生&#xff0c;成为了保…

商家转账到零钱申请必过教程2024

在微信作为重要的营销场景的当下&#xff0c;微信支付的商家转账到零钱功能对于众多企业来说具有重要意义。要顺利开通该接口&#xff0c;需要注意以下几个要点。 首先&#xff0c;需要公司主体资质。申请主体必须是公司&#xff0c;个体工商户暂无法申请。同时&#xff0c;要确…

8.15成都市计量院面试问答

&#x1f416; Q&#xff1a;为什么要选择计量检定测试院&#xff1f; A&#xff1a;市计量院具备多项资质认定和计量认证项目&#xff0c;选择成都市计量检定测试院&#xff0c;意味着接触前沿技术&#xff0c;积累丰富经验&#xff0c;服务社会公益&#xff0c;参与创新研发&…

spring揭秘01-spring容器启动过程分析

文章目录 【README】【1】Spring容器根据配置元素组装可用系统的过程【2】BeanFactoryPostProcessor-Bean工厂后置处理器【2.1】属性占位符配置器使用场景代码【2.2】CustomerEditorConfigurer-自定义编辑器配置器【2.3】自定义编属性编辑器案例代码 【README】 本文总结自《s…

为什么electron占用空间大,而Tauri占用小,他们不都是封装Chromium吗

Electron 和 Tauri&#xff08;使用 WebView&#xff09;的确都涉及嵌入浏览器引擎来渲染 HTML、CSS 和 JavaScript&#xff0c;但它们的架构和设计有显著不同&#xff0c;这导致了它们在应用程序体积和资源占用上的差异。以下是一些关键的原因&#xff1a; 1. 嵌入的浏览器引…

【中等】 猿人学web第一届 第6题 js混淆-回溯

文章目录 请求流程请求参数 加密参数定位r() 方法z() 方法 加密参数还原JJENCOde js代码加密环境检测_n("jsencrypt")12345 计算全部中奖的总金额请求代码注意 请求流程 请求参数 打开 调试工具&#xff0c;查看数据接口 https://match.yuanrenxue.cn/api/match/6 请…

MySQL运维-分库分表

介绍 问题分析 拆分策略 垂直拆分 水平拆分 实现技术 Mycat概述 介绍 概念介绍 Mycat配置 schema.xml schema标签 schema标签&#xff08;table&#xff09; datanode标签 datahost标签 rule.xml sever.xml system标签 user标签 Mycat分片 分片规则-范围 分片规则-取模 分…

linux部署elasticserch单节点

简介 Elasticsearch概述&#xff1a;Elasticsearch是一个建立在Apache Lucene之上的分布式、实时文档存储搜索引擎&#xff0c;它能够胜任上百个服务节点的扩展&#xff0c;并支持PB级别的结构化或非结构化数据。 Lucene与Elasticsearch&#xff1a;简要介绍Lucene作为搜索引擎…

分布式中的CAP理论是什么?BASE理论是什么?看完你就彻底懂啦

CAP 理论 CAP理论是分布式系统理论中的一个重要概念&#xff0c;它阐述了在分布式计算环境中&#xff0c;一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区容错性&#xff08;Partition Tolerance&#xff09;三者之间的权衡关系…