【CLion + ROS2】在 clion 中编译调试 ros2 package

目录

  • 0 背景
  • 1. 命令行编译 ros2 package
  • 2. 使用 clion 打开 ros2 工程
  • 3. 使用 clion 编译整个 ros2 工程
    • 3.1 使用 clion 的 external tool 配置 `colcon build`
    • 3.2 开始编译 dev_ws 工程
    • 3.3 编译结果:
  • 4. 调试单独的 ros2 package
    • 4.1 创建 ros2 package 的独立的 colcon build bash 脚本
    • 4.2 创建 clion 中 ros2 package 的独立的 custom build target
    • 4.3 创建 clion 中 对独立的 custom build target 的 **run | debug** configuration
    • 4.4 构建(build) ros2 package
    • 4.5 调试(debug)ros2 package
  • & 参考


0 背景

最近学习 ros2 的 carla-ros-bridge 代码,发现代码中没有顶层 CMakeLists.txt,这种情况下,clion 无法构建 ros2 工程,从而无法编译调试 ros2 package 或者工程,在浏览了一些网页寻找解决方法之后,发现 链接1,2,3 中给出了很好的指导步骤,这篇文章就是用来记录自己操作时的一点心得。

文章结构很大程度上借鉴了链接 1 和 3(clion 官方教程)。如有侵权请告知。


1. 命令行编译 ros2 package

命令行或clion命令和中编译 dev_ws

colcon build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja# 选项:-DCMAKE_EXPORT_COMPILE_COMMANDS=ON,用于生成 
# In order to be able to open a ROS2 workspace in CLion, we will generate a JSON compilation database using the CMAKE_EXPORT_COMPILE_COMMANDS CMake flag.# 如果没有 Ninja,sudo 安装
sudo apt install ninja-build

当前项目目录结构:

dev_ws
└── src├── cpp_pubsub│   ├── cmake_commands.bat│   ├── CMakeLists.txt│   ├── include│   │   └── cpp_pubsub│   ├── package.xml│   └── src│       ├── publisher_member_function.cpp│       └── subscriber_member_function.cpp└── cpp_srvcli├── cmake_commands.bat├── CMakeLists.txt├── include│   └── cpp_srvcli├── package.xml└── src├── add_two_ints_client.cpp└── add_two_ints_server.cpp10 directories, 10 files

结果文件如下:

jacob@jacob-xx15:~/Work_ROS/ros2_study_ws/dev_ws$ tree . -L 2
.
├── build
│   ├── COLCON_IGNORE
│   ├── compile_commands.json  # -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 生成的代码
│   ├── cpp_pubsub
│   └── cpp_srvcli
├── install
│   ├── ..
│   ├── cpp_pubsub
│   ├── cpp_srvcli
│   ├── ..
├── log
│   ├── build_2023-08-14_19-26-37
│   ├── COLCON_IGNORE
│   ├── latest -> latest_build
│   └── latest_build -> build_2023-08-14_19-26-37
└── src├── cpp_pubsub└── cpp_srvcli13 directories, 14 files

生成的 .json 文件如下:

