Bladeren bron

完善录课材料

sangxin 3 jaren geleden
bovenliggende
commit
8ef98dd158

+ 1 - 3
docs/chapt4/4.1ROS2话题介绍.md

@@ -4,7 +4,7 @@
 
 ## 1.背景故事
 
-李四是一名擅长写小说的作家,既然是作家,肯定要写文章才行,所以李四就写了一本颜色小说《艳娘传奇》。
+李四是一名擅长写小说的作家,既然是作家,肯定要写文章才行,所以李四就写了一本颜色小说《艳娘传奇》。
 
 王二是一名单身多年的单身狗,单身狗没啥爱好,但看《艳娘传奇》肯定是必看的。
 
@@ -125,7 +125,6 @@ ros2 topic echo /chatter
 ![image-20210803115124591](4.1ROS2话题介绍/imgs/image-20210803115124591.png)
 
 
-
 #### ros2 topic info <topic_name> 查看主题信息
 
 命令
@@ -153,7 +152,6 @@ ros2 interface show std_msgs/msg/String
 ![image-20210803115726942](4.1ROS2话题介绍/imgs/image-20210803115726942.png)
 
 
-
 #### ros2 topic pub <topic_name> <msg_type>  arg 手动发布命令
 
 命令

+ 43 - 29
docs/chapt4/4.2话题通信实现(Python).md

@@ -7,7 +7,6 @@
 接下来快和小鱼一起动手学习编写Python的话题发布者和订阅者吧~
 
 
-
 ## 1.发布话题(sexy_girl)
 
 ### 1.1 如何编写
@@ -20,7 +19,7 @@ class WriterNode(Node):
 
 这是什么意思呢?如果没有学过面向对象的同学可能很懵逼,其实很简单,这种在自己名字里写一个Node的意思就是让WriterNode继承于Node,这样李四就能拥有Node所具备的属性和能力。
 
-大家可以把Node理解成人类,WriterNode继承于Node,也就是说李四是一个人类,这样李四就拥有了人类所具备的手和脚等器官,且获得说话吃饭刷B站和关注小鱼公众号的能力了
+> 大家可以把Node理解成人类,作家类(WriterNode)继承于人类(Node),李四是一名作家,也可以说李四是一个人类,人类所具备的手和脚等器官,能说话吃饭刷B站和关注小鱼公众号了,那么李四肯定也具备这些能力
 
 那代码里的WriterNode继承Node之后,会具备什么能力呢?在本节中用到了以下四个能力:
 
@@ -31,7 +30,7 @@ class WriterNode(Node):
 
 接下来我们就依次调用WriterNode所继承的能力来实现订阅发布功能。
 
-
+> 详细的能力可以查看API:https://docs.ros2.org/foxy/api/rclpy/index.html
 
 ### 1.2  编写程序
 
@@ -52,32 +51,38 @@ import rclpy
 from rclpy.node import Node
 from std_msgs.msg import String
 
+
 class WriterNode(Node):
     """
-    创建一个李四节点,并在初始化时输出一
+    创建一个李四节点,并在初始化时输出一
     """
-    def __init__(self):
-        super().__init__("li4") #给节点一个名字 li4
-        self.get_logger().info("大家好,我是李四,我是一名作家!") #来个自我介绍
-        self.write = self.create_publisher(String,"sexy_girl", 10) 
-        timer_period = 1  #李四的手速,每1s写一段话,够不够快
-        self.timer = self.create_timer(timer_period, self.timer_callback)  #启动一个定时装置,每 1 s,调用一次time_callback函数
+    def __init__(self,name):
+        super().__init__(name)
+        self.get_logger().info("大家好,我是%s,我是一名作家!" % name)
+        # 创建并初始化发布者成员属性pubnovel
+        self.pubnovel = self.create_publisher(String,"sexy_girl", 10) 
+
+
+        # 创建定时器成员属性timer
         self.i = 0 # i 是个计数器,用来算章节编号的
+        timer_period = 5  #每5s写一章节话
+        self.timer = self.create_timer(timer_period, self.timer_callback)  #启动一个定时装置,每 1 s,调用一次time_callback函数
+
 
     def timer_callback(self):
         """
-        定时器,用于定时发布小说
+        定时器回调函数
         """
         msg = String()
         msg.data = '第%d回:潋滟湖 %d 次偶遇胡艳娘' % (self.i,self.i)
