Explorar o código

[feat]:完成第二章基础篇和入门篇

鱼香ROS %!s(int64=3) %!d(string=hai) anos
pai
achega
4d869cb610
Modificáronse 69 ficheiros con 1534 adicións e 22 borrados
  1. 12 12
      docs/_sidebar.md
  2. 2 2
      docs/humble/chapt1/advanced/2.中间件DDS架构.md
  3. 2 0
      docs/humble/chapt1/basic/4.玩转Ubuntu之编程工具.md
  4. 20 1
      docs/humble/chapt1/get_started/3.动手安装ROS2.md
  5. 7 7
      docs/humble/chapt1/get_started/4.ROS2初体验.md
  6. BIN=BIN
      docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124658803.png
  7. BIN=BIN
      docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124701935.png
  8. BIN=BIN
      docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124722852.png
  9. BIN=BIN
      docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124742399.png
  10. BIN=BIN
      docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124845382.png
  11. BIN=BIN
      docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603125332498.png
  12. 11 0
      docs/humble/chapt2/advanced/1.五种不同的方式编写节点.md
  13. 11 0
      docs/humble/chapt2/advanced/2.生命周期节点介绍.md
  14. 11 0
      docs/humble/chapt2/advanced/3.ROS2节点发现机制原理.md
  15. 11 0
      docs/humble/chapt2/advanced/4.Colcon编译原理.md
  16. 11 0
      docs/humble/chapt2/advanced/5.ROS2包运行原理.md
  17. 11 0
      docs/humble/chapt2/advanced/6.ROS2客户端库源码导读.md
  18. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/SouthEast.png
  19. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603130600648.png
  20. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603131959194.png
  21. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603133814964.png
  22. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603135637630.png
  23. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603135717676.png
  24. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603135942917.png
  25. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603143016936.png
  26. BIN=BIN
      docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603145533742.png
  27. 199 0
      docs/humble/chapt2/basic/1.使用g++编译ROS2节点.md
  28. BIN=BIN
      docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/SouthEast.png
  29. BIN=BIN
      docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/image-20220603130600648.png
  30. BIN=BIN
      docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/image-20220603131959194.png
  31. BIN=BIN
      docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/image-20220603133814964.png
  32. BIN=BIN
      docs/humble/chapt2/basic/2.Python打包工具之Setup/imgs/image-20220603154952746.png
  33. 70 0
      docs/humble/chapt2/basic/2.使用make编译ROS2节点.md
  34. BIN=BIN
      docs/humble/chapt2/basic/2.使用make编译ROS2节点/imgs/image-20220603135717676.png
  35. BIN=BIN
      docs/humble/chapt2/basic/2.使用make编译ROS2节点/imgs/image-20220603135942917.png
  36. BIN=BIN
      docs/humble/chapt2/basic/2.使用make编译ROS2节点/imgs/image-20220603161445651.png
  37. 77 0
      docs/humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点.md
  38. BIN=BIN
      docs/humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点/imgs/image-20220603143016936.png
  39. BIN=BIN
      docs/humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点/imgs/image-20220603145533742.png
  40. 81 0
      docs/humble/chapt2/basic/4.CMake依赖查找流程.md
  41. BIN=BIN
      docs/humble/chapt2/basic/4.CMake依赖查找流程/imgs/image-20220603145533742.png
  42. 119 0
      docs/humble/chapt2/basic/5.Python依赖查找流程.md
  43. BIN=BIN
      docs/humble/chapt2/basic/5.Python依赖查找流程/imgs/image-20220603154952746.png
  44. 125 0
      docs/humble/chapt2/basic/6.Python工具之Setup.md
  45. BIN=BIN
      docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/Nodes-TopicandService-16542449255392.gif
  46. BIN=BIN
      docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/Nodes-TopicandService.gif
  47. BIN=BIN
      docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/image-20210915153915430-16542449255391.png
  48. BIN=BIN
      docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/image-20210915153915430.png
  49. 111 0
      docs/humble/chapt2/get_started/1.ROS2节点介绍.md
  50. BIN=BIN
      docs/humble/chapt2/get_started/1.ROS2节点介绍/imgs/Nodes-TopicandService-16542449255392.gif
  51. BIN=BIN
      docs/humble/chapt2/get_started/1.ROS2节点介绍/imgs/image-20210915153915430-16542449255391.png
  52. 148 0
      docs/humble/chapt2/get_started/2.ROS2功能包与工作空间.md
  53. BIN=BIN
      docs/humble/chapt2/get_started/2.功能包与工作空间/imgs/image-20210720102200144.png
  54. BIN=BIN
      docs/humble/chapt2/get_started/2.功能包与工作空间/imgs/image-20210720102349238.png
  55. BIN=BIN
      docs/humble/chapt2/get_started/2.功能包与工作空间/imgs/image-20210915172702101.png
  56. BIN=BIN
      docs/humble/chapt2/get_started/2.节点的家之工作空间/imgs/image-20210720102200144.png
  57. BIN=BIN
      docs/humble/chapt2/get_started/2.节点的家之工作空间/imgs/image-20210720102349238.png
  58. BIN=BIN
      docs/humble/chapt2/get_started/2.节点的家之工作空间/imgs/image-20210915172702101.png
  59. 156 0
      docs/humble/chapt2/get_started/3.ROS2编译器之Colcon.md
  60. BIN=BIN
      docs/humble/chapt2/get_started/3.ROS2编译器之Colcon/imgs/image-20210720211422653.png
  61. BIN=BIN
      docs/humble/chapt2/get_started/3.ROS2编译器之Colcon/imgs/image-20210720211959001.png
  62. 144 0
      docs/humble/chapt2/get_started/4.使用RCLCPP编写节点.md
  63. BIN=BIN
      docs/humble/chapt2/get_started/4.使用RCLCPP编写节点/imgs/image-20220603171631334.png
  64. BIN=BIN
      docs/humble/chapt2/get_started/4.使用RCLCPP编写节点/imgs/image-20220603172524241.png
  65. BIN=BIN
      docs/humble/chapt2/get_started/4.使用RCLCPP编写节点/imgs/image-20220603172729457.png
  66. 140 0
      docs/humble/chapt2/get_started/5.使用RCLPY编写节点.md
  67. BIN=BIN
      docs/humble/chapt2/get_started/5.使用RCLPY编写节点/imgs/image-20220603174606170.png
  68. BIN=BIN
      docs/humble/chapt2/get_started/5.使用RCLPY编写节点/imgs/image-20220603174623023.png
  69. 55 0
      docs/humble/chapt2/章节导读.md

+ 12 - 12
docs/_sidebar.md

@@ -17,7 +17,6 @@
     -  [Launch](humble/codebook/pages/launch.md) 
     -  [网络通讯](humble/codebook/pages/networking.md) 
     -  [功能包](humble/codebook/pages/packages.md) 
-
 - (一)​ROS2入门篇
   - 第 1 章 ROS2介绍与安装
     - [章节导读](humble/chapt1/章节导读.md) 
@@ -36,18 +35,20 @@
       -  [1.ROS2系统架构](humble/chapt1/advanced/1.ROS2系统架构.md) 
       -  [2.中间件DDS架构](humble/chapt1/advanced/2.中间件DDS架构.md) 
   - 第 2 章 ROS2第一个节点
-    - 章节导读
+    - [章节导读](humble/chapt2/章节导读.md) 
     - 基础篇-编程基础
-      - C++编译工具之CMake
-      - Python打包工具之Setup
-      - CMake依赖查找流程
-      - Python依赖查找流程
+      -  [1.使用g++编译ROS2节点](humble/chapt2/basic/1.使用g++编译ROS2节点.md) 
+      -  [2.使用make编译ROS2节点](humble/chapt2/basic/2.使用make编译ROS2节点.md) 
+      -  [3.使用CMakeLists.txt编译ROS2节点](humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点.md) 
+      -  [4.CMake依赖查找流程](humble/chapt2/basic/4.CMake依赖查找流程.md) 
+      -  [5.Python依赖查找流程](humble/chapt2/basic/5.Python依赖查找流程.md) 
+      -  [6.Python工具之Setup](humble/chapt2/basic/6.Python工具之Setup.md) 
     - 入门篇-动手使用ROS2
