【ROS2 入门】ROS2 创建工作空间

        大家好,我是虎哥,从今天开始,我将花一段时间,开始将自己从ROS1切换到ROS2,在上几篇中,我们一起了解ROS 2中很多基础概念,从今天开始我们逐步就开始利用ROS2的特性进行开发编程了。

        工作区(workspace)是包含ROS 2包的目录。在使用ROS 2之前,有必要在你计划使用的终端中source ROS 2安装工作空间。这使ROS 2的软件包可在该终端中使用。你还可以选择采购“覆盖”——一个辅助工作区,在那里你可以添加新的包,而不会干扰你已经source的现有ROS 2工作区”。

1.1 Source ROS 2 environment

source /opt/ros/eloquent/setup.bash

1.2 创建工作目录

最佳习惯是为每个新工作区创建一个新目录。名称不重要,但让它指示工作区的用途是有帮助的。让我们为“开发工作区”选择目录名dev_ws:

mkdir -p ~/dev_ws/src
cd ~/dev_ws/src

另一个最佳习惯是将工作区中的任何包放入src目录。上面的代码在dev_ws中创建一个src目录,然后CD到它。

1.3 clone 一个简单的测试工程

在clone之前,请确保您仍在dev_ws/src目录中。在的之后部分中,你将创建自己的包,但目前你将使用现有包练习如何将工作区放在一起。我们使用的现有软件包来自ros_tutorials存储库(repo)。如果您阅读了“初学者:CLI工具”教程,您将熟悉本回购中的一个软件包turtlesim。

入口:GitHub - ros/ros_tutorials: Code used in tutorials found on ROS wiki

 请注意目录列表上方左侧的“分支”下拉列表。克隆此repo时,添加-b参数,后跟与ROS2发行版对应的分支。

在dev_ws/src目录中,为正在使用的发行版运行以下命令:

git clone https://github.com/ros/ros_tutorials.git -b eloquent-devel

 我们可以进入这个包的目录,看到所有下载的子包

         前三个包被忽略;turtlesim是本回购协议中唯一实际的ROS 2包。现在,你已经用一个示例包填充了工作空间,但它还不是一个功能齐全的工作空间。需要首先解决依赖关系并构建工作区。

1.4 解决依赖关系(Resolve dependencies)

        在构建工作区之前,您需要解决包依赖关系。可能已经拥有所有依赖项,如果不希望构建在长时间等待后因为缺少依赖项而失败,最好做法是在每次检查依赖项。

从工作区的根目录(dev_ws)运行以下命令:

cd ~/dev_ws
rosdep install -i --from-path src --rosdistro eloquent -y

如果出现如下错误提示:

 

继续使用之前安装的时候提示使用的小鱼一键安装。

 

 完成后继续之前的建立依赖的命令,就可以成功了。

 如果您已经拥有所有依赖项,控制台将返回:

#All required rosdeps installed successfully

包在package.xml文件中声明其依赖关系。上面命令遍历这些声明并安装缺少的声明。后续可以在另一个教程中了解更多有关rosdep的信息。

1.5 使用colcon 编译工程

从工作区的根目录(dev_ws),现在可以使用以下命令构建包:

#进入根目录
cd ~/dev_ws
#编译
colcon build

编译过程中会有提示,因为之前我们安装过这个工程,现在编译,会有提示注意,这也是和之前ROS1有区别的地方,ROS2中可以使用覆盖的概念。

1、colcon build还可以带一些参数,这个做个分享:

  • --packages-up-to 只编译指定包,其所有依赖项,但不构建整个工作区(节省时间)

  • --symlink-install避免每次调整python脚本时都需要重新构建

  • --event-handlers console_direct+ 显示生成时的控制台输出(否则可以在“log”目录中找到)

构建完成后,在工作区根目录(~/dev_ws)中输入ls,您将看到colcon已经创建了新目录:

 install 目录是工作区的安装文件所在的目录,您可以使用它来源代码覆盖。这个和ROS1中有很大区别。

1.6 Source 环境变量覆盖(the overlay)

注意:在Source 之前,打开一个新的终端,与构建工作区的终端分开,这一点非常重要。在构建的同一终端中Source 覆盖层,或者同样在Source 覆盖层的地方构建覆盖层,可能会产生复杂的问题。

在新终端中,将您的主ROS 2环境作为“底层”,以便可以在其上构建覆盖层:

#新终端,不是构建终端 设置环境变量
source /opt/ros/eloquent/setup.bash
#进入工作根目录
cd ~/dev_ws
#执行覆盖
. install/local_setup.bash