-        self.write.publish(msg)  #将小说内容发布出去
+        self.pubnovel.publish(msg)  #将小说内容发布出去
         self.get_logger().info('李四:我发布了艳娘传奇:"%s"' % msg.data)    #打印一下发布的数据,供我们看
         self.i += 1 #章节编号+1
 ```
 
 ### 1.3 代码讲解
 
-#### 创建发布者
+#### 1.3.1 创建发布者
 
 ```
 self.create_publisher(String,"sexy_girl", 10) 
@@ -107,7 +112,7 @@ ros2 interface package std_msgs
 
 
 
-#### 定时器
+#### 1.3.2 编写发布逻辑发布数据
 
 这里小鱼使用了一个方法来创建一个定时器
 
@@ -161,7 +166,7 @@ ros2 run village_li li4_node
 ### 3.1 代码编写
 
 创建话题订阅者的一般流程:
-1. 导入订阅的话题类型
+1. 导入订阅的话题接口类型
 2. 创建订阅回调函数
 3. 声明并创建订阅者
 4. 编写订阅回调处理逻辑
@@ -180,38 +185,47 @@ self.create_subscription(UInt32,"sexy_girl_money",self.recv_money_callback,10)
 #!/usr/bin/env python3
 import rclpy
 from rclpy.node import Node
-from std_msgs.msg import String
-from std_msgs.msg import UInt32
+# 导入话题消息类型
+from std_msgs.msg import String,UInt32
 
 class WriterNode(Node):
     """
     创建一个李四节点,并在初始化时输出一个话
     """
-    def __init__(self):
-        super().__init__("li4") #给节点一个名字 li4
-        self.get_logger().info("大家好,我是李四,我是一名作家!") #来个自我介绍
+    def __init__(self,name):
+        super().__init__(name)
+        self.get_logger().info("大家好,我是%s,我是一名作家!" % name)
+        # 创建并初始化发布者成员属性pubnovel
+        self.pubnovel = self.create_publisher(String,"sexy_girl", 10) 
 
-        self.write = self.create_publisher(String,"sexy_girl", 10) 
-        timer_period = 1  #李四的手速,每1s写一段话,够不够快
-        self.timer = self.create_timer(timer_period, self.timer_callback)  #启动一个定时装置,每 1 s,调用一次time_callback函数
+
+        # 创建定时器成员属性timer
         self.i = 0 # i 是个计数器,用来算章节编号的
+        timer_period = 5  #每5s写一章节话
+        self.timer = self.create_timer(timer_period, self.timer_callback)  #启动一个定时装置,每 1 s,调用一次time_callback函数
+
 
         # 账户钱的数量
-        self.account = 0
-        # 开启收钱箱
-        self.sub_ = self.create_subscription(UInt32,"sexy_girl_money",self.recv_money_callback,10)
+        self.account = 80
+        # 创建并初始化订阅者成员属性submoney
+        self.submoney = self.create_subscription(UInt32,"sexy_girl_money",self.recv_money_callback,10)
+        
 
     def timer_callback(self):
         """
-        定时器,用于定时发布小说
+        定时器回调函数
         """
         msg = String()
         msg.data = '第%d回:潋滟湖 %d 次偶遇胡艳娘' % (self.i,self.i)
-        self.write.publish(msg)  #将小说内容发布出去
+        self.pubnovel.publish(msg)  #将小说内容发布出去
         self.get_logger().info('李四:我发布了艳娘传奇:"%s"' % msg.data)    #打印一下发布的数据,供我们看
         self.i += 1 #章节编号+1
 
+
     def recv_money_callback(self,money):
+        """
+        4. 编写订阅回调处理逻辑
+        """
         self.account += money.data
         self.get_logger().info('李四:我已经收到了%d的稿费' % self.account)
 