[
{"directory": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/build/cpp_pubsub","command": "/usr/bin/c++  -DDEFAULT_RMW_IMPLEMENTATION=rmw_fastrtps_cpp -DRCUTILS_ENABLE_FAULT_INJECTION -DSPDLOG_COMPILED_LIB -isystem /opt/ros/foxy/include    -Wall -Wextra -Wpedantic -std=gnu++14 -o CMakeFiles/listener.dir/src/subscriber_member_function.cpp.o -c /home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_pubsub/src/subscriber_member_function.cpp","file": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_pubsub/src/subscriber_member_function.cpp"
},{"directory": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/build/cpp_pubsub","command": "/usr/bin/c++  -DDEFAULT_RMW_IMPLEMENTATION=rmw_fastrtps_cpp -DRCUTILS_ENABLE_FAULT_INJECTION -DSPDLOG_COMPILED_LIB -isystem /opt/ros/foxy/include    -Wall -Wextra -Wpedantic -std=gnu++14 -o CMakeFiles/talker.dir/src/publisher_member_function.cpp.o -c /home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_pubsub/src/publisher_member_function.cpp","file": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_pubsub/src/publisher_member_function.cpp"
},{"directory": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/build/cpp_srvcli","command": "/usr/bin/c++  -DDEFAULT_RMW_IMPLEMENTATION=rmw_fastrtps_cpp -DRCUTILS_ENABLE_FAULT_INJECTION -DSPDLOG_COMPILED_LIB -isystem /opt/ros/foxy/include    -Wall -Wextra -Wpedantic -std=gnu++14 -o CMakeFiles/client.dir/src/add_two_ints_client.cpp.o -c /home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_srvcli/src/add_two_ints_client.cpp","file": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_srvcli/src/add_two_ints_client.cpp"
},{"directory": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/build/cpp_srvcli","command": "/usr/bin/c++  -DDEFAULT_RMW_IMPLEMENTATION=rmw_fastrtps_cpp -DRCUTILS_ENABLE_FAULT_INJECTION -DSPDLOG_COMPILED_LIB -isystem /opt/ros/foxy/include    -Wall -Wextra -Wpedantic -std=gnu++14 -o CMakeFiles/server.dir/src/add_two_ints_server.cpp.o -c /home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_srvcli/src/add_two_ints_server.cpp","file": "/home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_srvcli/src/add_two_ints_server.cpp"
}
]

2. 使用 clion 打开 ros2 工程

  1. 在 1 中已经生成了 compile_commands.json,使用 clion 将其作为项目打开(这个文件有点像 toplevel CMakeLists.txt)。
  2. 修改项目 root 目录。

此时 clion 还不能 build | run | debug dev_ws 工程的代码。


3. 使用 clion 编译整个 ros2 工程

大致步骤:

  1. 使用 clion 的 external tool 配置 colcon build
  2. 编译 dev_ws 工程

3.1 使用 clion 的 external tool 配置 colcon build

选择 Settings | Tools | External Tools (或者 shift x 2) 使用 + 添加一个新的 external tool,配置如下:
在这里插入图片描述

3.2 开始编译 dev_ws 工程

使用 tool bar 或者 shift x 2 (external tool),开始编译 dev_ws 工程。
在这里插入图片描述
在这里插入图片描述

3.3 编译结果:

可以使用 红框中的图标进行 rebuild。

需要 reload compilation database

在这里插入图片描述

其实这一步也是为了生成 compile_commands.json,做完这一步之后可以跳至 2。

编译完整个 ros2 dev_ws 工程之后,是无法调试单独的 ros2 package 的,需要对每一个 ros2 package 进行配置,从而进行调试。


4. 调试单独的 ros2 package

大致步骤:

  1. 创建 ros2 package 的独立的 colcon build bash 脚本。
  2. 创建 clion 中 ros2 package 的独立的 custom build target。
  3. 创建 clion 中 对独立的 custom build target 的 run | debug configuration。
  4. 构建(build) ros2 package。
  5. 调试(debug)ros2 package。

4.1 创建 ros2 package 的独立的 colcon build bash 脚本

cpp_pubsub 目录下,创建 cmake_commands.bat

jacob@jacob-xx15:~/Work_ROS/ros2_study_ws/dev_ws/src/cpp_pubsub$ tree
.
├── cmake_commands.bat  # 这玩意
├── CMakeLists.txt
├── include
│   └── cpp_pubsub
├── package.xml
└── src├── publisher_member_function.cpp└── subscriber_member_function.cpp3 directories, 5 files

编写 pubsub package 的 cmake_commands.bat,其他 package 可以参考这个来写。
第一行:构建命令。
第二行:编译命令。
第三行:安装命令。

/usr/bin/cmake /home/jacob/Work_ROS/ros2_study_ws/dev_ws/src/cpp_pubsub -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja -DCMAKE_INSTALL_PREFIX=/home/jacob/Work_ROS/ros2_study_ws/dev_ws/install/cpp_pubsub
/usr/bin/cmake --build /home/jacob/Work_ROS/ros2_study_ws/dev_ws/build/cpp_pubsub -- -j8 -l8
/usr/bin/cmake --install /home/jacob/Work_ROS/ros2_study_ws/dev_ws/build/cpp_pubsub