-      - ROS2节点与工作空间
-      - ROS2编译器之Colcon
-      - ROS2客户端库知多少
-      - 使用RCLCPP编写节点
-      - 使用RCLPY编写节点
+      -  [1.ROS2节点介绍](humble/chapt2/get_started/1.ROS2节点介绍.md) 
+      -  [2.ROS2功能包与工作空间](humble/chapt2/get_started/2.ROS2功能包与工作空间.md) 
+      -  [3.ROS2编译器之Colcon](humble/chapt2/get_started/3.ROS2编译器之Colcon.md) 
+      -  [4.使用RCLCPP编写节点](humble/chapt2/get_started/4.使用RCLCPP编写节点.md) 
+      -  [5.使用RCLPY编写节点](humble/chapt2/get_started/5.使用RCLPY编写节点.md) 
     - 进阶篇-ROS2系统
       - 五种不同的方式编写节点
       - 生命周期节点介绍
@@ -115,7 +116,6 @@
       - RQT插件开发指南
       - 兼容仿真工具-WeBots
       - 兼容仿真工具-Unity
-
 - (二)机器人学篇
   - 第 6 章 运动学基础
     - 章节导读

+ 2 - 2
docs/humble/chapt1/advanced/2.中间件DDS架构.md

@@ -18,7 +18,7 @@
 
 小鱼看完表示
 
-![img](2.中间件DDS架构/imgs/v2-e6dbd2aa59c57d6bda2fcb25d83f1a34_b-16541732577251.png)
+![img](2.中间件DDS架构/imgs/v2-e6dbd2aa59c57d6bda2fcb25d83f1a34_b.png)
 
 
 
@@ -26,7 +26,7 @@
 
 话不多说先上图
 
-![img](2.中间件DDS架构/imgs/v2-471abbce0a08b249637dc603f56dc9cf_b-16541732577252.png)
+![img](2.中间件DDS架构/imgs/v2-471abbce0a08b249637dc603f56dc9cf_b.png)
 
 > ROS/ROS2中间件对比
 >

+ 2 - 0
docs/humble/chapt1/basic/4.玩转Ubuntu之编程工具.md

@@ -88,6 +88,8 @@ sudo apt install g++
 g++ hello_fishros.cpp
 ```
 
+> 如报错请尝试安装:sudo apt-get install build-essential
+
 接着使用`ls`指令,你应该可以看到一个叫做`a.out`的文件。恭喜,现在你可以运行了。
 
 输入下面的指令即可运行

+ 20 - 1
docs/humble/chapt1/get_started/3.动手安装ROS2.md

@@ -95,7 +95,7 @@ echo "source /opt/ros/foxy/setup.bash" >> ~/.bashrc
 
 
 
-## 3.如何出现问题可以这样卸载
+## 3.出现问题可以这样卸载
 
 别的教程肯定不会写这个,不过这招有时候还挺好用,就是麻烦一些哈。
 
@@ -106,6 +106,25 @@ sudo apt autoremove
 
 
 
+## 4.ROS2到底装哪里了
+
+在Windows安装过软件的小伙伴都知道安装软件都会选择一个安装目录,但是安装ROS时候并没有让你选择,ROS安装的默认目录在/opt/ros/下,根据版本的名字进行区分。
+
+我们本节安装的是humble版本的ROS,所以安装目录在/opt/ros/humble下。
+
+```
+cd /opt/ros/humble/
+ls
+```
+
+
+
+
+
+
+
+
+
 参考链接:
 
 - ROS2 镜像使用帮助:https://mirrors.tuna.tsinghua.edu.cn/help/ros2/

+ 7 - 7
docs/humble/chapt1/get_started/4.ROS2初体验.md

@@ -14,7 +14,7 @@
    ros2 run demo_nodes_py listener
    ```
 
-3. 启动一个新终端Ctrl+Alt+T
+3. **启动一个新终端Ctrl+Alt+T**
 
 4. 启动说话者
 
@@ -24,7 +24,7 @@
 
 观察一下现象,talker节点每数一个输,倾听节点每一次都能听到一个,是不是很神奇。
 
-![image-20210720114613697](4.ROS2初体验/imgs/image-20210720114613697.png)
+![image-20220603124845382](4.ROS2初体验/imgs/image-20220603124845382.png)
 
 
 ## 2.游戏2:涂鸦乌龟
@@ -73,23 +73,23 @@ rqt
 
 打开之后的窗口如下图,空空如也,不要担心,因为我们没有选插件的原因。
 
-![image-20211015151901951](4.ROS2初体验/imgs/image-20211015151901951.png)
+![image-20220603124701935](4.ROS2初体验/imgs/image-20220603124701935.png)
 
 ### 选择插件
 
 这里我们可以选择现有的几个RQT插件来试一试,可以看到和话题、参数、服务、动作四大通信组件相关的工具都有,还有一些可视化、日志和系统计算图等相关的。
 
-![image-20211015151919724](4.ROS2初体验/imgs/image-20211015151919724.png)
+![image-20220603124722852](4.ROS2初体验/imgs/image-20220603124722852.png)
 
 
 #### Introspection / Node Graph
 
-第一个是肯定是rqt_graph,插件名字叫做Node Graph,这个名字小鱼觉得更加的贴切,用rqt_graph更多的是为了延续ROS1中的用法,这个**插件用于查看节点和节点之间的关系的**。
-
-![image-20211015151937543](4.ROS2初体验/imgs/image-20211015151937543.png)
+<img src="4.ROS2初体验/imgs/image-20220603124742399.png" alt="image-20220603124742399" style="zoom:50%;" />
 
 打开后就可以看到上面几个节点之间的数据关系了,是不是很方便的工具。
 
+![image-20220603125332498](4.ROS2初体验/imgs/image-20220603125332498.png)
+
 ## 4.总结
 
 通过本节的小游戏,你应该对ROS2稍微熟悉了一丢丢,不过心中也会多出那么几个问题?比如:

BIN=BIN
docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124658803.png


BIN=BIN
docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124701935.png


BIN=BIN
docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124722852.png


BIN=BIN
docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124742399.png


BIN=BIN
docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603124845382.png


BIN=BIN
docs/humble/chapt1/get_started/4.ROS2初体验/imgs/image-20220603125332498.png


+ 11 - 0
docs/humble/chapt2/advanced/1.五种不同的方式编写节点.md

@@ -0,0 +1,11 @@
+内容还在更新中,请关注公众号鱼香ROS,第一时间获取更新
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

+ 11 - 0
docs/humble/chapt2/advanced/2.生命周期节点介绍.md

@@ -0,0 +1,11 @@
+内容还在更新中,请关注公众号鱼香ROS,第一时间获取更新
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

+ 11 - 0
docs/humble/chapt2/advanced/3.ROS2节点发现机制原理.md

@@ -0,0 +1,11 @@
+内容还在更新中,请关注公众号鱼香ROS,第一时间获取更新
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

+ 11 - 0
docs/humble/chapt2/advanced/4.Colcon编译原理.md

@@ -0,0 +1,11 @@
+内容还在更新中,请关注公众号鱼香ROS,第一时间获取更新
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

+ 11 - 0
docs/humble/chapt2/advanced/5.ROS2包运行原理.md

@@ -0,0 +1,11 @@
+内容还在更新中,请关注公众号鱼香ROS,第一时间获取更新
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

+ 11 - 0
docs/humble/chapt2/advanced/6.ROS2客户端库源码导读.md

@@ -0,0 +1,11 @@
+内容还在更新中,请关注公众号鱼香ROS,第一时间获取更新
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/SouthEast.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603130600648.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603131959194.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603133814964.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603135637630.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603135717676.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603135942917.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603143016936.png


BIN=BIN
docs/humble/chapt2/basic/1.C++编译工具之CMake/imgs/image-20220603145533742.png


