Files are available as teleop_gui here
In this section we are going to create a GUI Dashboard that
can control the robot either in an automated mode
(very primitive, as autonomous driving is not our objective)
or in responce to buttons that user presses.
It will also display lidar and odometry information.
Finally, it will receive and display data from a video
camera.
In order to create GUI, am going to use GUI library called tkinter. It is neither powerful nor convenient, but simple enough to save us time: after all, we are not going to create anything complex.
$ sudo apt-get install python3-tk
The project is called teleop_gui, so we are going to create a folder for it under harsh (which is a name of my ROS2 workspace, you can use your own) / src.
The project is almost identical to the ros2_teleop above, as the mater of fact, I simply copied it over and went through all files, changing the name of an old package to a new one.
Alternatively, you can create a new package and add necessary files:
$ ros2 pkg create --build-type ament_python teleop_gui
Compared to ros2_teleop, the only new file is controller_gui.py that contains GUI code:
$ cd ~/SnowCron/ros_projects/harsh $ touch src/teleop_gui/teleop_gui/controller_gui.py
The directory structure looks like this:
$ cd cd ~/SnowCron/ros_projects/harsh $ tree --dirsfirst src/teleop_gui src/teleop_gui ├── launch │ └── teleop_gui.launch.py ├── resource │ └── teleop_gui # Empty ├── teleop_gui │ ├── controller_gui.py │ ├── __init__.py # Empty │ └── robot_controller.py ├── package.xml ├── setup.cfg └── setup.py
import os from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node(package='teleop_gui', executable='controller_gui', output='screen', emulate_tty=True) ])
As you can see, all this launch file does is starting teleop_gui node, looking for a main function in a controller_gui file.
This file contains your contact/Copyright data and dependencies the project requires.
[develop] script-dir=$base/lib/teleop_gui [install] install-scripts=$base/lib/teleop_gui
import os from setuptools import setup from glob import glob package_name = 'teleop_gui' setup( name=package_name, version='0.0.0', packages=[package_name], data_files=[ ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), (os.path.join('share', package_name), glob('launch/*.launch.py')) ], install_requires=['setuptools'], zip_safe=True, maintainer='harsh', maintainer_email='contact@mail.com', description='TODO: Package description', license='TODO: License declaration', tests_require=['pytest'], entry_points={ 'console_scripts': [ 'controller_gui = teleop_gui.controller_gui:main' ], }, )
Note that if you (like myself) make a copy of ros2_teleop instead of creating it, you will have to pay attention to package names, otherwise it just will not work.
This is a modified copy of a file from ros2_teleop. It now has odometry, that is not required for the code to run, but we use it to display coordinates on our GUI dashboard.
It also has some additional member variables. There are many ways to exchange data between robot_controller that receives/publishes data and controller_gui that displays data in GUI and reacts to user's actions.
A hardcore ROS2 practitioner would probably send ROS2 messages between them... while I just access member variables directly: not very structured approach, but definitely a simple one.
This file creates a Dashboard with Lidar, Odometry and Video.
# In Terminal 1, bring up GUI Dashboard: $ cd ~/SnowCron/ros_projects/harsh $ colcon build --packages-select teleop_gui $ source install/setup.bash $ ros2 launch teleop_gui teleop_gui.launch.py # In Terminal 2, bring up Gazebo: $ colcon build --packages-select diff_drive_controller_bot $ source install/setup.bash $ ros2 launch diff_drive_controller_bot launch_sim.launch world:=src/worlds/maze.sdf
To watch messages as they are being published, in a new terminal:
$ ros2 topic echo /diff_cont/cmd_vel_unstamped linear: x: 0.25 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: 0.0