4.2 创建 clion 中 ros2 package 的独立的 custom build target

  1. 在clion 中打开 custom build targets 窗口(shift x 2 输入 custom build targets)。
  2. 按照截图流程进行配置(edit tool 中的 cmake_commands.bat 就是步骤1中创建的文件)。
    在这里插入图片描述

4.3 创建 clion 中 对独立的 custom build target 的 run | debug configuration

按照截图流程进行操作
其中 5 中的 target 就是 步骤 2 中创建的 custom build target for pubsub package
如果 6 中有 build 文件夹,可以手动清除。
在这里插入图片描述

4.4 构建(build) ros2 package

可以先删除 dev_ws/build/cpp_pubsub/ 目录中所有文件,在用 clion 进行编译之前。
按照截图进行 pubsub package 的编译。
在这里插入图片描述
编译结果:

4.5 调试(debug)ros2 package

由于代码的特殊信,当前 package 包含两个可执行程序 pub(talker),sub(listener)。要调试两者的功能时,需要按截图操作。
如 2 中所示,需要为 pub,sub 分别创建调试配置,在 5 中选择 dev_ws/build/cpp_pubsub 可执行程序(talker,listener)。
在这里插入图片描述
调试结果:pub:
在这里插入图片描述
调试结果:sub:
在这里插入图片描述


& 参考

链接1:clion ros2 代码 build run debug编译运行断点调试
链接2:搭建ROS2 & CLion开发环境
链接3:ROS2 setup tutorial

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

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

相关文章

【Git】版本控制器详解之git的概念和基本使用

版本控制器git 初始Gitgit的安装git的基本使用初始化本地仓库配置本地仓库三区协作添加---add修改文件--status|diff版本回退--reset撤销修改删除文件 初始Git 为了能够更⽅便我们管理不同版本的⽂件,便有了版本控制器。所谓的版本控制器,就是⼀个可以记…

基于ssm+vue的新能源汽车在线租赁管理系统源码和论文PPT

基于ssmvue的新能源汽车在线租赁管理系统源码和论文PPT010 开发环境: 开发工具:idea 数据库mysql5.7(mysql5.7最佳) 数据库链接工具:navcat,小海豚等 开发技术:java ssm tomcat8.5 摘 要 随着科学技术的飞速发展&#xff0…

Ajax及前端工程化

Ajax:异步的js与xml。 作用: 1、通过ajax给服务器发送数据,并获得其响应的数据。 2、可以在不更新整个网页的情况下,与服务器交换数据并更新部分网页的技术。 一、同步与异步 二、原生Ajax 1、准备数据地址 2、创建XMLHttpReq…

SCSS的基本用法

1、声明变量 $ 声明变量的符号 $ 下面这张图左半部分是scss的语法,右半部分是编译后的css。(整篇文章皆是如此) 2、默认变量 !default sass 的默认变量仅需要在值后面加上 !default 即可。 如果分配给变量的值后面添加了 !default 标志…

Qt 杂项(Qwt、样式等)

Qt隐藏窗口边框 this->setWindowFlags(Qt::FramelessWindowHint);Qt模态框 this->setWindowModality(Qt::ApplicationModal);QLable隐藏border 代码中设置 lable->setStyleSheet("border:0px");或者UI中直接设置样式:“border:0px” Qwt开源…

JS实现树形结构、一维数组以及map之间的转换

