An attempt to port the CTU's f1tenth codebase (originally at git@rtime.felk.cvut.cz:f1tenth
)
from ROS 1 Kinetic Kame π’ to ROS 2.
Current status: Working Follow the Gap on the real CTU's F1TENTH car (with NVIDIA Jetson TX2, Teensy 3.2, VESC) and in the Stage simulator.
The work in this repository is a part of my bachelor's thesis where more details can be found.
The main requirement is a working ROS 2 installation. We tested our code with different ROS 2 versions:
- ROS 2 Foxy Fitzroy π¦ (May 2020)
- ROS 2 Galactic Geochelone π (May 2021)
- ROS 2 Humble Hawksbill π β recommended π (May 2022)
- ROS 2 Rolling Ridley π² β As of 08/28/2022 it works, it might break in the future.
ROS 2 targets different platforms. The best supported platform (both by ROS core packages and third-party packages) is Ubuntu. Windows and macOS are supported as well but their support is not as good. See REP 2000 for more info. Our recommendations:
-
Use the specific Ubuntu release that is targeted by the ROS 2 version you use. For ROS 2 rolling/humble that's Ubuntu 22.04, for ROS 2 galactic/foxy it's Ubuntu 20.04.
-
On Windows, WSL 2 with Ubuntu is probably better than native ROS 2 for Windows (because of third-party packages).
-
On macOS, ROS 2 and all packages must be built from sources. The best way to manage it is to use 3 different workspaces stacked on top of each other:
- This repository as the top level workspace.
- One underlying workspace with any dependencies (packages) (normally, on Ubuntu, one would install already-built
binary packages using
apt
/rosdep
). - The bottom underlay β workspace with ROS 2 core packages that make up the standard ROS 2. You can use the pokusew/ros2-build to automate creating and building the second and the third workspace.
Note: We successfully tested this project on macOS 10.14.6 with ROS 2 foxy and galactic.
- vcstool
- Test if you have it using:
vcs --version
(should printvcs 0.3.0
) - You can install it using
sudo apt install python3-vcstool
orpython3 -m pip install -U vcstool
.
- Test if you have it using:
- colcon
- Test if you have it (and which extensions) using:
colcon version-check
- Usually installed as a part of ROS 2 distribution, otherwise it can be installed manually.
- π Follow the instructions here to install colcon mixins and configure shell autocompletion.
- Test if you have it (and which extensions) using:
Make sure you have a [working ROS 2 installation][#ros-2-version]. You can follow the official ROS 2 installation guide, the one for ROS 2 Humble on Ubuntu (using apt packages) is here.
Then, make sure you have vcstool
and colcon
as well, see [Other requirements][#other-requirements].
π Tip: See the ROS 2 Tips & Tricks to learn useful tips about using ROS 2, colcon
, and
many more.
Clone this repository and checkout to its root directory:
git clone git@github.com:pokusew/f1tenth-rewrite.git
cd f1tenth-rewrite
Open at least two (clean) terminals, one for building the workspace and the other one(s) for sourcing the built workspace and running the nodes. Remember to always use a different terminal for building the workspace than for sourcing it and running it.
Build terminal (in the project root directory):
# Source ROS 2 (if you don't do it automatically in your .bashrc, which I do NOT recommend).
# Note: Change the path to your ROS 2 distro accordingly.
source /opt/ros/humble/setup.bash
# Clone external packages' sources using vcstool.
# 1) if you are running code on the car:
vcs import --input stack.auto.repos --force
# 1) if you are running code on you computer (e.g. with Stage simulator)
vcs import --input stack.sim.repos --force
# Install any required dependencies using rosdep.
# We have to explicitly ignore
# - Stage because rosdep cannot detect pure CMake packages.
# - slam_toolbox and cartographer_ros because they are not needed for the FTG app
# and might not be available on all platforms for an easy install using apt.
rosdep install -i --from-paths src -y --skip-keys="Stage slam_toolbox cartographer_ros"
# Only if are running code on you computer and you need the Stage simulator:
# Install Stage's dependencies manually because Stage is not a ROS package (no package.xml so rosdep cannot work).
# Stage also requires libpng-dev and libjpeg-dev but those are normally already installed.
sudo apt install libfltk1.1-dev libglu1-mesa-dev
# Build the workspace.
# Note:
# For --mixin flag to work, you need colcon-mixin extension.
# See https://github.com/pokusew/ros-setup/blob/main/ROS2-Tips.md#colcon for installation instructions.
# Alternatively, you can use the variant without --mixin flag below.
# Note 2:
# vesc_ackermann's build is failing (uses now-removed deprecated ROS 2 APIs) on rolling (and possibly humble).
# Because we do not use it now, we can afford to skip is build for now.
colcon build --symlink-install --mixin compile-commands --packages-ignore vesc_ackermann
colcon build --symlink-install --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON --no-warn-unused-cli --packages-ignore vesc_ackermann
To see that everything is working, we can run the Follow the Gap in the Stage simulator.
Run terminal 1 (in the project root directory):
# Source the workspace.
# Note:
# Any underlay(s) (typically ROS 2 base workspace),
# that were sourced when this workspace was built, will be sourced as well.
source install/setup.bash
# Run the Follow the Gap in the Stage simulator.
ros2 launch auto stage_sample_ftg.launch.py
Run terminal 2 (in the project root directory):
# Source the workspace.
source install/setup.bash
# Start the auto (i.e., publishes one bool message containing `False` to the /eStop topic).
auto start
# Auto CLI is automatically added to the PATH when sourcing the workspace.
# Another possibility is to write manually:
ros2 topic pub /eStop -1 std_msgs/msg/Bool 'data: False'
Please refer to the π Using VSCode and JetBrains IDEs (CLion, PyCharm) with ROS π.
Note 1: Bold names denotes ROS 2 packages. Italic text in parentheses specifies build system, either (Ament CMake) or (Pure Python) or (Pure CMake).
Note 2: There might still be a few things in the code that need to be explained, clarified, ... Look for TODO comments.
src/:
- auto (Ament CMake) β Global launch files (ported from the launchers package), configs, and a simple Auto CLI.
- decision_and_control/
- follow_the_gap_v0 (Ament CMake) β The algorithm implementation and a ROS 2 wrapper node, both in C++.
- follow_the_gap_v0_ride (Pure Python) β A node that converts the heading angle from FTG to control commands. Extracted from follow_the_gap_v0 package.
- messages/
- command_msgs (Ament CMake) β IDL
- drive_api_msgs (Ament CMake) β IDL
- obstacle_msgs (Ament CMake) β IDL
- plan_msgs (Ament CMake) β IDL
- teensy_drive_msgs (Ament CMake) β IDL
- perception/
- recognition/
- obstacle_substitution (Pure Python) β A simple Python node that converts LiDAR scans to obstacles. Each LiDAR point to a CircleObstacle.
- cartographer_slam (Ament CMake) β Configuration and launch files for Google Cartographer.
- slam_toolbox_slam (Ament CMake) β Configuration and launch files for slam_toolbox.
- sensors/
- ros2_razor_imu (Pure Python) β ROS 2 driver for 9DoF Razor IMU M0 (external, currently not cloned, see stack.sim.repos and stack.auto.repos).
- recognition/
- simulation/
- storage (Ament CMake) β Data files.
- vehicle_platform/
- drive_api β Drive-API Python node for controlling the vehicle.
- teensy_drive β (Ament CMake) A C++ node that handles communication between ROS 2 and the Teensy 3.2 MCU which is responsible for servo control, RC control and emergency manual override.
- vesc/ β VESC ROS 2 driver and related packages (external).
ROS 2 Pure Python packages cannot contain IDL definitions (messages, services)
(at least for now, it may be supported in the future). It is possible create Ament CMake packages with Python code.
But the best practice is to split the messages definitions into separate packages (with _msgs
as a suffix,
per-convention). It speeds up the build and provides greater flexibility.
colcon --symlink-install
does not work correctly with Pure Python packages. Launch files, config files and any
other asset files are not symlinked.
The best workarounds:
- Prefer putting launch files and config files to Ament CMake packages which are symlinked correctly.
- βPut implementations of the launch methods in the package modules (which indirectly get symlink installed) and simply making a one line call out to it from the launch script. Since the one line call out rarely changes, it just needs the one install (build).β This idea comes from this comment.
- Accept the situation and build after every change to the assets file of a Pure Python package. Speed up the build by
selecting only that package using
colcon build --package-select <package>
.
ROS 2 examples, docs, tutorial and other resources and pretty inconsistent about the style of the main()
function.
When main()
is called from autogenerated executable, no arguments are passed
(but sys.argv[0]
may be tweaked).
When rclpy.init(args=None)
is called, the args
defaults to
sys.argv
, see rclpy/context.py
, line 59:
# rclpy/context.py, line 59:
rclpy_implementation.rclpy_init(args if args is not None else sys.argv, capsule)
So instead, we might as well set args
to sys.argv
directly ourselves, so we can extract what interests us.
So the final main()
we use for Python entrypoints is:
import sys
import rclpy
def main(args=None):
if args is None:
args = sys.argv
rclpy.init(args=args)
# ... further code
- There is no "global parameter server" in ROS 2