-
Notifications
You must be signed in to change notification settings - Fork 11
Creating a Navigator node
You've been asked to create a new component for Navigator, our big, complex autonomous driving codebase. Don't panic! Creating a node isn't too bad, and I'll prove it to you here.
We'll be creating a "speedometer" node, which subscribes to speed data published on our system, then publishes a visualization message that can display our current speed in Rviz.
- This tutorial is designed to be followed in parts. It's OK to tackle this in multiple sessions.
- Our aim is to keep this document up to date, but our project moves so quickly that you may find discrepancies. Use your best judgement, and find a teammate if you have questions.
In this tutorial, we will:
- Cover the basics of how ROS works
- Clone Navigator onto a new machine
- Build Navigator using Colcon
- Create a new package and add files
- Write a Node in C++
- Test our Node in the simulator
- Push our changes to GitHub
Above all else, the Robot Operating System, or ROS, is a communication framework. It allows individual programs called nodes to communicate with each other. In most cases, nodes either publish or subscribe to topics. This results in a web of nodes and topics, all mixed together. In fact, Navigator is simply a collection of Nodes and their topics.
Topics each hold their messages in a specific format called a ROS message. By default, ROS has message types to describe velocity, orientation, images, maps, and anything else a robot might use. In some cases, the Nova team creates custom message types when no existing type is available, such as a type to describe our car's selected gear.
Nodes are really just normal computer executables that use a ROS library to connect to our ROS network. Nodes written in C++ use a library called rclcpp, or the ROS Common Library for C++, to connect to our network. rclcpp allows our programs to do things like publish and subscribe to topics.
Clone Navigator, checkout our dev branch, and create a new branch for the changes we'll make:
wheitman@quad:~/tutorials$ git clone [email protected]:Nova-UTD/navigator.git
Cloning into 'navigator'...
Enter passphrase for key '/home/wheitman/.ssh/id_ed25519':
remote: Enumerating objects: 6841, done.
remote: Counting objects: 100% (142/142), done.
remote: Compressing objects: 100% (84/84), done.
remote: Total 6841 (delta 83), reused 81 (delta 54), pack-reused 6699
Receiving objects: 100% (6841/6841), 323.69 MiB | 9.66 MiB/s, done.
Resolving deltas: 100% (1996/1996), done.
Enter passphrase for key '/home/wheitman/.ssh/id_ed25519':
wheitman@quad:~/tutorials$ cd navigator
wheitman@quad:~/tutorials/navigator$ git checkout dev
*Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Switched to a new branch 'dev'
wheitman@quad:~/tutorials/navigator$ git checkout -b feature_speedometer
Switched to a new branch 'feature_speedometer'*
wheitman@quad:~/tutorials/navigator$
Colcon is ROS2's prefered build tool. It's really a wrapper around a number of build tools, like CMake. By using Colcon, we can build (and test) all of Navigator at once.
In the root directory of the cloned repository (navigator
), source ROS and run colcon build --symlink-install
:
wheitman@quad:~/tutorials/navigator$ . /opt/ros/foxy/setup.bash
wheitman@quad:~/tutorials/navigator$ colcon build --symlink-install
Starting >>> autoware_auto_cmake
Starting >>> autoware_auto_msgs
...
Finished <<< pure_pursuit_nodes [10.8s]
Summary: 81 packages finished [1min 33s]
6 packages had stderr output: gnss_conversion_nodes lio_sam rosapi state_estimate_monitoring trajectory_follower trajectory_follower_nodes
...
If Colcon fails to build all packages, you should resolve any build errors before moving on. Note that build warnings and stderr output are OK (use your common sense).
Start by navigating to the folder under src/
where you'd like the new package to go. In our example, the speedometer would fit under "miscellaneous", so we'll cd into src/misc/
. Then run the ROS2 package creation utility:
wheitman@quad:~/tutorials/navigator$ cd src/misc/
wheitman@quad:~/tutorials/navigator/src/misc$ ros2 pkg create --build-type ament_cmake speedometer
Which gives:
going to create a new package
package name: speedometer
destination directory: /home/wheitman/tutorials/navigator/src/misc
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['wheitman <[email protected]>']
licenses: ['TODO: License declaration']
build type: ament_cmake
dependencies: []
creating folder ./speedometer
creating ./speedometer/package.xml
creating source and include folder
creating folder ./speedometer/src
creating folder ./speedometer/include/speedometer
creating ./speedometer/CMakeLists.txt
The build-type ament_cmake
setting above creates a package using CMake. We chose this since our package is written in C++. The last option is our package name, "speedometer."
Now we'll add in our custom CMakeLists.txt file. If our package is a delicious chocolate cake, then this is our recipe. It describes where to find our dependencies (the ingredients), which files to process, and where to put the result. Our special file template creates our recipe for us, so long as we follow a standard package structure. As of writing, this custom "recipe" is copied like so:
wheitman@quad:src/misc$ cd speedometer/
wheitman@quad:src/misc/speedometer$ cp ../../tools/nova_auto_package/ExampleCMakeLists.txt CMakeLists.txt
We can then check the contents:
wheitman@quad:~/tutorials/navigator/src/misc/speedometer$ cat CMakeLists.txt
# Filename: CMakeLists.txt
# Author: Joshua Williams
# Email: [email protected]
# Copyright: 2021, Nova UTD
# License: MIT License
# No package name is specified above since this is our standard
# CMakeLists.txt file and will be the same across multiple
# projects. To use it, just add nova_auto_package as a
# buildtool_depend in package.xml and copy this file into the root of
# your package.
cmake_minimum_required(VERSION 3.5)
get_filename_component(directory_name ${CMAKE_CURRENT_SOURCE_DIR} NAME)
project(${directory_name})
find_package(nova_auto_package REQUIRED)
nova_auto_package()
Not bad! You can see that Josh has left his signature at the top ;)
The last file we need to look at is package.xml
. Every ROS package has one of these files. It describes what the package is, who maintains it, and what its dependencies are. That last part is important: Our automatic "recipe" above actually looks here to see what our package needs.
The pkg create
utility has created the basics for us, but modify package.xml
to look like this:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>speedometer</name>
<version>1.0.0</version>
<description>Subscribe to vehicle odometry and publish speed as Marker</description>
<maintainer email="[email protected]">wheitman</maintainer>
<license>MIT</license>
<buildtool_depend>nova_auto_package</buildtool_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
The important line above is the single "buildtool_depend." Make sure that "nova_auto_package" is added, or our CMakeLists.txt won't work.
...tbd
General
- Papers for literature review
- Demo 2: Grand Tour (Overview)
- Our Team
- Learning resources
- Meeting notes
- Archived Pages
Development & Simulation
- Code Standards and Guidelines
- Writing and Running Tests
- Installation and usage
- Logging into the Quad Remote Simulator
- Running the Simulator
Software Design
Outdated or Uncategorized