const treeData[ {id:1, name:中国, children:[ {id:11,name:河南省,children:[{id:111,name:南阳市,children:[{id:1111,name:淅川县,children:null}]},{id:112,name:郑州市,children:[{id:1121,name:中牟县,children:null}]}] }, {id:22,name:广东省,children:[{id:221,name:…

c++中的多态

文章目录 1.多态的概念1.1概念 2.多态的定义及实现2.1多态的构成条件2.2虚函数2.3虚函数的重写2.4 C11 override 和 final2.5 重载、覆盖(重写)、隐藏(重定义)的对比 3. 抽象类3.1概念3.2接口继承和实现继承 4.多态的原理4.1虚函数表4.2多态原理分析4.3 动态绑定与静态绑定 5.单…

学习笔记整理-面向对象-03-构造函数

一、构造函数 1. 用new调用函数的四步走 new 函数();JS规定,使用new操作符调用函数会进行"四步走": 函数体内会自动创建出一个空白对象函数的上下文(this)会指向这个对象函数体内的语句会执行函数会自动返回上下文对象,即使函数没…

HDMI接口的PCB布局布线要求

高清多媒体接口(High Definition Multimedia Interface),简称:HDMI,是一种全数字化视频和声音发送接口,可以发送未压缩的音频及视频信号。随着技术的不断提升,HDMI的传输速率也不断的提升&#…

brew+nginx配置静态文件服务器

背景 一下子闲下来了,了解的我的人都知道我闲不下来。于是,我在思考COS之后,决定自己整一个本地的OSS,实现静态文件的访问。那么,首屈一指的就是我很熟的nginx。也算是个小复习吧,复习一下nginx代理静态文…

解决生成式AI落地之困,亚马逊云科技提供完整解决方案

生成式AI技术无疑是当前最大的时代想象力之一。 资本、创业者、普通人都在涌入生成式AI里去一探究竟:“百模大战”连夜打响,融资规模连创新高,各种消费类产品概念不断涌现……根据Bloomberg Intelligence 的报告,2022年生成式AI 市…

文件操作/IO

文件 文件是一种在硬盘上存储数据的方式,操作系统帮我们把硬盘的一些细节都封装起来了,程序员只需要了解文件相关的接口即可,相当于操作文件就是间接的操作硬盘了 硬盘用来存储数据,和内存相比硬盘的存储空间更大,访问…

使用FTP文件传输协议的潜在风险

数据(事实,数字,价值)是当今业务运行的核心要素。但是,如果数据没有得到有效的存储和传输,它们就会成为阻碍业务发展的障碍。如果企业不能及时地把数据送到合适的地方,就会造成严重的经济损失。…

【Linux】Shell脚本之流程控制语句 if判断、for循环、while循环、case循环判断 + 实战详解[⭐建议收藏!!⭐]

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

.bit域名调研

.bit域名研究 问题: .bit域名和ENS域名的相同点?不同点?有什么关系? .bit的定义 .bit 是基于区块链的,开源的,跨链去中心化账户系统.bit 提供了以 .bit 为后缀的全局唯一的命名体系,可用于加密…

安全第二次

一&#xff0c;iframe <iframe>标签用于在网页里面嵌入其他网页。 1&#xff0c;sandbox属性 如果嵌入的网页是其他网站的页面&#xff0c;因不了解对方会执行什么操作&#xff0c;因此就存在安全风险。为了限制<iframe>的风险&#xff0c;HTML 提供了sandb…

分布式应用:Zabbix监控MariaDB

目录 一、理论 1.Zabbix监控MariaDB 二、实验 1.Zabbix监控MariaDB 一、理论 1.Zabbix监控MariaDB &#xff08;1&#xff09;环境 zabbix服务端&#xff1a;192.168.204.214 zabbix客户端&#xff1a;192.168.204.215 &#xff08;2&#xff09;MareaDB安装 安装 za…

做海外游戏推广有哪些条件?

做海外游戏推广需要充分准备和一系列条件的支持。以下是一些关键条件&#xff1a; 市场调研和策略制定&#xff1a;了解目标市场的文化、玩家偏好、竞争格局等是必要的。根据调研结果制定适合的推广策略。 本地化&#xff1a;将游戏内容、界面、语言、货币等进行本地化&#…

使用ip2region获取客户端地区

目录 从gitee拉取ip2region.xdb资源文件 写测试类 注意要写对资源路径 本地测试结果 ​编辑 远端测试结果 从gitee拉取ip2region.xdb资源文件 git clone https://gitee.com/lionsoul/ip2region.git 将xdb放入resources资源文件夹 引入依赖 <dependency><groupId&…

[HDLBits] Exams/m2014 q4d

Implement the following circuit: module top_module (input clk,input in, output out);always(posedge clk) beginout<out^in;end endmodule直接写out^in就行