Skip to content

Outdoors Package Template

Sergei Grichine edited this page Nov 25, 2025 · 5 revisions

** As produced by ChatGPT.com on Nov 23, 2025 **

See:


ROS 2 Bringup Package Template (Option C)

Below is a fully prefabricated template for an outdoor GPS+SLAM bringup package.

Directory Structure

my_robot_bringup/
├── package.xml
├── setup.py
├── setup.cfg
├── resource/
│   └── my_robot_bringup
├── my_robot_bringup/
│   ├── __init__.py
│   ├── launch/
│   │   ├── robot_bringup.launch.py
│   │   ├── localization.launch.py
│   │   └── slam.launch.py
│   ├── params/
│   │   ├── navsat_params.yaml
│   │   ├── ekf_params.yaml
│   │   ├── slam_toolbox_params.yaml
│   │   └── mapper_server_params.yaml
│   └── tf/
│       ├── static_transforms.yaml
│       └── frames.pdf (optional diagram)
└── README.md

package.xml

<package format="3">
  <name>my_robot_bringup</name>
  <version>0.1.0</version>
  <description>Outdoor-capable bringup (GPS + NavSat + EKF + SLAM Toolbox)</description>

  <maintainer email="maintainer@example.com">Maintainer</maintainer>
  <license>Apache-2.0</license>

  <buildtool_depend>ament_cmake</buildtool_depend>
  <buildtool_depend>ament_python</buildtool_depend>

  <exec_depend>launch</exec_depend>
  <exec_depend>launch_ros</exec_depend>
  <exec_depend>robot_localization</exec_depend>
  <exec_depend>nav2_map_server</exec_depend>
  <exec_depend>nav2_util</exec_depend>
  <exec_depend>tf2_ros</exec_depend>
  <exec_depend>geographic_msgs</exec_depend>
  <exec_depend>sensor_msgs</exec_depend>
  <exec_depend>slam_toolbox</exec_depend>

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

setup.cfg

[develop]
script_dir=$base/lib/my_robot_bringup
[install]
install_scripts=$base/lib/my_robot_bringup

setup.py

from setuptools import setup
from glob import glob
import os

package_name = 'my_robot_bringup'

setup(
    name=package_name,
    version='0.1.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, 'launch'), glob('my_robot_bringup/launch/*.py')),
        (os.path.join('share', package_name, 'params'), glob('my_robot_bringup/params/*.yaml')),
        (os.path.join('share', package_name, 'tf'), glob('my_robot_bringup/tf/*')),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='Maintainer',
    maintainer_email='maintainer@example.com',
    description='Outdoor GPS mapping bringup',
    license='Apache-2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [],
    },
)

launch/robot_bringup.launch.py

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, DeclareLaunchArgument
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import ThisLaunchFileDir, LaunchConfiguration
from launch_ros.substitutions import FindPackageShare
from pathlib import Path


def generate_launch_description():
    pkg = FindPackageShare('my_robot_bringup').find('my_robot_bringup')
    params = Path(pkg) / 'params'

    return LaunchDescription([
        IncludeLaunchDescription(
            PythonLaunchDescriptionSource(str(Path(pkg) / 'launch' / 'localization.launch.py'))
        ),

        IncludeLaunchDescription(
            PythonLaunchDescriptionSource(str(Path(pkg) / 'launch' / 'slam.launch.py'))
        ),
    ])

launch/localization.launch.py

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import ThisLaunchFileDir
from launch_ros.substitutions import FindPackageShare
from pathlib import Path

def generate_launch_description():
    pkg = FindPackageShare('my_robot_bringup').find('my_robot_bringup')
    params = Path(pkg) / 'params'

    return LaunchDescription([
        # NavSat → odom
        Node(
            package='robot_localization',
            executable='navsat_transform_node',
            name='navsat_transform',
            parameters=[params / 'navsat_params.yaml'],
            remappings=[
                ('imu/data', '/imu/data'),
                ('gps/fix', '/gps/fix'),
                ('gps/filtered', '/gps/filtered')
            ]
        ),

        Node(
            package='robot_localization',
            executable='ekf_node',
            name='ekf_local',
            parameters=[params / 'ekf_params.yaml'],
            remappings=[
                ('odometry/filtered', '/odometry/local')
            ]
        ),
    ])

launch/slam.launch.py

from launch import LaunchDescription
from launch_ros.actions import Node
from launch.substitutions import ThisLaunchFileDir
from launch_ros.substitutions import FindPackageShare
from pathlib import Path


def generate_launch_description():
    pkg = FindPackageShare('my_robot_bringup').find('my_robot_bringup')
    params = Path(pkg) / 'params'

    return LaunchDescription([
        Node(
            package='slam_toolbox',
            executable='sync_slam_toolbox_node',
            name='slam_toolbox',
            output='screen',
            parameters=[params / 'slam_toolbox_params.yaml'],
            remappings=[('/scan', '/scan')]
        )
    ])

params/navsat_params.yaml

frequency: 10
magnetic_declination_radians: 0.0
yaw_offset: 0.0
zero_altitude: true
publish_filtered_gps: true
broadcast_utm_transform: true
use_odometry_yaw: false

params/ekf_params.yaml

frequency: 30
sensor_timeout: 0.2
transform_time_offset: 0.0
transform_timeout: 0.0
publish_tf: true
map_frame: map
odom_frame: odom
base_link_frame: base_footprint
world_frame: map

params/slam_toolbox_params.yaml

slam_toolbox:
  ros__parameters:
    mode: mapping
    map_frame: map
    odom_frame: odom
    base_frame: base_footprint
    scan_topic: /scan

tf/static_transforms.yaml

# Example: GPS → base_link offset
static_transforms:
  - frame_id: base_link
    child_frame_id: gps_link
    translation: [0.15, 0.0, 0.4]
    rotation: [0.0, 0.0, 0.0]

README.md

# My Robot Bringup

This package launches a full outdoor-capable navigation stack:
- NavSat transform
- EKF fusion
- SLAM Toolbox mapping

Run:
  ros2 launch my_robot_bringup robot_bringup.launch.py

Clone this wiki locally