|Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.|
Kobuki's Control SystemDescription: Get familiar with the concept of Kobuki's control system
Keywords: kobuki, control system, concept
Tutorial Level: ADVANCED
Next Tutorial: Write your own controller for Kobuki
New in groovy
This tutorial will bring you in touch with the concept for Kobuki's control system. It describes the different components and how they interact with each other. At last, the reader is walked through a simple demo showing the benefits of the concept.
A note on Nodelets
Nodelets are heavily used in Kobuki's control system. They have various benefits over normal nodes. The most important among them are avoiding serialising/deserialising of messages and the transmission over the TCP/IP. This is done by passing pointers to messages instead of the messages themselves. That means messages are faster processed and transmitted. When working with big messages, such as point clouds, this can also significantly lower the CPU consumption.
For our use case, the speed improvement is important, that is why we implement controllers and other speed-sensitive parts of Kobuki's control system as nodelets.
Implementing code as nodelets instead of node is nothing to be afraid of as the the next tutorial will show.
Control System Concept
Kobuki's control system uses three different components.
kobuki_node: (AKA mobile base) is actually a nodelet, which wraps the C++ driver for communicating with Kobuki
cmd_vel_mux: is a velocity command multiplexer (or in otherwords a switch). It manages multiple incoming velocity commands according to the configured priority.
Kobuki controller: is a nodelet-based controller type - used for various applications; one example is the kobuki_safety_controller, which watches the bumper, cliff and wheel drop sensors and acts accordingly. Use this to implement your own reactive controller (see the next tutorial).
Furthermore, there is an implementation of a velocity smoother: yocs_velocity_smoother. This tool is optional, but highly recommended to use. In case a node publishing velocity commands can't ensure their smoothness, put this smoother in between that node and the cmd_vel_mux.
How it works
The three components introduced above are used in a small hierarchy. Starting bottom-up, there is the mobile base, which listens for commands (LEDs, sounds, velocity) and publishes sensor information. On top of that we use the cmd_vel_mux, which makes sure, that only one velocity command at a time is relayed through to the mobile base. On the next level we have one or more controllers and other programs, such as keyboard teleop and the navi stack. There are cases, in which we want smooth velocity (e.g. keyop) and cases in which we don't (safety controller). So, use the velocity smoother when necessary.
The diagram below shows example use cases:
In the shown scenario, there are multiple programs, which want to control Kobuki's movement. The velocity muxer allows using all of them in parallel. An example multiplexer configuration could be the following:
- 3 (highest priority): safety controller
- 2: keyboard teleop
- 1: android teleop
- 0 (lowest priority): navi stack teleop
In this case, the navi stack would control the robot in most of the times. However, the user can override navi stack's commands, by triggering commands with the Android teleop app or the keyboard teleop. In case both teleops would be active at the same time, keyboard teleop would win. However, all the velocity commands above will be overridden when the safety controller kicks in (bumper, cliff or wheel drop sensor activated). This allows safe driving of Kobuki with all three tools.
Playing with the Control System
To show you the benefit of following the presented control concept, we will modify the default launch files to show you bad behaviour we want to avoid.
In order to bring forth Kobuki's bad behaviour, we will tweak kobuki_node/keyop.launch.
1. Comment out the multiplexer:
[...] <launch> <!-- <node pkg="nodelet" type="nodelet" name="cmd_vel_mux" args="load cmd_vel_mux/CmdVelMuxNodelet kobuki"> --> <!-- <param name="subscribers_cfg_file" value="$(find kobuki_node)/param/keyop_mux.yaml"/> --> <!-- <remap from="cmd_vel_mux/mux_cmd_vel" to="mobile_base/commands/velocity"/> --> <!-- </node> --> [...]
2. Remap the velocity command topic of the safety controller in order to send commands directly to the mobile_base nodelet:
[...] <node pkg="nodelet" type="nodelet" name="kobuki_safety_controller" args="load kobuki_safety_controller/SafetyControllerNodelet kobuki"> <!-- <remap from="kobuki_safety_controller/cmd_vel" to="cmd_vel_mux/safety_controller"/> --> <remap from="kobuki_safety_controller/cmd_vel" to="mobile_base/commands/velocity"/> [...]
3. The same for keyop:
<node pkg="kobuki_keyop" type="keyop" name="keyop" output="screen"> <remap from="keyop/enable" to="mobile_base/enable"/> <remap from="keyop/disable" to="mobile_base/disable"/> <!-- <remap from="keyop/cmd_vel" to="cmd_vel_mux/keyboard_teleop"/> --> <remap from="keyop/cmd_vel" to="mobile_base/commands/velocity"/> [...]
Now, let's see what will happens:
First, launch the basics:
roslaunch kobuki_node minimal.launch --screen
and then in a separate terminal the keyop app (keyop.launch):
roslaunch kobuki_node keyop.launch --screen
First, make Kobuki drive against an obstacle. You will notice that Kobuki's starts to shake (quickly moving back and forth) at the obstacle.
Now, lift Kobuki up. The safety controller will stop Kobuki, once one of the wheel drop sensors trigger. However, you will notice that the wheels are shaking and slowely moving forward.
Both behaviours are due to Kobuki receiving and executing velocity commands from both keyop and the safety controller at the same time.
Now, undo the modifications above and start minimal.launch and keyop.launch again.
You will notice that Kobuki now moves a couple of centimeters back, when hitting an obstacle. Also, when you lift Kobuki up, the wheels stop turning.
Follow the control system concept!
The above is true, but we also want to highlight, that the presented control concept represents our first iteration. In the future, we want to further improve the performance and design. If you have suggestions, please feel free to join the development!
Now, that you have learned about the control system, it is time to implement your own controller: Write your own controller for Kobuki