+ 199 - 0
docs/humble/chapt2/basic/1.使用g++编译ROS2节点.md

@@ -0,0 +1,199 @@
+# 1.使用g++编译ROS2节点
+
+讲这一节的原因,是小鱼发现很多小伙伴在后期学习和使用ROS2时候,遇到各种依赖找不到的问题,不知如何解决。其实就是对C++依赖查找机制不熟悉,本节就是帮你打牢基础。
+
+## 1.动态链接库
+
+### 动态链接库介绍
+
+> 引用文章:
+>
+> - [gcc/g++ 链接库的编译与链接_surgewong的博客-CSDN博客_g++ 使用动态库](https://blog.csdn.net/surgewong/article/details/39236707)
+
+程序编译一般需要经预处理、编译、汇编和链接几个步骤。在实际应用中,有些公共代码需要反复使用,就把这些代码编译成为“库”文件。在链接步骤中,链接器将从库文件取得所需的代码,复制到生成的可执行文件中,这种库称为静态(链接)库,其特点是可执行文件中包含了库代码的一份完整拷贝,缺点是被多次使用就会多份冗余拷贝。还有一种库,就是程序在开始运行后调用库函数时才被载入,这种库独立于现有的程序,其本身不可执行,但包含着程序需要调用的一些函数,这种库称为动态(链接)库(Dynamic Link Library)。
+
+![img](1.使用g++编译ROS2节点/imgs/SouthEast.png)
+
+在widows平台下,静态链接库是.lib文件,动态库文件是.dll文件。在linux平台下,静态链接库是.a文件,动态链接库是.so文件。
+
+### 2. 用g++编译ROS2的C++节点
+
+### 2.1 编写节点
+
+编写一个ROS2的C++节点非常简单,只需三行代码即可完成。
+
+打开终端,创建`chapt2/basic`目录,用VSCODE打开d2lros2目录。
+
+```shell
+mkdir -p d2lros2/chapt2/basic/
+code d2lros2
+```
+
+接着在左侧chapt2上新建first_node.cpp,然后在first_node.cpp中输入下面的代码。
+
+```c++
+// 包含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;
+}
+```
+
+### 2.2 编译
+
+接着我们使用g++来编译`first_node`节点。正常的话一定会报错。
+
+```
+g++ first_ros2_node.cpp 
+```
+
+报错内容如下:
+
+```
+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 directory
+    3 | #include "rclcpp/rclcpp.hpp"
+      |          ^~~~~~~~~~~~~~~~~~~
+compilation terminated.
+```
+
+一定要记住这个错误` 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.h
+```
+
+> ls指令列出命令 | grep rclcpp.h 是对列出的结果进行过滤,只显示包含`rclcpp.h`的行。
+
+使用上面的指令,可以看到这个文件确实在这里。
+
+![image-20220603130600648](1.使用g++编译ROS2节点/imgs/image-20220603130600648.png)
+
+接着我们可以用-I(大写i)来为g++指定这个目录,然后再次运行,你会发现依然报错
+
+```
+g++ first_ros2_node.cpp -I /opt/ros/humble/include/rclcpp/ 
+```
+
+报错如下
+
+```
+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 directory
+   30 | #include "rcl/guard_condition.h"
+      |          ^~~~~~~~~~~~~~~~~~~~~~~
+compilation terminated.
+```
+
+虽然错误有些不一样,但是核心的文件都是一样的,你应该都看到了`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/
+```
+
+你会发现还是相同错误,因为头文件的包含是类似于套娃形式的,一层层加下去,总有终点,直到小鱼最终这个样子
+
+```shell
+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
+```
+
+运行完上面这段代码,你会发现报的错误变了。
+
+```
+/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 status
+```
+
+**请记住上面错误中的`undefined reference to xxxxx`,这将是你接下来机器人学习工作生涯中另一个最常见的错误。**
+
+原因在于g++找不到库文件,解决方法就是我们帮助它定位到库文件的位置,并通过-L参数指定库目录,-l(小写L)指定库的名字。
+
+ROS2相关的库的地址都在`/opt/ros/humble/lib`下,你可以使用下面的指定看到rclcpp的动态链接库。
+
+```
+ls /opt/ros/humble/lib | grep rclcpp
+```
+
+![image-20220603131959194](1.使用g++编译ROS2节点/imgs/image-20220603131959194.png)
+
+**指定库目录和使用的库后的终极命令**
+
+```shell
+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 -lrcutils
+```
+
+运行后,你会发现没有任何报错了,但是在当前目录下多出了一个`a.out`,这个就是我们将上面的代码编译和链接完库之后得出的可执行文件。
+
+> 如果你觉得a.out不好听,可以在g++指定后添加 `-o 名字`  ,比如 `-o first_node`
+
+### 3. 运行节点
+
+执行代码
+
+```
+./a.out
+```
+
+打开新的终端,使用`ros2 node list`查看正在运行的节点,是否有`first_node`。
+
+![image-20220603133814964](1.使用g++编译ROS2节点/imgs/image-20220603133814964.png)

BIN=BIN
docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/SouthEast.png


BIN=BIN
docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/image-20220603130600648.png


BIN=BIN
docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/image-20220603131959194.png


BIN=BIN
docs/humble/chapt2/basic/1.使用g++编译ROS2节点/imgs/image-20220603133814964.png


BIN=BIN
docs/humble/chapt2/basic/2.Python打包工具之Setup/imgs/image-20220603154952746.png


+ 70 - 0
docs/humble/chapt2/basic/2.使用make编译ROS2节点.md

@@ -0,0 +1,70 @@
+# 2.使用make编译ROS2节点
+
+有没有觉得用g++编译节点无比的麻烦,的确是这样子,为此先行者们发明了一个叫做make的**批处理**工具,我们可以将g++的指令写成脚本,就可以通过make自动的调用脚本完成操作。
+
+## 1.安装make
+
+```shell
+sudo apt install make
+```
+
+## 2.编写Makefile
+
+在`d2lros2/d2lros2/chapt2/basic`下新建`Makefile`,然后将上面的g++编译指令用下面的形式写到Makefile里。
+
+```makefile
+build:
+	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 -lrcutils \
+	-o first_node
+	
+# 顺便小鱼加个clean指令,用来删掉first_node
+clean:
+	rm first_node
+```
+
+## 3. 编译
+
+在Makefile同级目录输入
+
+```
+make build
+```
+
+![image-20220603135717676](2.使用make编译ROS2节点/imgs/image-20220603135717676.png)
+
+可以看到make指令调用了脚本里的build下的指令,对代码进行了编译。同级目录下也产生了first_node可执行文件(绿色代表可执行)。
+
+使用`make clean`指令即可删掉`first_node`节点。
+
+![image-20220603135942917](2.使用make编译ROS2节点/imgs/image-20220603135942917.png)
+
+## 4.运行测试
+
+```
+./first_node
+```
+
+新开终端
+
+```
+ros2 node list
+```
+
+![image-20220603161445651](2.使用make编译ROS2节点/imgs/image-20220603161445651.png)
+

BIN=BIN
docs/humble/chapt2/basic/2.使用make编译ROS2节点/imgs/image-20220603135717676.png


BIN=BIN
docs/humble/chapt2/basic/2.使用make编译ROS2节点/imgs/image-20220603135942917.png


BIN=BIN
docs/humble/chapt2/basic/2.使用make编译ROS2节点/imgs/image-20220603161445651.png


+ 77 - 0
docs/humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点.md

@@ -0,0 +1,77 @@
+# 3.使用CMakeLists.txt编译ROS2节点
+
+虽然通过make调用Makefile编译代码非常的方便,但是还是需要我们手写gcc指令来编译,那有没有什么办法可以自动生成Makefile呢?
+
+答案是有的,那就是cmake工具。
+
+**cmake通过调用CMakeLists.txt直接生成Makefile。**
+
+## 1.安装Cmake
+
+```shell
+sudo apt install cmake
+```
+
+## 2.新建CMakeLists.txt
+
+在`d2lros2/d2lros2/chapt2/basic`新建`CMakeLists.txt`,输入下面内容。
+
+```cmake
+cmake_minimum_required(VERSION 3.22)
+
+project(first_node)
+
+#include_directories 添加特定的头文件搜索路径 ,相当于指定g++编译器的-I参数
+include_directories(/opt/ros/humble/include/rclcpp/)
+include_directories(/opt/ros/humble/include/rcl/)
+include_directories(/opt/ros/humble/include/rcutils/)
+include_directories(/opt/ros/humble/include/rcl_yaml_param_parser/)
+include_directories(/opt/ros/humble/include/rosidl_runtime_c/)
+include_directories(/opt/ros/humble/include/rosidl_typesupport_interface/)
+include_directories(/opt/ros/humble/include/rcpputils/)
+include_directories(/opt/ros/humble/include/builtin_interfaces/)
+include_directories(/opt/ros/humble/include/rmw/)
+include_directories(/opt/ros/humble/include/rosidl_runtime_cpp/)
+include_directories(/opt/ros/humble/include/tracetools/)
+include_directories(/opt/ros/humble/include/rcl_interfaces/)
+include_directories(/opt/ros/humble/include/libstatistics_collector/)
+include_directories(/opt/ros/humble/include/statistics_msgs/)
+
+# link_directories - 向工程添加多个特定的库文件搜索路径,相当于指定g++编译器的-L参数
+link_directories(/opt/ros/humble/lib/)
+
+# add_executable - 生成first_node可执行文件
+add_executable(first_node first_ros2_node.cpp)
+
+# target_link_libraries - 为first_node(目标) 添加需要动态链接库,相同于指定g++编译器-l参数
+# 下面的语句代替 -lrclcpp -lrcutils
+target_link_libraries(first_node rclcpp rcutils)
+```
+
+## 3.编译代码
+
+我们一般会创建一个新的目录,运行cmake并进行编译,这样的好处是不会显得那么乱。
+
+```shell
+mkdir build
+cd build
+```
+
+创建好文件夹,接着运行cmake指令,`..`代表到上级目录找`CMakeLists.txt`。
+
+```
+cmake ..
+```
+
+运行完cmake你应该可以在build目录下看到cmake自动生成的Makefile了,接着就可以运行make指令进行编译
+
+```
+make
+```
+
+运行完上面的指令,就可以在build目录下发现`first_node`节点了。
+
+![image-20220603143016936](3.使用CMakeLists.txt编译ROS2节点/imgs/image-20220603143016936.png)
+
+
+

BIN=BIN
docs/humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点/imgs/image-20220603143016936.png


BIN=BIN
docs/humble/chapt2/basic/3.使用CMakeLists.txt编译ROS2节点/imgs/image-20220603145533742.png


+ 81 - 0
docs/humble/chapt2/basic/4.CMake依赖查找流程.md

@@ -0,0 +1,81 @@
+
+
+# 4.CMake依赖查找流程
+
+上面我们用g++、make、cmake三种方式来编译ros2的C++节点。用cmake虽然成功了,但是CMakeLists.txt的内容依然非常的臃肿,我们需要将其进一步的简化。
+
+## 1.优化CMakeList.txt
+
+将上面的CmakLists.txt改成下面的样子
+
+```cmake
+cmake_minimum_required(VERSION 3.22)
+project(first_node)
+
+find_package(rclcpp REQUIRED)
+add_executable(first_node first_ros2_node.cpp)
+target_link_libraries(first_node rclcpp::rclcpp)
+```
+
+接着继续生成和编译
+
+```
+cmake ..
+make
+```
+
+![image-20220603145533742](4.CMake依赖查找流程/imgs/image-20220603145533742.png)
+
+是不是非常的神奇,为什么可以浓缩成那么短的几句指令呢?
+
+## 2.find_package查找路径
+
+find_package查找路径对应的环境变量如下。
+
+```
+<package>_DIR
+CMAKE_PREFIX_PATH
+CMAKE_FRAMEWORK_PATH
+CMAKE_APPBUNDLE_PATH
+PATH
+```
+
+打开终端,输入指令:
+
+```shell
+echo $PATH
+```
+
+结果
+
+```
+PATH=/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+```
+
+观察PATH变量,你会发现`/opt/ros/humble/bin`赫然在其中,`PATH`中的路径如果以`bin`或`sbin`结尾,则自动回退到上一级目录,接着检查这些目录下的
+
+```text
+<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/          (U)
+<prefix>/(lib/<arch>|lib|share)/<name>*/                (U)
+<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/  (U)
+```
+
+cmake找到这些目录后,会开始依次找`<package>Config.cmake`或`Find<package>.cmake`文件。找到后即可执行该文件并生成相关链接信息。
+
+打开`/opt/ros/humble/share/rclcpp/cmake`你会发现`rclcppConfig.cmake`就在其中。
+
+## 3.总结
+
+本节小鱼带你通过多种方式进行节点的编译,主要是让你了解C++编译工具cmake以及其路径查找规则,以后在学习生涯中再遇到`undefined reference to xxxxx`和` No such file or directory`就再也不用慌张了。
+
+
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/basic/4.CMake依赖查找流程/imgs/image-20220603145533742.png


+ 119 - 0
docs/humble/chapt2/basic/5.Python依赖查找流程.md

@@ -0,0 +1,119 @@
+# 5.Python依赖查找流程
+
+python的打包和引入依赖的方式相比C++要容易太多。本节小鱼带你来通过几个实例学习下Python的路径查找机制。
+
+## 1.编写ROS2的Python节点
+
+在`d2lros2/d2lros2/chapt2/basic`新建`second_ros2_node.py`,输入下面的内容
+
+```python
+# 导入rclpy库,如果Vscode显示红色的波浪线也没关系
+# 我们只是把VsCode当记事本而已,谁会在意记事本对代码的看法呢,不是吗?
+import rclpy
+from rclpy.node import Node
+# 调用rclcpp的初始化函数
+rclpy.init() 
+# 调用rclcpp的循环运行我们创建的second_node节点
+rclpy.spin(Node("second_node"))
+```
+
+## 2.运行Python节点
+
+打开终端,输入指令
+
+```
+ls
+python3 second_ros2_node.py
+```
+
+打开新的终端,输入
+
+```shell
+ros2 node list
+```
+
+![image-20220603154952746](5.Python依赖查找流程/imgs/image-20220603154952746.png)
+
+完美,四行代码写了个ROS2的Python节点。
+
+那么问题来了,我们import rclpy,rclpy到底在哪里?python是如何找到的?
+
+
+
+## 3.Python包查找流程
+
+Python3运行`import rclpy`时候如何找到它的呢?答案是通过环境变量`PYTHONPATH`
+
+Ctrl+C打断节点运行,接着输入下面指令
+
+```shell
+echo $PYTHONPATH
+```
+
+结果
+
+```python
+/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages
+```
+
+你会发现里面有关于humble的python路径,在上面两个目录下找一下rclpy,看看能不能找到rclpy
+
+查找第一个路径
+
+```
+ls -l /opt/ros/humble/lib/python3.10/site-packages | grep rclpy
+```
+
+没找到,第二个
+
+```
+ls -l /opt/ros/humble/local/lib/python3.10/dist-packages/ | grep rclpy
+```
+
+找到了
+
+```
+drwxr-xr-x 1 root root 4096 Jun  3 04:45 rclpy
+drwxr-xr-x 2 root root 4096 May 23 22:23 rclpy-3.3.4-py3.10.egg-info
+```
+
+## 4.unset实验
+
+使用`unset`指令可以将环境变量删除掉,尝试删除掉`PYTHONPATH`之后再运行代码,看看是否还可以导入`rclpy`。
+
+```
+unset
+python3 second_ros2_node.py
+```
+
+提示如下
+
+```
+root@490925f19143:~/d2lros2/d2lros2/chapt2/basic# python3 second_ros2_node.py 
+Traceback (most recent call last):
+  File "/root/d2lros2/d2lros2/chapt2/basic/second_ros2_node.py", line 3, in <module>
+    import rclpy
+ModuleNotFoundError: No module named 'rclpy'
+```
+
+请你记住这个报错信息`ModuleNotFoundError: No module named 'xxx'`,这也是你未来学习过程中可能会经常会遇到的。
+
+下**次遇到时,你会想起小鱼这篇文章,然后对它轻蔑的一笑,接着找到这个库所在的目录,把它加到环境里。**
+
+
+
+## 5.总结
+
+本节小鱼带你学习了Python编写ROS2节点的方式,并带你认识了一个常见的错误`ModuleNotFoundError: No module named 'xxx'`。
+
+
+
+---
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/basic/5.Python依赖查找流程/imgs/image-20220603154952746.png


+ 125 - 0
docs/humble/chapt2/basic/6.Python工具之Setup.md

@@ -0,0 +1,125 @@
+# 2.Python打包工具之Setup
+
+> 本文摘自:[Python 之打包工具 setup.py_奔跑的大西吉的博客-CSDN博客_python setup 打包](https://blog.csdn.net/fenglepeng/article/details/119296632)
+
+本部分只做了解即可,我们平时用的并不多,因为python的依赖并不是靠setup来查找的,但是C++却靠着CmakeLists.txt进行查找。
+
+## 1. 为什么需要对项目分发打包?
+
+平常我们习惯了使用 pip 来安装一些第三方模块,这个安装过程之所以简单,是因为模块开发者为我们默默地为我们做了所有繁杂的工作,而这个过程就是 `打包`。
+
+打包,就是将你的源代码进一步封装,并且将所有的项目部署工作都事先安排好,这样使用者拿到后即装即用,不用再操心如何部署的问题(如果你不想对照着一堆部署文档手工操作的话)。
+
+不管你是在工作中,还是业余准备自己写一个可以上传到 PyPI 的项目,你都要学会如何打包你的项目。
+
+Python 发展了这么些年了,项目打包工具也已经很成熟了。他们都有哪些呢?
+
+你可能听过 `distutils` 、`distutils2`、`setuptools`等等,好像很熟悉,却又很陌生,他们都是什么关系呢?
+
+## 2. 包分发的始祖:distutils
+
+`distutils` 是 Python 的一个标准库,从命名上很容易看出它是一个分发(distribute)工具(utlis),它是 Python 官方开发的一个分发打包工具,所有后续的打包工具,全部都是基于它进行开发的。
+
+`distutils` 的精髓在于编写 setup.py,它是模块分发与安装的指导文件。
+
+那么如何编写 setup.py 呢?我会在后面进行详细的解析。
+
+你有可能没写过 setup.py ,但你绝对使用过 setup.py 来做一些事情,比如下面这条命令,我们经常用它来进行模块的安装。
+
+```text
+python setup.py install
+```
+
+这样的安装方法是通过源码安装,与之对应的是通过二进制软件包的安装,同样我也会在后面进行介绍。
+
+## 3. 分发工具升级:setuptools
+
+`setuptools` 是 distutils 增强版,不包括在标准库中。其扩展了很多功能,能够帮助开发者更好的创建和分发 Python 包。大部分 Python 用户都会使用更先进的 setuptools 模块。
+
+**distribute**,或许你在其他地方也见过它,这里也提一下。
+
+distribute 是 setuptools 有一个分支版本,分支的原因可能是有一部分开发者认为 setuptools 开发太慢了。但现在,distribute 又合并回了 setuptools 中。因此,我们可以认为它们是同一个东西。
+
+还有一个大包分发工具是 **distutils2**,其试图尝试充分利用distutils,detuptools 和 distribute 并成为 Python 标准库中的标准工具。但该计划并没有达到预期的目的,且已经是一个废弃的项目。
+
+因此,setuptools 是一个优秀的,可靠的 Python 包安装与分发工具。
+
+## 4. 超详细讲解 setup.py 的编写?
+
+打包分发最关键的一步是编写 `setup.py` 文件。
+
+以下是一个 setup.py 简单的使用示例
+
+```
+from setuptools import setup, find_packages
+
+setup(
+    # 指定项目名称,我们在后期打包时,这就是打包的包名称,当然打包时的名称可能还会包含下面的版本号哟~
+    name="mytest",
+    # 指定版本号
+    version="1.0",
+    author="flp",
+    author_email="flepeng@163.com",
+    # 这是对当前项目的一个描述
+    description="这只是一次测试",
+
+    # 项目主页
+    url="http://iswbm.com/", 
+
+    # 你要安装的包,通过 setuptools.find_packages 找到当前目录下有哪些包
+    packages=find_packages()
+    
+    # 指定包名,即你需要打包的包名称,要实际在你本地存在哟,它会将指定包名下的所有"*.py"文件进行打包哟,但不会递归去拷贝所有的子包内容。
+    # 综上所述,我们如果想要把一个包的所有"*.py"文件进行打包,应该在packages列表写下所有包的层级关系哟~这样就开源将指定包路径的所有".py"文件进行打包!
+    packages=['devops', "devops.dev", "devops.ops"],
+)
+```
+
+setup 函数常用的参数如下:
+
+| 参数                 | 说明                                                     |
+| -------------------- | -------------------------------------------------------- |
+| name                 | 包名称                                                   |
+| version              | 包版本                                                   |
+| author               | 程序的作者                                               |
+| author_email         | 程序的作者的邮箱地址                                     |
+| maintainer           | 维护者                                                   |
+| maintainer_email     | 维护者的邮箱地址                                         |
+| url                  | 程序的官网地址                                           |
+| license              | 程序的授权信息                                           |
+| description          | 程序的简单描述                                           |
+| long_description     | 程序的详细描述                                           |
+| platforms            | 程序适用的软件平台列表                                   |
+| classifiers          | 程序的所属分类列表                                       |
+| keywords             | 程序的关键字列表                                         |
+| packages             | 需要处理的包目录(通常为包含 **init**.py 的文件夹)        |
+| py_modules           | 需要打包的 Python 单文件列表                             |
+| download_url         | 程序的下载地址                                           |
+| cmdclass             | 添加自定义命令                                           |
+| package_data         | 指定包内需要包含的数据文件                               |
+| include_package_data | 自动包含包内所有受版本控制(cvs/svn/git)的数据文件        |
+| exclude_package_data | 当 include_package_data 为 True 时该选项用于排除部分文件 |
+| data_files           | 打包时需要打包的数据文件,如图片,配置文件等             |
+| ext_modules          | 指定扩展模块                                             |
+| scripts              | 指定可执行脚本,安装时脚本会被安装到系统 PATH 路径下      |
+| package_dir          | 指定哪些目录下的文件被映射到哪个源码包                   |
+| entry_points         | 动态发现服务和插件,下面详细讲                           |
+| python_requires      | 指定运行时需要的Python版本                               |
+| requires             | 指定依赖的其他包                                         |
+| provides             | 指定可以为哪些模块提供依赖                               |
+|                      | install_requires                                         |
+| extras_require       | 当前包的高级/额外特性需要依赖的分发包                    |
+| tests_require        | 在测试时需要使用的依赖包                                 |
+| setup_requires       | 指定运行 setup.py 文件本身所依赖的包                     |
+| dependency_links     | 指定依赖包的下载地址                                     |
+| zip_safe             | 不压缩包,而是以目录的形式安装                           |
+
+---
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/Nodes-TopicandService-16542449255392.gif


BIN=BIN
docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/Nodes-TopicandService.gif


BIN=BIN
docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/image-20210915153915430-16542449255391.png


BIN=BIN
docs/humble/chapt2/get_started/1.ROS2节点与工作空间/imgs/image-20210915153915430.png


+ 111 - 0
docs/humble/chapt2/get_started/1.ROS2节点介绍.md

@@ -0,0 +1,111 @@
+# 1.ROS2节点介绍
+
+本节小鱼正式的来介绍节点的概念。
+
+## 1. ROS2节点是什么
+
+ROS2中每一个节点也是只负责一个单独的模块化的功能(比如一个节点负责控制车轮转动,一个节点负责从激光雷达获取数据、一个节点负责处理激光雷达的数据、一个节点负责定位等等)
+
+![image-20210915153915430](1.ROS2节点介绍/imgs/image-20210915153915430-16542449255391.png)
+
+## 2.节点之间如何交互?
+
+上面举了一个激光雷达的例子,一个节点负责获取激光雷达的扫描数据,一个节点负责处理激光雷达数据,比如去除噪点。
+
+那节点与节点之间就必须要通信了,那他们之间该如何通信呢?ROS2早已为你准备好了一共四种通信方式:
+
+- 话题-topics
+- 服务-services
+- 动作-Action
+- 参数-parameters
+
+这四种种通信方式的用途和使用方法,小鱼放到了第四和第五章来介绍,到时候同时会带大家手撸代码。
+
+
+
+官方给了一张图,大家先大概看一下,帮助理解![Nodes-TopicandService](1.ROS2节点介绍/imgs/Nodes-TopicandService-16542449255392.gif)
+
+## 3. 如何启动一个节点?
+
+知道了节点的概念之后,我们该如何启动一个节点呢?
+
+因为工作空间和包的概念,小鱼放到了下一讲,这里大家跟着小鱼一起运行一个节点,感受一下。
+
+使用指令:
+
+```
+ros2 run <package_name> <executable_name>
+```
+
+指令意义:启动 <package_name>包下的 <executable_name>中的节点。
+
+**使用样例:**
+
+```
+ros2 run turtlesim turtlesim_node
+```
+
+大家可以尝试一下上面的指令,就是我们在第一章中启动小乌龟模拟器的那条指令。
+
+运行之后可以看到一只小乌龟,接下来就可以试试下一节中提到的几个指令来查看节点信息和列表。
+
+
+
+## 4. 通过命令行界面查看节点信息
+
+### 4.1 ROS2命令行
+
+ROS2的CLI,就是和ROS2相关的命令行操作。什么是命令行界面呢?这里小鱼再讲解一个概念,CLI(Command-Line Interface)和GUI(Graphical User Interface)
+
+- GUI(Graphical User Interface)就是平常我们说的图形用户界面,大家用的Windows是就是可视化的,我们可以通过鼠标点击按钮等图形化交互完成任务。
+- CLI(Command-Line Interface)就是命令行界面了,我们所用的终端,黑框框就是命令行界面,没有图形化。
+
+很久之前电脑还是没有图形化界面的,所有的交互都是通过命令行实现,就学习机器人而言,命令行操作相对于图形化优势更加明显。
+
+ROS2为我们提供了一系列指令,通过这些指令,可以实现对ROS2相关模块信息的获取设置等操作。
+
+### 4.2 节点相关的CLI
+
+运行节点(常用)
+
+```
+ros2 run <package_name> <executable_name>
+```
+
+查看节点列表(常用):
+
+```
+ros2 node list
+```
+
+查看节点信息(常用):
+
+```
+ros2 node info <node_name>
+```
+
+重映射节点名称
+
+```
+ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
+```
+
+
+
+## 5.总结
+
+通过本节课的学习,希望大家对节点的概念有所了解,下一节小鱼带你一起学习工作空间的相关概念
+
+
+
+- ROS2命令行工具源码;[ros2/ros2cli: ROS 2 command line interface tools (github.com)](https://github.com/ros2/ros2cli)
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/get_started/1.ROS2节点介绍/imgs/Nodes-TopicandService-16542449255392.gif


BIN=BIN
docs/humble/chapt2/get_started/1.ROS2节点介绍/imgs/image-20210915153915430-16542449255391.png


+ 148 - 0
docs/humble/chapt2/get_started/2.ROS2功能包与工作空间.md

@@ -0,0 +1,148 @@
+# 2.ROS2工作空间
+
+大家好,我是小鱼~上一节小鱼给大家介绍了一下节点,运行一个节点的时候使用的是
+
+```
+ros2 run 包名字 可执行文件名字
+```
+
+那你有没有想过,我们想找到一个节点(可执行文件),就必须要先知道它在哪个包,那问题就来了,想要找到某个包,该去哪里找?
+
+**答案就是:工作空间**
+
+> 注意:一个工作空间下可以有多个功能包,一个功能包可以有多个节点存在
+
+## 1. 工作空间
+
+小鱼定义:工作空间是包含若干个功能包的目录,一开始大家把工作空间理解成一个文件夹就行了。这个文件夹包含下有`src`。所以一般新建一个工作空间的操作就像下面一样
+
+```shell
+cd d2lros2/chapt2/
+mkdir -p chapt2_ws/src
+```
+
+是不是觉得就像创建一个目录(其实就是创建一个目录)
+
+## 2.功能包是什么
+
+功能包可以理解为存放节点的地方,ROS2中功能包根据编译方式的不同分为三种类型。
+
+- ament_python,适用于python程序
+- cmake,适用于C++
+- ament_cmake,适用于C++程序,是cmake的增强版
+
+后面小鱼会带你一起手把手创建功能包~
+
+
+
+## 3.功能包获取的两种方式
+
+### 3.1 安装获取
+
+安装一般使用
+
+```
+sudo apt install ros-<version>-package_name
+```
+
+安装获取会自动放置到系统目录,不用再次手动source。
+
+### 3.2 手动编译获取
+
+手动编译相对麻烦一些,需要下载源码然后进行编译生成相关文件。
+
+> 什么时候需要手动编译呢?一般我们能安装的功能包都是作者编译好程序将可执行文件上传到仓库中,然后我们才能够通过apt进行安装,如果作者还没来得及测试上传,或者忘记了测试上传,就会找不到对应的包,这时候就需要手动编译安装了。
+>
+> 另外一种就是我们需要对包的源码进行修改,这个时候也需要自己编译修改。
+
+手动编译之后,需要手动source工作空间的install目录。
+
+下一节学习完编译器colcon小鱼会通过实例带大家一起下载编译安装功能包~
+
+
+
+## 4.与功能包相关的指令 ros2 pkg
+
+```
+create       Create a new ROS2 package
+executables  Output a list of package specific executables
+list         Output a list of available packages
+prefix       Output the prefix path of a package
+xml          Output the XML of the package manifest or a specific tag
+```
+
+**1.创建功能包**
+
+```
+ros2 pkg create <package-name>  --build-type  {cmake,ament_cmake,ament_python}  --dependencies <依赖名字>
+```
+
+
+
+**2.列出可执行文件**
+
+ 列出所有
+
+```
+ros2 pkg executables
+```
+
+列出`turtlesim`功能包的所有可执行文件
+
+```
+ros2 pkg executables turtlesim
+```
+
+![image-20210915172702101](2.功能包与工作空间/imgs/image-20210915172702101.png)
+
+**3.列出所有的包**
+
+```
+ros2 pkg list
+```
+
+
+
+**4.输出某个包所在路径的前缀**
+
+```
+ros2 pkg prefix  <package-name>
+```
+
+比如小乌龟
+
+```
+ros2 pkg prefix turtlesim
+```
+
+
+
+**5.列出包的清单描述文件**
+
+> 每一个功能包都有一个标配的manifest.xml文件,用于记录这个包的名字,构建工具,编译信息,拥有者,干啥用的等信息。
+>
+> 通过这个信息,就可以自动为该功能包安装依赖,构建时确定编译顺序等
+
+查看小乌龟模拟器功能包的信息。
+
+```
+ros2 pkg xml turtlesim 
+```
+
+
+
+## 5.总结
+
+介绍完工作空间和功能包,接下来就可以讲讲ROS2的编译工具colcon,下一讲我们就开始对代码动手了~
+
+
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/get_started/2.功能包与工作空间/imgs/image-20210720102200144.png


BIN=BIN
docs/humble/chapt2/get_started/2.功能包与工作空间/imgs/image-20210720102349238.png


BIN=BIN
docs/humble/chapt2/get_started/2.功能包与工作空间/imgs/image-20210915172702101.png


BIN=BIN
docs/humble/chapt2/get_started/2.节点的家之工作空间/imgs/image-20210720102200144.png


BIN=BIN
docs/humble/chapt2/get_started/2.节点的家之工作空间/imgs/image-20210720102349238.png


BIN=BIN
docs/humble/chapt2/get_started/2.节点的家之工作空间/imgs/image-20210915172702101.png


+ 156 - 0
docs/humble/chapt2/get_started/3.ROS2编译器之Colcon.md

@@ -0,0 +1,156 @@
+# 3. ROS2构建工具—Colcon
+
+大家好,我是编译代码特别慢的小鱼。本节课我们来讲一下ROS2编译工具`colcon`
+
+本节小鱼会从下面几个方面来介绍:
+
+1. Colcon是个啥
+2. 安装colcon
+3. 编个东西测试一下
+4. 运行一个自己编的节点
+5. colcon学习总结指令
+
+
+
+## 1.Colcon是个啥
+
+colcon其实是一个功能包构建工具,这个工具用来做什么的呢?
+
+简单点说就是用来编译代码的,上几节跟大家讲了如何进行ROS2工作空间的创建,但没有说如何进行编译,其实就是用colcon。
+
+ROS2默认是没有安装colcon的,所以小鱼就从如何安装colcon开始跟大家讲解colcon的使用方法。
+
+> colcon想当于ros1中的catkin工具,学过ros1的同学可以辅助理解。没学过也没关系,用多了自然也就懂了。
+
+## 2.安装colcon
+
+如果使用一键安装ROS2,会帮你安装好这个工具,以防万一我们再装一次,打开终端复制粘贴进去即可。
+
+```
+sudo apt-get install python3-colcon-common-extensions
+```
+
+安装完成后,打开终端输入`colcon`即可看到其使用方法。
+
+## 3. 编个东西测试一下
+
+1. 创建一个工作区文件夹`colcon_test_ws`
+
+   ```
+   cd d2lros2/chapt2/
+   mkdir colcon_test_ws && cd colcon_test_ws
+   ```
+
+2. 下载个ROS2示例源码测试一下
+
+   ```
+   git clone https://github.com/ros2/examples src/examples -b humble
+   ```
+
+   > 如果这步克隆错误,你可能需要一个梯子翻个墙:[点击这里试试小鱼用了很多年的梯子](https://portal.shadowsocks.nz/aff.php?aff=41638)
+
+3. 编译工程
+
+   ```
+   colcon build
+   ```
+
+   ![image-20210720211422653](3.ROS2编译器之Colcon/imgs/image-20210720211422653.png)
+
+4. 编完之后的目录结构
+
+   构建完成后,在`src`同级目录我们应该会看到 `build` 、 `install` 和 `log` 目录:
+
+   ```
+   .
+   ├── build
+   ├── install
+   ├── log
+   └── src
+   
+   4 directories, 0 files
+   ```
+   
+   - `build` 目录存储的是中间文件。对于每个包,将创建一个子文件夹,在其中调用例如CMake
+   - `install` 目录是每个软件包将安装到的位置。默认情况下,每个包都将安装到单独的子目录中。
+   - `log` 目录包含有关每个colcon调用的各种日志信息。
+
+## 4.运行一个自己编的节点
+
+1. 打开一个终端使用 cd colcon_test_ws进入我们刚刚创建的工作空间,先source 一下资源
+
+   ```
+   source install/setup.bash
+   ```
+
+2. 运行一个订杂志节点,你将看不到任何打印,因为没有发布者
+
+   ```
+   ros2 run examples_rclcpp_minimal_subscriber subscriber_member_function
+   ```
+
+3. 打开一个新的终端,先source,再运行一个发行杂志节点
+
+   ```
+   source install/setup.bash
+   ros2 run examples_rclcpp_minimal_publisher publisher_member_function
+   ```
+
+   ![image-20210720211959001](3.ROS2编译器之Colcon/imgs/image-20210720211959001.png)
+
+
+
+## 5.本节学习指令
+
+> 这个小鱼要特别说一下,因为ros2的build没有ros中的devel概念了,如果想达到devel目录那样的效果,就需要加这个参数。没有学过ros的请主动忽略这句话。
+
+### 5.1 只编译一个包
+
+```
+colcon build --packages-select YOUR_PKG_NAME 
+```
+
+### 5.2 不编译测试单元
+
+```
+colcon build --packages-select YOUR_PKG_NAME  --cmake-args -DBUILD_TESTING=0
+```
+
+### 5.3 运行编译的包的测试
+
+```
+colcon test
+```
+
+### 5.4 允许通过更改src下的部分文件来改变install(重要)
+
+每次调整 python 脚本时都不必重新build了
+
+```
+colcon build --symlink-install
+```
+
+
+
+## 6.总结
+
+通过本节课的学习,相信你已经掌握如何编译ROS2的工程了,先别着急结束,还有一个小作业~
+
+
+
+参考资料:
+
+- colcon官方文档 [https://colcon.readthedocs.io/en/released/user/installation.html](https://colcon.readthedocs.io/en/released/user/installation.html)
+- ROS2官网文档 [https://docs.ros.org/en/foxy/Tutorials/Colcon-Tutorial.html](https://docs.ros.org/en/foxy/Tutorials/Colcon-Tutorial.html)
+
+
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/get_started/3.ROS2编译器之Colcon/imgs/image-20210720211422653.png


BIN=BIN
docs/humble/chapt2/get_started/3.ROS2编译器之Colcon/imgs/image-20210720211959001.png


+ 144 - 0
docs/humble/chapt2/get_started/4.使用RCLCPP编写节点.md

@@ -0,0 +1,144 @@
+# 4.使用RCLCPP编写节点
+
+节点需要存在于功能包当中、功能包需要存在于工作空间当中。所以我们要想创建节点,就要先创建一个工作空间,再创建功能包。
+
+## 1.创建工作空间和功能包
+
+### 1.1 工作空间
+
+工作空间就是文件夹,所以很简单。
+
+```
+cd d2lros2/chapt2/
+mkdir -p chapt2_ws/src/
+```
+
+### 1.2 创建example_cpp功能包
+
+创建example_cpp功能包,使用ament-cmake作为编译类型,并为其添加rclcpp依赖。
+
+```
+cd chapt2_ws/src
+ros2 pkg create example_cpp --build-type ament_cmake --dependencies rclcpp
+```
+
+大家可以手写一下这个代码,感受一下。现在小鱼来讲一讲这条命令的含义和参数。
+
+- pkg create 是创建包的意思
+- --build-type 用来指定该包的编译类型,一共有三个可选项`ament_python`、`ament_cmake`、`cmake`
+- --dependencies 指的是这个功能包的依赖,这里小鱼给了一个ros2的python客户端接口`rclpy`
+
+
+
+打开终端,进入`chapt2_ws/src`运行上面的指令,创建完成后的目录结构如下:
+
+```
+.
+└── src
+    └── example_cpp
+        ├── CMakeLists.txt
+        ├── include
+        │   └── example_cpp
+        ├── package.xml
+        └── src
+
+5 directories, 2 files
+```
+
+## 2.创建节点
+
+接着我们在`example_cpp/src`下创建一个`node_01.cpp`文件,创建完成后的目录结构如下:
+
+![image-20220603171631334](4.使用RCLCPP编写节点/imgs/image-20220603171631334.png)
+
+## 3.编写代码
+
+### 3.1 编写代码
+
+继续跟着小鱼一起输入代码,输入的时候可以边输边理解。
+
+```cpp
+#include "rclcpp/rclcpp.hpp"
+
+
+int main(int argc, char **argv)
+{
+    /* 初始化rclcpp  */
+    rclcpp::init(argc, argv);
+    /*产生一个node_01的节点*/
+    auto node = std::make_shared<rclcpp::Node>("node_01");
+    // 打印一句自我介绍
+    RCLCPP_INFO(node->get_logger(), "node_01节点已经启动.");
+    /* 运行节点,并检测退出信号 Ctrl+C*/
+    rclcpp::spin(node);
+    /* 停止运行 */
+    rclcpp::shutdown();
+    return 0;
+}
+```
+
+### 3.2 修改CmakeLists
+
+在`node_01.cpp`中输入上面的内容后,还需要修改一下CMakeLists.txt。将其添加为可执行文件,并使用`install`指令将其安装到`install`目录。
+
+在CmakeLists.txt最后一行加入下面两行代码。
+
+```
+add_executable(node_01 src/node_01.cpp)
+ament_target_dependencies(node_01 rclcpp)
+```
+
+添加这两行代码的目的是让编译器编译node_01这个文件,接着在上面两行代码下面添加下面的代码。
+
+```shell
+install(TARGETS
+  node_01
+  DESTINATION lib/${PROJECT_NAME}
+)
+```
+
+## 2.编译运行节点
+
+在`chapt2_ws`下依次输入下面的命令
+
+### 2.1 编译节点
+
+```
+colcon build
+```
+
+### 2.2 source环境
+
+```
+source install/setup.bash
+```
+
+### 2.3 运行节点
+
+```
+ros2 run example_cpp node_01
+```
+
+不出意外,你可以看到
+
+![image-20220603172524241](4.使用RCLCPP编写节点/imgs/image-20220603172524241.png)
+
+## 3.测试
+
+当节点运行起来后,可以再尝试使用`ros2 node list `指令来查看现有的节点。这个时候你应该能看到:
+
+![image-20220603172729457](4.使用RCLCPP编写节点/imgs/image-20220603172729457.png)
+
+## 4.总结
+
+至此,相信你已经掌握了如何编写一个C++版本的ros2节点了,但是这仅仅是编写ROS2节点方式之一,相比之下,小鱼更推荐你使用面向对象的方式编写节点,在进阶篇小鱼将会向你展示其写法。
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/get_started/4.使用RCLCPP编写节点/imgs/image-20220603171631334.png


BIN=BIN
docs/humble/chapt2/get_started/4.使用RCLCPP编写节点/imgs/image-20220603172524241.png


BIN=BIN
docs/humble/chapt2/get_started/4.使用RCLCPP编写节点/imgs/image-20220603172729457.png


+ 140 - 0
docs/humble/chapt2/get_started/5.使用RCLPY编写节点.md

@@ -0,0 +1,140 @@
+# 5.使用RCLPY编写节点
+
+## 1.创建C++功能包
+
+创建一个名字叫做`example_py` python版本的功能包。
+
+```
+cd chapt2/chapt2_ws/src/
+ros2 pkg create example_py  --build-type ament_python --dependencies rclpy
+```
+
+创建完成后的目录结构
+
+```
+.
+├── example_py
+│   └── __init__.py
+├── package.xml
+├── resource
+│   └── example_py
+├── setup.cfg
+├── setup.py
+└── test
+    ├── test_copyright.py
+    ├── test_flake8.py
+    └── test_pep257.py
+
+3 directories, 8 files
+```
+
+## 2.编写程序
+
+编写ROS2节点的一般步骤
+
+```
+1. 导入库文件
+2. 初始化客户端库
+3. 新建节点
+4. spin循环节点
+5. 关闭客户端库
+```
+
+
+在`example_py`下创建`node_02.py`接着我们开始编写代码。跟着小鱼一起边理解输入下面的代码,注释不用输。
+
+```
+import rclpy
+from rclpy.node import Node
+
+def main(args=None):
+    """
+    ros2运行该节点的入口函数
+    编写ROS2节点的一般步骤
+    1. 导入库文件
+    2. 初始化客户端库
+    3. 新建节点对象
+    4. spin循环节点
+    5. 关闭客户端库
+    """
+    rclpy.init(args=args) # 初始化rclpy
+    node = Node("node_02")  # 新建一个节点
+    node.get_logger().info("大家好,我是node_02.")
+    rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
+    rclpy.shutdown() # 关闭rclpy
+```
+
+代码编写完成用Crtl+S进行保存。接着修改`setup.py`。
+
+```
+    entry_points={
+        'console_scripts': [
+            "node_02 = example_py.node_02:main"
+        ],
+    },
+)
+```
+
+`setup.py`这段配置是声明一个ROS2的节点,声明后使用`colcon build`才能检测到,从而将其添加到`install`目录下。
+
+完成上面的工作后,就可以编译运行了。
+
+## 3.编译运行节点
+
+打开vscode终端,进入`town_ws`
+
+### 3.1 编译节点
+
+```
+cd chapt2/chapt2_ws/
+colcon build
+```
+
+> ```
+> --- stderr: example_py                   
+> /usr/lib/python3/dist-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
+>   warnings.warn(
+> ---
+> ```
+>
+> 如果在编译中看到上述错误没关系,不影响使用,ros2官方正在修复。
+
+### 3.2 source环境
+
+```
+source install/setup.bash
+```
+
+### 3.3 运行节点
+
+```
+ros2 run example_py node_02
+```
+
+运行结果
+
+![image-20220603174606170](5.使用RCLPY编写节点/imgs/image-20220603174606170.png)
+
+## 4.测试
+
+当节点运行起来后,可以再尝试使用`ros2 node list `指令来查看现有的节点。这个时候你应该能看到:
+
+![image-20220603174623023](5.使用RCLPY编写节点/imgs/image-20220603174623023.png)
+
+这说明你的节点已经运行起来了。
+
+## 5.总结
+
+本节我们学习了使用Python在工作空间的功能包里编写一个节点,代码是相同的,但是多了一些配置。
+
+当然除了使用这种方法编写一个节点,还有其他方式,小鱼将其放到了进阶篇来讲。
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划

BIN=BIN
docs/humble/chapt2/get_started/5.使用RCLPY编写节点/imgs/image-20220603174606170.png


BIN=BIN
docs/humble/chapt2/get_started/5.使用RCLPY编写节点/imgs/image-20220603174623023.png


+ 55 - 0
docs/humble/chapt2/章节导读.md

@@ -0,0 +1,55 @@
+# 第 2 章 ROS2第一个节点
+
+## 1.章节介绍
+
+本节我们将正式踏上ROS2的学习之旅,本章节同样的也分为三个部分。
+
+- 入门篇,主要介绍Python和C++的程序运行时如何查找依赖。
+- 基础篇,主要介绍ROS2的基础概念,同时重点的介绍ROS2的客户端库,并带你动手编写ROS2的节点。
+- 进阶篇,主要对ROS2的节点进一步的介绍,同时扩展了生命周期节点,节点发现机制和功能包的运行原理进行介绍。
+
+## 2.食用方法
+
+如果你不会C++或者Python语言,可以先简单学习下基本语法。
+
+如果你对Python包加载过程和CMake比较熟悉可以直接跳过基础篇。
+
+如果你对ROS2的基础概念和节点编写方法比较熟悉,可以直接跳过入门篇。
+
+## 3.章节目录
+
+- 基础篇-编程基础
+
+  - 1.C++编译工具之CMake
+
+  - 2.Python打包工具之Setup
+
+  - 3.CMake依赖查找流程
+
+  - 4.Python依赖查找流程
+- 入门篇-动手使用ROS2
+  - 1.ROS2节点与工作空间
+  - 2.ROS2编译器之Colcon
+  - 3.ROS2客户端库知多少
+  - 4.使用RCLCPP编写节点
+  - 5.使用RCLPY编写节点
+- 进阶篇-ROS2系统
+  - 1.五种不同的方式编写节点
+  - 2.在同一个进程组织多个节点
+  - 3.生命周期节点介绍
+  - 4.ROS2节点发现机制原理
+  - 5.Colcon编译原理与进阶使用
+  - 6.ROS2包运行原理
+  - 7.ROS2客户端库源码导读
+
+
+
+--------------
+
+技术交流&&问题求助:
+
+- **微信公众号及交流群:鱼香ROS**
+- **小鱼微信:AiIotRobot**
+- **QQ交流群:139707339**
+
+- 版权保护:已加入“维权骑士”(rightknights.com)的版权保护计划