本系列教程作者:小鱼
公众号:鱼香ROS
QQ交流群:139707339
教学视频地址:小鱼的B站
完整文档地址:鱼香ROS官网
版权声明:如非允许禁止转载与商业用途。

讲这一节的原因,是小鱼发现很多小伙伴在后期学习和使用ROS2时候,遇到各种依赖找不到的问题,不知如何解决。其实就是对C++依赖查找机制不熟悉,本节就是帮你打牢基础。

1.动态链接库

动态链接库介绍

引用文章:

  • gcc/g++ 链接库的编译与链接_surgewong的博客-CSDN博客_g++ 使用动态库

程序编译一般需要经预处理、编译、汇编和链接几个步骤。在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为“库”文件。在链接步骤中,链接器将从库文件取得所需的代码,复制到生成的可执行文件中,这种库称为静态(链接)库,其特点是可执行文件中包含了库代码的一份完整拷贝,缺点是被多次使用就会多份冗余拷贝。还有一种库,就是程序在开始运行后调用库函数时才被载入,这种库独立于现有的程序,其本身不可执行,但包含着程序需要调用的一些函数,这种库称为动态(链接)库(Dynamic Link Library)。

在widows平台下,静态链接库是.lib文件,动态库文件是.dll文件。在linux平台下,静态链接库是.a文件,动态链接库是.so文件。

2. 用g++编译ROS2的C++节点

2.1 编写节点

编写一个ROS2的C++节点非常简单,只需三行代码即可完成。

打开终端,创建chapt2/basic目录,用VSCODE打开d2lros2目录。

mkdir -p d2lros2/chapt2/basic/
code d2lros2Copy to clipboardErrorCopied

接着在左侧chapt2上新建first_node.cpp,然后在first_node.cpp中输入下面的代码。

// 包含rclcpp头文件,如果Vscode显示红色的波浪线也没关系
// 我们只是把VsCode当记事本而已,谁会在意记事本对代码的看法呢,不是吗?
#include "rclcpp/rclcpp.hpp"int main(int argc, char **argv)
{// 调用rclcpp的初始化函数rclcpp::init(argc, argv);// 调用rclcpp的循环运行我们创建的first_node节点rclcpp::spin(std::make_shared<rclcpp::Node>("first_node"));return 0;
}Copy to clipboardErrorCopied

2.2 编译

接着我们使用g++来编译first_node节点。正常的话一定会报错。

g++ first_ros2_node.cpp Copy to clipboardErrorCopied

报错内容如下:

root@490925f19143:~/d2lros2/d2lros2/chapt2/basic# g++ first_ros2_node.cpp
first_ros2_node.cpp:3:10: fatal error: rclcpp/rclcpp.hpp: No such file or directory3 | #include "rclcpp/rclcpp.hpp"|          ^~~~~~~~~~~~~~~~~~~
compilation terminated.Copy to clipboardErrorCopied

一定要记住这个错误 No such file or directory,这将是你接下来机器人学习工作生涯中最常见的错误之一。

接着小鱼来说说错误原因和解决方案。

原因我们在代码里包含了"rclcpp/rclcpp.hpp"头文件,但是g++找不到这个头文件,解决方法就是告诉g++这个头文件的目录。

首先我们要找到这个头文件在哪里,这个头文件是ROS2的客户端库,其地址肯定在ROS2的安装目录下,即/opt/ros/humble/include/rclcpp