执行local_setup只会将系统中可用的包添加到您的环境中。local_setup提供了允许使用这两个工作空间。因此,像刚才所做的那样,获取主ROS 2安装的设置,然后获取dev_ws覆盖的local_setup,与获取dev_w的设置是一样的,因为这包括创建它的底层环境。如果有很多个,交叉覆盖,就可能会出现一些问题。

现在,你可以在这个终端中运行你刚才编译的包了:

ros2 run turtlesim turtlesim_node

 但是,你怎么能知道这是正在运行的包,而不是系统自带的那个包呢?

你可以修改叠自己包中的turtlesim,以便可以看到效果:

 可以看到本地的优先于系统的。

我是在启动文件最开始增加了一句打印:

cd ~/dev_ws/src/ros_tutorials/turtlesim/src

vim turtlesim.cpp

 

1.7 官方提供的修改窗口标题的方法验证

上面为了验证,谁的优先,我自己增加了打印,官方提供的事修改窗口名称的方法,我就一并也分享给大家:

cd ~/dev_ws/src/ros_tutorials/turtlesim/src

 

vim turtle_frame.cpp

 

 重新编译:

#进入根目录
cd ~/dev_ws
#编译
colcon build

完事后,继续再新的终端测试:

我们用新的一个终端,运行系统自带的做对比:

 

以上就是我今天要分享的内容。纠错,疑问,交流: 911946883@qq.com

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
好的,以下是一个简单的 ROS 2 入门示例。 假设你已经安装好了 ROS 2 和相关的依赖包。我们将创建一个简单的 ROS 2 节点,该节点将发布一个名为 `/demo_topic` 的主题,其中包含一个字符串消息。我们还将创建一个订阅该主题的节点。 首先,在终端中创建一个工作空间: ``` mkdir -p ~/ros2_ws/src cd ~/ros2_ws/ colcon build ``` 接下来,创建一个 ROS 2 包: ``` cd ~/ros2_ws/src ros2 pkg create my_demo_pkg --build-type ament_cmake ``` 这将在 `~/ros2_ws/src` 目录下创建一个名为 `my_demo_pkg` 的 ROS 2 包。进入该包的目录: ``` cd my_demo_pkg/ ``` 在 `my_demo_pkg` 目录下创建一个名为 `publisher.cpp` 的 C++ 文件,并将以下代码复制到文件中: ```cpp #include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; class PublisherNode : public rclcpp::Node { public: PublisherNode() : Node("publisher_node") { publisher_ = this->create_publisher<std_msgs::msg::String>("/demo_topic", 10); timer_ = this->create_wall_timer(1s, std::bind(&PublisherNode::timer_callback, this)); } private: void timer_callback() { auto message = std_msgs::msg::String(); message.data = "Hello, ROS 2!"; publisher_->publish(message); } rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; rclcpp::TimerBase::SharedPtr timer_; }; int main(int argc, char **argv) { rclcpp::init(argc, argv); auto node = std::make_shared<PublisherNode>(); rclcpp::spin(node); rclcpp::shutdown(); return 0; } ``` 这个节点将创建一个名为 `/publisher_node` 的节点,并在 `/demo_topic` 主题上发布一个字符串消息。 接下来,在 `my_demo_pkg` 目录下创建一个名为 `subscriber.cpp` 的 C++ 文件,并将以下代码复制到文件中: ```cpp #include "rclcpp/rclcpp.hpp" #include "std_msgs/msg/string.hpp" void callback(const std_msgs::msg::String::SharedPtr msg) { RCLCPP_INFO(rclcpp::get_logger("subscriber_node"), "Received message: '%s'", msg->data.c_str()); } int main(int argc, char **argv) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("subscriber_node"); auto subscriber = node->create_subscription<std_msgs::msg::String>("/demo_topic", 10, callback); rclcpp::spin(node); rclcpp::shutdown(); return 0; } ``` 这个节点将创建一个名为 `/subscriber_node` 的节点,并订阅 `/demo_topic` 主题。当接收到消息时,它将打印消息内容。 现在,我们需要将这两个节点添加到 `CMakeLists.txt` 文件中: ``` add_executable(publisher_node src/publisher.cpp) ament_target_dependencies(publisher_node rclcpp std_msgs) add_executable(subscriber_node src/subscriber.cpp) ament_target_dependencies(subscriber_node rclcpp std_msgs) ``` 最后,编译并运行节点: ``` cd ~/ros2_ws/ colcon build --packages-select my_demo_pkg source install/setup.bash ros2 run my_demo_pkg publisher_node ``` 在另一个终端中运行以下命令: ``` ros2 run my_demo_pkg subscriber_node ``` 现在你应该能够在订阅节点的终端中看到如下输出: ``` [INFO] [subscriber_node]: Received message: 'Hello, ROS 2!' ``` 这就是一个简单的 ROS 2 入门示例。你可以尝试修改代码并探索更多高级功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器人虎哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值