4. ROS Packages

We already covered the basics of ROS in our wiki. In this part, we will explain the basic structure of our ROS packages. They all share a basic structure that will be explained through the simulation.src.simulation_onboarding package. This package is located at simulation/src/simulation_onboarding and will be used throughout the onboarding.

/bin/sh: 1: cd: can't cd to /workspaces/kitcar-gazebo-simulation/

4.1. Launch directory

Inside the launch directory are files which define what should be done when you execute for example this command:

roslaunch simulation_onboarding master.launch road:=<ROAD_NAME>

Let’s break this command down:

  • simulation_onboarding is the name of the ROS Package.

  • master.launch is the name of the launch file that is launched by roslaunch.

  • road:=<ROAD_NAME> is used to pass the launch file the argument road with a value of <ROAD_NAME.

Let’s take a look at master.launch:

As you can see, two arguments are defined and used within the launch file master.launch. The onboarding_node.launch file is included and also launched. Let’s take a look at it:

The onboarding_node gets executed with additional parameters loaded from topics.yaml.

4.2. Message directory

ROS messages are defined inside the directory msg. Each *.msg file defines a new message type. Learn more about ROS messages at http://wiki.ros.org/Messages. You can see an example here:

4.3. Parameter directory

Each node has its own sub-directory inside the param directory. In there is always a file called topics.yaml. It defines the topics which are published from the node. Here is the topics.yaml:

Additionally, the directory usually contains the default.yaml file; it defines parameters used within the node:

Note

Using parameters in nodes creates programs with flexible behavior and code that does not depend on magic-numbers, i.e. numbers that are defined within the code and are very hard to read!

4.4. Scripts directory

The scripts directory contains python scripts that can start ROS nodes.

The scripts/onboarding_node is called when launching onboarding_node.launch which in turn initializes an instance of OnboardingNode:

Now you know how roslaunch uses python scripts to start nodes.

4.5. Source directory

The src directory is the heart of every ROS package. It contains the actual Python code defining ROS nodes. Each node is defined within a sub-directory (== python package) within src. Inside this sub-directory, you can find the node and sometimes additional Python modules that add functionality to it. In this example, the onboarding node is defined in the module node.py within the src/onboarding directory.

We will explain this code in the next chapter, but for integrity, here is the file node.py:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""OnboardingNode."""

import rclpy
from kitcar_utils.ros_base.node_base import NodeBase


class OnboardingNode(NodeBase):
    """ROS node to teach new members."""

    def __init__(self):
        """Initialize the node."""
        super().__init__(name="onboarding_node")

        # Start running node
        # This will do the following
        # 1) Call self.start()
        # 2) Call self.steer() 60 times a second!
        # 3) Call self.stop() when ROS is shutting down
        self.run(function=self.steer, rate=60)

    def start(self):
        """Start node."""
        # When overwriting a function, ensure that the original function (NodeBase.start())
        # is also called
        super().start()

    def stop(self):
        """Turn off node."""
        # When overwriting a function, ensure that the original function (NodeBase.stop())
        # is also called
        super().stop()

    def steer(self):
        """Control the car's pose to drive along the road."""
        pass


def main(args=None):
    """Console-script entry point for the onboarding node."""
    rclpy.init(args=args)
    try:
        OnboardingNode()
    except KeyboardInterrupt:
        pass
    finally:
        if rclpy.ok():
            rclpy.shutdown()

4.6. CMakeLists file

The file CMakeLists.txt contains information for the compiler so it knows what has to be done when it gets executed.

It should be executed in $KITCAR_REPO_PATH/kitcar-gazebo-simulation/simulation/ with the command:

catkin_make

The file looks like this:

4.7. Package file

The file package.xml holds metadata about this ROS Package:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://relaxng.org/ns/structure/1.0"?>
<package format="3">
  <name>simulation_onboarding</name>
  <version>2.0.0</version>
  <description>Onboarding tutorial node for the KITcar simulation.</description>
  <maintainer email="kitcar-simulation@lists.kit.edu">KITcar Simulation</maintainer>
  <license>MIT</license>

  <buildtool_depend>ament_python</buildtool_depend>

  <depend>rclpy</depend>
  <depend>kitcar_utils</depend>
  <depend>simulation_onboarding_msgs</depend>

  <test_depend>ament_copyright</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>

4.8. Setup file

The setup.py file tells cmake where the Python packages are located: