joy_teleop

This file is ai generated. Do not edit this file directly. Instead, edit the node source code and run the generate-node-docs command to update this file.

Description

The joy_teleop node is a generic joystick teleoperation interface that maps joystick buttons and axes to ROS topics, services, and actions. It provides flexible configuration to control robots using any joystick, allowing users to map joystick inputs to arbitrary message/service/action types.

Subscribers

Topic

Type

Description

joy

sensor_msgs/msg/Joy

Receives joystick input messages containing button and axis states

Publishers

Publishers are dynamically created based on configuration. Each configured topic command creates a publisher with:

  • Topic name: User-defined in configuration

  • Message type: User-defined in configuration (e.g., geometry_msgs/msg/TwistStamped, geometry_msgs/msg/Wrench)

  • Description: Publishes command messages when configured buttons/axes are activated

Services

Service clients are dynamically created based on configuration. Each configured service command creates a client with:

  • Service name: User-defined in configuration

  • Service type: User-defined in configuration

  • Description: Calls service when configured buttons/axes are activated

Actions

Action clients are dynamically created based on configuration. Each configured action command creates a client with:

  • Action name: User-defined in configuration

  • Action type: User-defined in configuration

  • Description: Sends action goals when configured buttons/axes are activated

Parameters

The node uses a hierarchical parameter structure where each command is configured under its own namespace. All parameters are defined dynamically through configuration files.

Command Configuration Parameters

Each command requires the following base parameters:

Parameter

Type

Description

<command_name>.type

string

Interface type: topic, service, or action

<command_name>.interface_type

string

ROS message/service/action type (e.g., geometry_msgs/msg/Twist)

Topic Commands

Parameter

Type

Description

<command_name>.topic_name

string

Name of the topic to publish to

<command_name>.deadman_buttons

list of integers

Button indices that must be pressed (1-indexed)

<command_name>.deadman_axes

list of integers

Axis indices that must be at 1.0

<command_name>.deadman_axes_negative

list of integers

Axis indices that must be at -1.0

<command_name>.message_value.<field>

dict

Fixed message field values to publish

<command_name>.axis_mappings.<field>.axis

integer

Joystick axis index to map from

<command_name>.axis_mappings.<field>.button

integer

Joystick button index to map from

<command_name>.axis_mappings.<field>.value

any

Fixed value to use

<command_name>.axis_mappings.<field>.scale

float

Scaling factor for axis/button value

<command_name>.axis_mappings.<field>.offset

float

Offset to add after scaling

<command_name>.axis_mappings.<field>.index

integer

Index for array fields (default: 0)

Service Commands

Parameter

Type

Description

<command_name>.service_name

string

Name of the service to call

<command_name>.buttons

list of integers

Button indices that must be pressed

<command_name>.axes

list of integers

Axis indices that must be at 1.0

<command_name>.axes_negative

list of integers

Axis indices that must be at -1.0

<command_name>.service_request

dict

Request fields to set when calling service

Action Commands

Parameter

Type

Description

<command_name>.action_name

string

Name of the action server

<command_name>.buttons

list of integers

Button indices that must be pressed

<command_name>.axes

list of integers

Axis indices that must be at 1.0

<command_name>.axes_negative

list of integers

Axis indices that must be at -1.0

<command_name>.action_goal

dict

Goal fields to set when sending action

Example Usage

Basic Launch

ros2 run joy_teleop joy_teleop --ros-args --params-file /path/to/config.yaml

Example Configuration File

joy_teleop:
  ros__parameters:
    # Topic command with axis mapping (for continuous control)
    cmd_vel:
      type: topic
      interface_type: geometry_msgs/msg/TwistStamped
      topic_name: cmd_vel
      deadman_buttons: [4]
      axis_mappings:
        twist-linear-x:
          axis: 1
          scale: 0.5
          offset: 0.0
        twist-angular-z:
          axis: 0
          scale: 0.5
          offset: 0.0

    # Topic command with fixed message (for discrete control)
    stop:
      type: topic
      interface_type: geometry_msgs/msg/Twist
      topic_name: cmd_vel
      deadman_buttons: [0, 2]
      message_value:
        linear-x:
          value: 0.0
        angular-z:
          value: 0.0

    # Service command
    reset_odom:
      type: service
      interface_type: std_srvs/srv/Empty
      service_name: reset_odometry
      buttons: [8]
      service_request: {}

    # Action command
    navigate:
      type: action
      interface_type: nav2_msgs/action/NavigateToPose
      action_name: navigate_to_pose
      buttons: [9]
      action_goal:
        pose-header-frame_id: "map"
        pose-pose-position-x: 1.0
        pose-pose-position-y: 2.0

Launch with Joy Node

from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os

def generate_launch_description():
    config_file = os.path.join(
        get_package_share_directory('joy_teleop'),
        'config', 'joy_teleop_example.yaml'
    )
    
    return LaunchDescription([
        Node(
            package='joy',
            executable='joy_node',
            name='joy_node'
        ),
        Node(
            package='joy_teleop',
            executable='joy_teleop',
            parameters=[config_file]
        )
    ])

Notes

  • Button and axis indices are 0-indexed

  • Topic commands with message_value publish once per button press (debounced)

  • Topic commands with axis_mappings publish continuously while deadman buttons are held

  • Service and action commands are debounced to prevent multiple calls per button press

  • Messages with a header field will have the timestamp automatically filled with the current time

  • Field names in configuration use - as separator (e.g., twist-linear-x maps to twist.linear.x)