Skip to content

Commit

Permalink
docs:更新笔记
Browse files Browse the repository at this point in the history
  • Loading branch information
Natsu-Akatsuki committed May 7, 2024
1 parent 5bb0267 commit 47b41a9
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 14 deletions.
69 changes: 58 additions & 11 deletions docs/Beginner/Executor and Callback.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Executor and Callback

- 根据[官方设计说明](http://design.ros2.org/articles/changes.html),ROS1 和 ROS2 的 C++实现中均有单线程模型和多线程模型, ROS2 能自行设计颗粒度更细的线程模型
根据[官方设计说明](http://design.ros2.org/articles/changes.html),ROS1 和 ROS2 的 C++实现中均有单线程模型和多线程模型,而在 ROS2 中能自行设计颗粒度更细的线程模型

## Usage

Expand Down Expand Up @@ -65,6 +65,45 @@ my_subscription = this->create_subscription<Int32>("/topic", rclcpp::SensorDataQ
</details>
<details>
<summary>:wrench: <b>用例 2:</b>
使用特定的线程处理特定的消息队列
</summary>
设置一个专门处理点云回调函数的线程(线程数 = 1),处理 IMU 回调函数和定时器回调函数的线程(线程数 = 内核数)
```cpp
#include <thread>
// 创建处理 IMU 回调函数和定时器回调函数的线程(线程数 = 内核数 - 1)
int core_number = std::thread::hardware_concurrency()
ros::AsyncSpinner spinner(core_number - 1); // Simple constructor. Uses the global callback queue.
spinner.start();
// >>> 创建一个专门处理点云回调函数的线程 >>>
// 创建专门接收点云的消息队列和 spinner
ros::NodeHandle pc_nh;
ros::CallbackQueue pc_queue;
// 使所有关联该句柄的订阅回调函数和定时器都走这个回调函数队列,调用 ros::spin() and ros::spinOnce() 时不会处理这部分的回调函数
pc_nh.setCallbackQueue(&pc_queue)
ros::Subscriber sub_a = pc_nh.subscribe("/velodyne_points", 1, callBackPointCloud);
// 为点云回调函数创建一个新的线程
// 方案一:
// std::thread pc_spinner_thread([&pc_queue]() {
// ros::SingleThreadedSpinner spinner;
// spinner.spin(&pc_queue);
// });
// pc_spinner_thread.join();
// 方案二:
ros::AsyncSpinner spinner(1, &pc_queue);
spinner.start();
ros::waitForShutdown();
```

</details>

## FAQ

暂未找到权威的资料,部分回答为自己的推理
Expand Down Expand Up @@ -132,19 +171,18 @@ my_subscription = this->create_subscription<Int32>("/topic", rclcpp::SensorDataQ
各种队列
</summary>

| 类型 | 作用 |
|:----------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| subscriber queue | When new messages arrive, they are stored in a queue until ROS gets a chance to execute your callback function. This parameter establishes a maximum number of messages that ROS will store in that queue at one time. If new messages arrive when the queue is full, the oldest unprocessed messages will be dropped to make room. (估计暂未反序列化) |
| publisher queue | the publisher queue is another queue like callback queue, but the queue is for queuing published message which is filled every time ``publish()`` function is called. (估计暂未进行序列化) |
| callback queue | |
| 类型 | 作用 |
|:---------------------------------------:|:-------------------------------------:|
| 订阅器队列<br />(消息队列)<br />subscriber queue | 用于存储将要被回调函数处理的消息;当队列已满,则移除最旧的数据 |
| 发布器队列<br />(消息队列)<br />publisher queue | 用于存储 publish() 将要发布的消息;当队列已满,则移除最旧的数据 |
| 回调函数队列<br />callback queue | |

</details>

<details>
<summary>:question: <b>问题 8:</b>
如何解决 ROS1 中 rosbag play 的数据丢包的问题?
</summary>
方案一:降低数据发布的频率,以适配订阅端回调函数处理数据的速度 \
方案二:在 ROS 1 中,将订阅器的 queue_size 设得足够大;rosbag play 播放时添加选项 --queue <一个足够大的数>;当 rosbag 准备播放完时,按空格键暂停,避免 rosbag 发布器中的数据停止发布。相关原理猜想为,在 ROS 的设计中,发布器要等自己的数据被订阅器处理(包括回调调用或者因为队列的维护而丢弃)了才发下一个数据。而待发的数据也会放到发布队列中,如果发布队列的数据超出上限时则丢掉最旧的数据。

Expand Down Expand Up @@ -314,10 +352,19 @@ if __name__ == "__main__":

</details>

## Reference
<details>
<summary>:question: <b>问题 9:</b>
<a href="https://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning">什么时候需要构建多个回调函数队列?</a>
</summary>

- [精讲多线程之 MultiThreadedSpinner](https://zhuanlan.zhihu.com/p/375418691)
- [ROS Spinning, Threading, Queuing](https://levelup.gitconnected.com/ros-spinning-threading-queuing-aac9c0a793f)
- ROSCON: [concurrency (2019)](https://roscon.ros.org/2019/talks/roscon2019_concurrency.pdf)
希望处理某些数据时(比如点云)不会阻塞其他的线程;希望创建多个线程,其中一个线程专门用于密集型计算的

</details>

## Reference

| 摘要 | 链接 |
|----------------------------------|-----------------------------------------------------------------------------------------------|
| 精讲多线程之 MultiThreadedSpinner | https://zhuanlan.zhihu.com/p/375418691 |
| ROS Spinning, Threading, Queuing | https://levelup.gitconnected.com/ros-spinning-threading-queuing-aac9c0a793f |
| ROSCON(concurrency (2019)) | https://roscon.ros.org/2019/talks/roscon2019_concurrency.pdf<br />https://vimeo.com/379127709 |
20 changes: 17 additions & 3 deletions docs/Beginner/Node and Component.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,15 @@ int main(int argc, char **argv) {
</details>
<details>
<summary>:wrench: <b>用例 5:</b>
分析 ROS1 roslaunch 启动的进程
</summary>
![](https://natsu-akatsuki.oss-cn-guangzhou.aliyuncs.com/img/image-20220624114324096.png ':size=900 roslaunch 为父进程,其启动的节点为子进程' )
</details>
## FAQ
<details>
Expand Down Expand Up @@ -326,6 +335,11 @@ def register_signals():

## Reference

- Official tutorial for [ROS1](http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29) and [ROS2](https://docs.ros.org/en/humble/Concepts/About-Executors.html)
- CLI for [ROS1](http://wiki.ros.org/nodelet#Helper_tools)
- GitHub demo: [ROS1 example node class](https://github.com/wsnewman/ros_class/blob/master/example_ros_class/src/example_ros_class.cpp), [sample_nodelet](https://github.com/cryborg21/sample_nodelet)
| 摘要 | ROS2 | ROS1 |
|------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
| 官方教程 | https://docs.ros.org/en/humble/Concepts/About-Executors.html | http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29 |
| CLI | https://docs.ros.org/en/iron/Tutorials/Intermediate/Tf2/Writing-A-Tf2-Listener-Cpp.html | http://wiki.ros.org/nodelet#Helper_tools |

| 摘要 | 链接 |
|------|------------------------------------------------------------------------------------------------------------------------------------------------|
| 示例代码 | https://github.com/wsnewman/ros_class/blob/master/example_ros_class/src/example_ros_class.cpp<br />https://github.com/cryborg21/sample_nodelet |
15 changes: 15 additions & 0 deletions docs/Intermediate/Signal.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,18 @@ int main() {
```
</details>
<details>
<summary>:question: <b>问题 6:</b>
节点中断的相关知识点
</summary>
在 bash 启动的 roslaunch 可以被 kill -s 2(键盘中断)中断,这种中断可以让节点顺利退出 \
使用 kill -s 9 中断节点或 roslaunch 进程可能会导致节点部分程序资源没有被完全回收,无法正常退出。最终表现为即使对应的进程已经关闭,但依然可以通过 `rosnode` 看到该节点(该节点没有从 `rosmaster` 中注销成功),若要通过命令行注销则需要使用 `rosnode cleanup`
- 由于 kill -s 9 或者程序资源没有回收完全的原因,即使对应的进程已经关闭,但是还是可以通过 `rosnode` 看到该节点(该节点没有完全从 `rosmaster` 中注销成功),若要通过命令行注销则需要使用 `rosnode cleanup`
- 使用 `kill -s 9` 作用于 launch 进程时,其管理的节点可能不会成功退出,因此在 rosnode 中仍然能看到,使用 `kill -s 2`
![](https://natsu-akatsuki.oss-cn-guangzhou.aliyuncs.com/img/image-20220627101048101.png ':size=500')
</details>

0 comments on commit 47b41a9

Please sign in to comment.