本人最近在学习ros2,看了鱼香ros的教程,还没学完就看到b站有一个大佬发布了一个八分钟入门视频,不禁极为好奇,整个看下来其实是做了一个很实用的框架,所以我想要在我使用的ubuntu20.04里复刻一下操作,并尝试改到能在ros2下运行的程度
这篇文章会记录我的操作,想要看到具体细节和讲解的话希望可以观看这个视频:超精简8分钟ros入门教程,实战前够用的基础知识。茴字有四种写法,但你只要会一种_哔哩哔哩_bilibili侵删
需要做的准备:
安装好20.04版本的ubuntu
ros和visual studio code(这些我就直接用鱼香ros的脚本下好了,各位也可以试试)
vs code要在扩展界面下载c++和ros(ros2)和cmake tools
1.创建工作空间(即创建两个文件夹)
在对应地址创建好一个随意取名的文件夹(我命名为ros2_workplace),再进入这个文件夹,创建一个src文件夹
这个时候工作空间就创建好了,所有ros代码都会放在src文件夹下
2.创建功能包(独立的代码模块)
进入src文件夹,输入指令
(1)ros:
//ros
catkin_create_pkg example roscpp
//ros2
ros2 pkg create example --build-type ament_cmake --dependencies rclcpp
就能创建好一个包含roscpp库的源代码的包,名字叫example
3.创建最基础的ros代码,并进行编译运行
在example文件夹内的src文件夹内创建cpp源代码
touch example.cpp
4.用vscode打开功能包
操作为右键src下的example文件夹,选择用其他应用打开
或者直接在vscode内打开文件夹,选择对应的example文件夹
5.在创建的cpp中引入头文件
//ros
#include<ros/ros.h>
//ros2
#include "rclcpp/rclcpp.hpp"
※引入头文件时报错解决方案:
1.查看vscode的拓展有没有下载好ros(ros2)
2.非vscode:编辑includePATH,我安装的是ros2 foxy,路径一般在opt/ros/foxy/include/rclcpp/rclcpp.hpp
6.编辑主程序
ros:
int main(int argc.char**argv)
{
ros::init(argc,argv,"example"); //初始化ROS节点,不写example就系统默认
ros::NodeHandle nh; //创建ros节点句柄
std::cout<<"hello ros!"<<std::endl;
return 0;
}
ros2:
int main(int argc.char**argv)
{
rclcpp::init(argc, argv, rclcpp::InitOptions()); //初始化ROS2节点
auto node = std::make_shared<rclcpp::Node>("example"); //创建名为example的ros2节点
return 0;
}
7.指定编译规则
在CMakeList.txt(就在src文件夹下)中添加句式
ros:
add_executable(${PROJECT_NAME}_node src/example_node.cpp)
//134行,记得修改对应的PROJECT_NAME
target_link/-libraries(${PROJECT_NAME}_node ${catkin——;IBRARIES})
//149-151行,记得修改对应的PROJECT_NAME
ros2:
add_executable(my_new_node src/my_new_node.cpp)
target_link_libraries(my_new_node ${rclcpp_LIBRARIES})
install(TARGETS my_new_node DESTINATION lib/${PROJECT_NAME})//安装目标的二进制文件
8.编译生成可执行文件
在工作空间根目录下执行catkin_make命令(ros2用colcon build)
//ros
catkin_make
//ros2,记得修改对应的your_package_name
colcon build --packages-select <your_package_name>
然后根目录下会出现两个文件夹,可执行文件在devel下(ros2在install)
9.确保工作空间环境变量在当前终端生效
使用以下命令
//ros
//仅当前终端有效
source devel/setup.bash
//ros2
//仅当前终端有效
source install/setup.bash
10.运行ros节点
在这之前要先执行roscore命令启动ros(直接在终端里输入roscore)(ros2用ros2 run)
rosrun example example_node //example是功能包名称,example_node是可执行文件的名字
11.设置一个ros循环
//ros
ros::Rate rate(10); //设置休眠频率为10hz
while(ros::ok()) //ros::ok()可判断ros节点运行的状态
{
std::cout<<"hello ros!"<<std::endl;
rate.sleep(); //休眠,让循环时间补足到上面设置的休眠频率
}
//ros2
rclcpp::Rate rate(10); // 设置循环频率为1s/10次
while (rclcpp::ok()) // rclcpp::ok()可用于判断ROS 2节点运行的状态
{
std::cout << "hello ROS 2!" << std::endl;
rate.sleep(); // 休眠,让循环时间补足到上面设置的频率
}
设置好之后需要catkin_make(ros2是colcon build --packages-select <your_package_name>)
这个时候再用roscore(ros2 run)去运行这个程序,就能看到这个循环了
12.创建话题
使用rostopic list(ros2用ros2 topic list),可以查看当前所有ros话题。默认话题包括一个订阅者和一个发布者。
在程序中创建一个话题可用下面的代码:
//ros
#incude<geometry_msgs/Twist.h>
ros::Publisher pub/-cmd = nh.advertise<geometry_msgs::Twist>("cme_vel",10)
//cme_vel是话题名称,可自定,10是消息缓存大小,也可自定
//ros2
#include "geometry_msgs/msg/twist.hpp"
auto pub_cmd = nh->create_publisher<geometry_msgs::msg::Twist>("cmd_vel", 10);
13.给发布者创建需要发布的消息
将下面的代码防御while循环内
//ros1
geometry_msgs::Twist cmd_vel; //移动运动的消息类型
cmd_vel.linear.x=10;
pub_cmd.publish(cmd_vel);
//ros2
auto cmd_vel = std::make_unique<geometry_msgs::msg::Twist>();
msg->linear.x = 10.0
publisher->publish(*msg, header);
再次用rosrun编译程序
这个时候用rostopic list(ros2用ros2 topic list)查看话题列表,就会发现多了一个cmd_vel话题
可以通过rostopic echo /cme_vel打印内容,也可以用rostopic hz /cme_vel查看话题发布的频率
14.创建订阅者
//ros
//下面的代码定义了一个回调函数
void cmdCallback(geometry_msgs::Twist cmdMsg)
{
std::cout<<"vel_x=="<<cmdMsg.linear.x<<std::endl;
}
//下面的代码在主程序内,创建了一个订阅者
ros::Subscriber sub_cmd=nh.subscribe("cmd_vel",10,cmdCallback)
//ros2
void cmdCallback(const geometry_msgs::msg::Twist::SharedPtr cmdMsg)
{
std::cout<<"vel_x=="<<cmdMsg->linear.x<<std::endl;
}
auto sub_cmd = node->create_subscription<geometry_msgs::msg::Twist>("cmd_vel",10,cmdCallback);
这个时候,可以在循环体内加上ros::spinOnce或主程序里加上ros::spin来执行回调函数