cd /opt/ros/humble/include/rclcpp
ls rclcpp/* | grep rclcpp.hCopy to clipboardErrorCopied

ls指令列出命令 | grep rclcpp.h 是对列出的结果进行过滤,只显示包含rclcpp.h的行。

使用上面的指令,可以看到这个文件确实在这里。

接着我们可以用-I(大写i)来为g++指定这个目录,然后再次运行,你会发现依然报错

g++ first_ros2_node.cpp -I /opt/ros/humble/include/rclcpp/ Copy to clipboardErrorCopied

报错如下

root@490925f19143:~/d2lros2/d2lros2/chapt2/basic# g++ first_ros2_node.cpp -I/opt/ros/humble/include/rclcpp/
In file included from /opt/ros/humble/include/rclcpp/rclcpp/executors/multi_threaded_executor.hpp:25,from /opt/ros/humble/include/rclcpp/rclcpp/executors.hpp:21,from /opt/ros/humble/include/rclcpp/rclcpp/rclcpp.hpp:155,from first_ros2_node.cpp:3:
/opt/ros/humble/include/rclcpp/rclcpp/executor.hpp:30:10: fatal error: rcl/guard_condition.h: No such file or directory30 | #include "rcl/guard_condition.h"|          ^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.Copy to clipboardErrorCopied

虽然错误有些不一样,但是核心的文件都是一样的,你应该都看到了No such file or directory这个问题,并且错误信息还提示你了,在/opt/ros/humble/include/rclcpp/rclcpp/executors/multi_threaded_executor.hpp:25这个位置,包含了rcl/guard_condition.h发现找不到这个头文件。

既然错误一样,那么解决方案也是相同的,rcl/guard_condition.h所在的路径是/opt/ros/humble/include/rcl/我们再次指定后运行。

g++ first_ros2_node.cpp -I /opt/ros/humble/include/rclcpp/ -I /opt/ros/humble/include/rcl/Copy to clipboardErrorCopied

你会发现还是相同错误,因为头文件的包含是类似于套娃形式的,一层层加下去,总有终点,直到小鱼最终这个样子

g++ first_ros2_node.cpp \
-I/opt/ros/humble/include/rclcpp/ \
-I /opt/ros/humble/include/rcl/ \
-I /opt/ros/humble/include/rcutils/ \
-I /opt/ros/humble/include/rmw \
-I /opt/ros/humble/include/rcl_yaml_param_parser/ \
-I /opt/ros/humble/include/rosidl_runtime_c \
-I /opt/ros/humble/include/rosidl_typesupport_interface \
-I /opt/ros/humble/include/rcpputils \
-I /opt/ros/humble/include/builtin_interfaces \
-I /opt/ros/humble/include/rosidl_runtime_cpp \
-I /opt/ros/humble/include/tracetools \
-I /opt/ros/humble/include/rcl_interfaces \
-I /opt/ros/humble/include/libstatistics_collector \
-I /opt/ros/humble/include/statistics_msgsCopy to clipboardErrorCopied

运行完上面这段代码,你会发现报的错误变了。

/usr/bin/ld: /tmp/ccoA8hho.o: in function `main':
first_ros2_node.cpp:(.text+0x37): undefined reference to `rcutils_get_default_allocator'
/usr/bin/ld: first_ros2_node.cpp:(.text+0x5c): undefined reference to `rclcpp::InitOptions::InitOptions(rcutils_allocator_s)'
/usr/bin/ld: first_ros2_node.cpp:(.text+0x7d): undefined reference to `rclcpp::init(int, char const* const*, rclcpp::InitOptions const&, rclcpp::SignalHandlerOptions)'
/usr/bin/ld: first_ros2_node.cpp:(.text+0x89): undefined reference to `rclcpp::InitOptions::~InitOptions()'
/usr/bin/ld: first_ros2_node.cpp:(.text+0xb1): undefined reference to `rclcpp::spin(std::shared_ptr<rclcpp::Node>)'
/usr/bin/ld: first_ros2_node.cpp:(.text+0xe9): undefined reference to `rclcpp::InitOptions::~InitOptions()'
/usr/bin/ld: /tmp/ccoA8hho.o: in function `void __gnu_cxx::new_allocator<rclcpp::Node>::construct<rclcpp::Node, char const (&) [11]>(rclcpp::Node*, char const (&) [11])':
first_ros2_node.cpp:(.text._ZN9__gnu_cxx13new_allocatorIN6rclcpp4NodeEE9constructIS2_JRA11_KcEEEvPT_DpOT0_[_ZN9__gnu_cxx13new_allocatorIN6rclcpp4NodeEE9constructIS2_JRA11_KcEEEvPT_DpOT0_]+0x86): undefined reference to `rcutils_get_default_allocator'
/usr/bin/ld: first_ros2_node.cpp:(.text._ZN9__gnu_cxx13new_allocatorIN6rclcpp4NodeEE9constructIS2_JRA11_KcEEEvPT_DpOT0_[_ZN9__gnu_cxx13new_allocatorIN6rclcpp4NodeEE9constructIS2_JRA11_KcEEEvPT_DpOT0_]+0xb7): undefined reference to `rclcpp::NodeOptions::NodeOptions(rcutils_allocator_s)'
/usr/bin/ld: first_ros2_node.cpp:(.text._ZN9__gnu_cxx13new_allocatorIN6rclcpp4NodeEE9constructIS2_JRA11_KcEEEvPT_DpOT0_[_ZN9__gnu_cxx13new_allocatorIN6rclcpp4NodeEE9constructIS2_JRA11_KcEEEvPT_DpOT0_]+0xe7): undefined reference to `rclcpp::Node::Node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::NodeOptions const&)'
collect2: error: ld returned 1 exit statusCopy to clipboardErrorCopied

请记住上面错误中的undefined reference to xxxxx,这将是你接下来机器人学习工作生涯中另一个最常见的错误。

原因在于g++找不到库文件,解决方法就是我们帮助它定位到库文件的位置,并通过-L参数指定库目录,-l(小写L)指定库的名字。

ROS2相关的库的地址都在/opt/ros/humble/lib下,你可以使用下面的指定看到rclcpp的动态链接库。

ls /opt/ros/humble/lib | grep rclcppCopy to clipboardErrorCopied

指定库目录和使用的库后的终极命令

g++ first_ros2_node.cpp \
-I/opt/ros/humble/include/rclcpp/ \
-I /opt/ros/humble/include/rcl/ \
-I /opt/ros/humble/include/rcutils/ \
-I /opt/ros/humble/include/rmw \
-I /opt/ros/humble/include/rcl_yaml_param_parser/ \
-I /opt/ros/humble/include/rosidl_runtime_c \
-I /opt/ros/humble/include/rosidl_typesupport_interface \
-I /opt/ros/humble/include/rcpputils \
-I /opt/ros/humble/include/builtin_interfaces \
-I /opt/ros/humble/include/rosidl_runtime_cpp \
-I /opt/ros/humble/include/tracetools \
-I /opt/ros/humble/include/rcl_interfaces \
-I /opt/ros/humble/include/libstatistics_collector \
-I /opt/ros/humble/include/statistics_msgs \
-L /opt/ros/humble/lib/ \
-lrclcpp -lrcutilsCopy to clipboardErrorCopied

运行后,你会发现没有任何报错了,但是在当前目录下多出了一个a.out,这个就是我们将上面的代码编译和链接完库之后得出的可执行文件。

如果你觉得a.out不好听,可以在g++指定后添加 -o 名字 ,比如 -o first_node

3. 运行节点

执行代码

./a.outCopy to clipboardErrorCopied

打开新的终端,使用ros2 node list查看正在运行的节点,是否有first_node

ROS2前置基础教程 | 小鱼教你用g++编译ROS2节点相关推荐

  1. Python培训基础教程都教哪些

    根据相关数据统计,目前学习Python技术的同学大多数是零基础,都是从其他行业转型来学习的,那么Python培训基础教程都教哪些呢?好不好学呢?来看看下面的详细介绍. Python培训基础教程都教哪些 ...

  2. keyshot渲染图文教程_KeyShot渲染基础教程,教你五个步骤实现焦散线效果

    KeyShot渲染基础教程,教你五个步骤实现焦散线效果 想要渲染效果好,逼真,KeyShot渲染技巧不可少,品索搜集最新最权威KeyShot渲染教程,只为帮助广大KeyShot渲染爱好学习者们!想要有 ...

  3. 【ppt基础教程】教你用PowerPoint轻松实现板书效果

    转载者: 草原ppt课件 搜索: ppt基础教程 教你用PowerPoint轻松实现板书效果 教你用PowerPoint轻松实现板书效果!一个很不错的ppt基础教程,分享给你! 方法很简单,既不用那么 ...

  4. DirectX12(D3D12)基础教程(外篇一)——编译Assimp

    目录 1.前言 2.Assimp库简介 3.编译Assimp库的准备工作 4.下载Assimp源码并编译 1.前言   D3D12系列教程因为我转移精力学习Nodejs.VueJs等技能,暂时中断了一 ...

  5. python基础教程:教你如何自学python入门到精通

    python自学网www.pythonzxw.com/thread-371-1-1.html 其实python非常适合初学者入门.相比较其他不少主流编程语言,有更好的可读性,因此上手相对容易.自带的各 ...

  6. 计算机基础教程.doc,计算机基础教程-教案.doc

    计算机基础教程-教案 教 案 2014 -2015 学年第 1 学期 教学单位 所属专业 课程名称 计算机基础 课程性质 公共基础课程 授课班级 授课教师(校内) (企业) 2014年 9 月 20 ...

  7. DirectX12(D3D12)基础教程(二十二) ——HDR IBL 等距柱面环境光源加载和解算及 GS 一次性渲染到 CubeMap

    前序文章目录 DirectX12(D3D12)基础教程(一)--基础教程 DirectX12(D3D12)基础教程(二)--理解根签名.初识显存管理和加载纹理.理解资源屏障 DirectX12(D3D ...

  8. ps入门教程零基础视频 小鱼老师美工PS教程

    多媒体设计就业前景非常好,专业网站美工设计,很赚钱的,同时photoshop学的好的话还可以同时作平面设计,在广告公司很吃香,跟着小鱼老师一起来学美工ps教程! ps课程目标 本套PS教程主要教PS软 ...

  9. javascript技术教程蔡敏_程序员都必掌握的前端教程之JavaScript基础教程(上)

    阅读本文约需要10分钟,您可以先关注我们,避免下次无法找到. 本篇文章成哥继续带大家来学习前端教程之JavaScript,网页的动态事件基本上都是靠它来实现的.下面我们就一起来学习内容吧! 01 Ja ...

  10. php mvc教程 文档,PHP培训教程教你快速打造PHP MVC框架[PHP基础教程]

    PHP培训教程教你快速打造PHP MVC框架[PHP基础教程] 简介 MVC框架在现在的开发中相当流行,不论你使用的是JAVA,C#,PHP或者IOS,你肯定都会选择一款框架.虽然不能保证100%的开 ...

最新文章

  1. C++程序设计:原理与实践(进阶篇)16.1 标准库算法
  2. 看完这些、你能体会到半导体与电路集成的伟大了吗?
  3. 使用jQuery更改下拉列表的选定值
  4. java shiro 访问频率_java shiro配置记住密码功能 RememberMe
  5. 【maven3学习之三】maven构建一个简单的Hello World
  6. Exchange 2010 DAG转载
  7. Thread类和Runnable接口
  8. linux重启后版本变了,linux – 重启后如何使设备映射保持不变?
  9. 【金融申请评分卡】数据准备 - 缺失值数据清洗
  10. mysql锁优化_mysql锁以及配置优化
  11. numpy中的broadcast
  12. NFC技术:Android中的NFC技术
  13. jdk的官方下载地址
  14. 2015年数模A题太阳影子定位学习笔记
  15. 前端网页设计必逛的六个宝藏网站(非常值得收藏)
  16. python docx官网_Python操作docx文档
  17. 【Windows】之电脑之间共享文件(亲测可行)
  18. 批量将txt文件转为csv文件
  19. 木讷的程序员需要知道的事情 (四)
  20. Django框架学习记录(3)

热门文章

  1. 数学与计算机专业的论文,数学与计算机论文
  2. Python-实现九宫格
  3. 为什么webview中网页字体大小跟样式设置的不同?
  4. java opts tomcat,tomcat JAVA_OPTS配备
  5. 图像scale与相机参数_摄像头参数测试指导分析解析
  6. 2020-08-18
  7. 苹果电脑的文件怎么复制到移动硬盘,macbook文件怎么拷贝到移动硬盘
  8. 一年级下册计算机教学计划,最新人教版一年级下册教学计划
  9. 天翎myAppsSetup_V4.4.sp10系统结构图
  10. 【苹果手机登录163邮箱】