@@ -221,7 +235,7 @@ def main(args=None):
     ros2运行该节点的入口函数,可配置函数名称
     """
     rclpy.init(args=args) # 初始化rclpy
-    node = WriterNode()  # 新建一个节点
+    node = WriterNode("li4")  # 新建一个节点
     rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
     rclpy.shutdown() # rcl关闭
 ```

+ 34 - 21
docs/chapt4/4.3ROS2话题通信(C++).md

@@ -6,23 +6,23 @@
 
 ## 1.订阅话题
 
-### 1.1 如何订阅
+### 1.1 如何编写
 
 在C++中如何实现话题的订阅呢?其实做法和Python中差不多。还记得第三章中我们新建的王二节点类的定义吗?
 
 ```
-class Wang2Node : public rclcpp::Node
+class SingleDogNode : public rclcpp::Node
 ```
 
-Wang2Node继承了Node节点,其实Node可以理解为一个类,Wang2Node继承了Node后就会拥有Node类所具备的能力和知识。
+SingleDogNode继承了Node节点,其实Node可以理解为一个类,SingleDogNode继承了Node后就会拥有Node类所具备的能力和知识。
 
-和python中李四继承的Node类一样,本节中会使用Wang2Node继承而来的三种能力:
+和python中李四继承的Node类一样,本节中会使用SingleDogNode继承而来的三种能力:
 
 - 创建一个话题订阅者的能力,用于拿到艳娘传奇的数据
 
   ```
   rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sub_;
-  sub_ = this->create_subscription<std_msgs::msg::String>("sexy_girl", 10, std::bind(&Wang2Node::topic_callback, this, _1));
+  sub_ = this->create_subscription<std_msgs::msg::String>("sexy_girl", 10, std::bind(&SingleDogNode::topic_callback, this, _1));
   ```
 
 - 创建一个话题发布者的能力,用于给李四送稿费
@@ -39,13 +39,21 @@ Wang2Node继承了Node节点,其实Node可以理解为一个类,Wang2Node继
   RCLCPP_INFO(this->get_logger(), "大家好,我是单身汉王二.");
   ```
 
-
+更多的能力可以参考rclcpp的API:https://docs.ros2.org/foxy/api/rclcpp/index.html
 
 ### 1.2 代码实现
 
+创建话题订阅者的一般流程:
+
+1. 导入订阅的话题接口类型
+2. 创建订阅回调函数
+3. 声明并创建订阅者
+4. 编写订阅回调处理逻辑
+
 用VsCode打开上一章中town_ws工作空间,并打开wang2.cpp。我们在其中添加代码即可。
 
-添加完成后Wang2Node类中代码如下:
+
+添加完成后SingleDogNode类中代码如下:
 
 ```
 #include "rclcpp/rclcpp.hpp"
@@ -54,27 +62,27 @@ Wang2Node继承了Node节点,其实Node可以理解为一个类,Wang2Node继
 
 using std::placeholders::_1;
 /*
-    创建一个类节点,名字叫做Wang2Node,继承自Node.
+    创建一个类节点,名字叫做SingleDogNode,继承自Node.
 */
-class Wang2Node : public rclcpp::Node
+class SingleDogNode : public rclcpp::Node
 {
 
 public:
-    Wang2Node() : Node("wang2")
+    SingleDogNode() : Node("wang2")
     {
         // 打印一句自我介绍
         RCLCPP_INFO(this->get_logger(), "大家好,我是单身汉王二.");
         // 创建一个订阅者来订阅李四写的小说,通过名字sexy_girl
-        sub_ = this->create_subscription<std_msgs::msg::String>("sexy_girl", 10, std::bind(&Wang2Node::topic_callback, this, _1));
+        sub_ = this->create_subscription<std_msgs::msg::String>("sexy_girl", 10, std::bind(&SingleDogNode::topic_callback, this, _1));
     }
 
 private:
-    // 声明一个订阅者(成员变量)
-    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sub_;
-
+    // 声明一个订阅者(成员变量),用于订阅小说
+    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sub_novel;
+    
     void topic_callback(const std_msgs::msg::String::SharedPtr msg) const
     {
-        RCLCPP_INFO(this->get_logger(), "王二:我收到了:'%s'", msg->data.c_str());
+        RCLCPP_INFO(this->get_logger(), "王二::'%s'", msg->data.c_str());
     }
 };
 
@@ -82,7 +90,7 @@ int main(int argc, char **argv)
 {
     rclcpp::init(argc, argv);
     /*产生一个Wang2的节点*/
-    auto node = std::make_shared<Wang2Node>();
+    auto node = std::make_shared<SingleDogNode>();
     /* 运行节点,并检测退出信号*/
     rclcpp::spin(node);
     rclcpp::shutdown();
@@ -114,7 +122,7 @@ C++中创建一个订阅者,需要传入话题类型、话题名称、所要
 ### 2.1 编译运行
 
 ```
-$ colcon build --packages-select village_wang
+colcon build --packages-select village_wang
 ```
 
 ![image-20210804074029456](4.3ROS2话题通信(C++)/imgs/image-20210804074029456.png)
@@ -141,7 +149,12 @@ ros2 run  village_li  li4_node
 
 ![image-20210804074600329](4.3ROS2话题通信(C++)/imgs/image-20210804074600329.png)
 
-## 3.发布稿费
+
+
+
+
+
+## 3.发布(支付)稿费
 
 李四也要过日子的,过日子就需要money。王二也不能白看,所以王二需要支付稿费。我们上一节中已经给李四新建了订阅者订阅话题`sexy_girl_money`来收取稿费了。现在我们要给王二写一个发布者,来送稿费给李四,鼓励一下李四继续创作。
 
@@ -162,16 +175,16 @@ pub_ = this->create_publisher<std_msgs::msg::UInt32>("sexy_girl_money",10);
 我们来看一下增加发布者之后的完整代码
 
 ```
-class Wang2Node : public rclcpp::Node
+class SingleDogNode : public rclcpp::Node
 {
 
 public:
-    Wang2Node() : Node("wang2")
+    SingleDogNode() : Node("wang2")
     {
         // 打印一句自我介绍
         RCLCPP_INFO(this->get_logger(), "大家好,我是单身汉王二.");
         // 创建一个订阅者来订阅李四写的小说,通过名字sexy_girl
-        sub_ = this->create_subscription<std_msgs::msg::String>("sexy_girl", 10, std::bind(&Wang2Node::topic_callback, this, _1));
+        sub_ = this->create_subscription<std_msgs::msg::String>("sexy_girl", 10, std::bind(&SingleDogNode::topic_callback, this, _1));
         pub_ = this->create_publisher<std_msgs::msg::UInt32>("sexy_girl_money",10);
     }
 

+ 8 - 8
docs/chapt4/4.4话题小练习-李三白嫖.md

@@ -4,15 +4,15 @@
 
 ## 1.小练习背景
 
-话说李四有个兄弟叫李三,他是李四的哥哥。他看李四写的艳娘传奇非常的有意思,自己也想拿来品鉴一下。但他又不想给李四钱。
-所以我们的任务就是,在李家村里创建李三这个节点,然后为其订阅sexy_girl话题数据。
+话说李四有个兄弟叫李三,他是李四的哥哥,一个典型的白嫖党。他看李四写的艳娘传奇非常的有意思,自己也想拿来品鉴一下。但他又不想给李四钱。
+所以我们的任务就是,在李家村里创建白嫖党李三这个节点,然后为其订阅sexy_girl话题数据。
 
 ## 2.小练习思路
 
 你可以将其分为下面几步:
 
-1. 新建li3.py这个文件,在里面创建一个Li3Node类并定义一个main()函数
-2. 编写Li3Node类,为其订阅话题和编写回调函数
+1. 新建li3.py这个文件,在里面创建一个BaiPiaoNode类并定义一个main()函数
+2. 编写BaiPiaoNode类,为其订阅话题和编写回调函数
 3. 在setup.py中配置li3节点,如果记不得如何配置可以看看3.5章节
 4. 编译运行李三节点,并启动李四和王二节点
 5. 观察运行结果,用rqt_graph查看计算图
@@ -27,12 +27,12 @@ import rclpy
 from rclpy.node import Node
 from std_msgs.msg import String
 
-class Li3Node(Node):
+class BaiPiaoNode(Node):
     """
     创建一个李三节点,并在初始化时输出一个话
     """
-    def __init__(self):
-        super().__init__("li3")
+    def __init__(self,name):
+        super().__init__(name)
         self.get_logger().info("大家好,我是李三,李四他哥,我可以白嫖李四的小说!")
         self.sub_ = self.create_subscription(String,"sexy_girl",self.recv_callback,10)
 
@@ -45,7 +45,7 @@ def main(args=None):
     ros2运行该节点的入口函数,可配置函数名称
     """
     rclpy.init(args=args) # 初始化rclpy
-    node = Li3Node()  # 新建一个节点
+    node = BaiPiaoNode("li3")  # 新建一个节点
     rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
     rclpy.shutdown() # rcl关闭
 ```