杰瑞科技汇

如何在ROS launch文件中调用Python脚本?

Of course! This is a fundamental concept in ROS. Launching a Python script (or any executable) using a ros2 launch file is the standard way to orchestrate multiple nodes and configure parameters for your robot or application.

如何在ROS launch文件中调用Python脚本?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering everything from the basics to best practices.


The Core Concept: launch_ros Nodes

In ROS 2, you don't directly "launch" a Python script. Instead, you define a node within a launch file. A node is an isolated process that performs some computation. The launch_ros package provides the tools to describe ROS 2 nodes.

The key component is the Node action.

from launch_ros.actions import Node

This Node action tells the ROS 2 launch system how to start your executable (your Python script).

如何在ROS launch文件中调用Python脚本?-图2
(图片来源网络,侵删)

Step-by-Step: Creating a Launch File for a Python Script

Let's walk through a complete example.

Step 1: Create Your Python Node

First, you need a simple Python script that can be run as a ROS 2 node. It must use the rclpy library.

File: my_python_pkg/scripts/my_talker.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalPublisher(Node):
    def __init__(self):
        super().__init__('minimal_publisher')
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        timer_period = 0.5  # seconds
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.count = 0
        self.get_logger().info('Talker node has been started.')
    def timer_callback(self):
        msg = String()
        msg.data = f'Hello, World! {self.count}'
        self.publisher_.publish(msg)
        self.get_logger().info(f'Publishing: "{msg.data}"')
        self.count += 1
def main(args=None):
    rclpy.init(args=args)
    minimal_publisher = MinimalPublisher()
    try:
        rclpy.spin(minimal_publisher)
    except KeyboardInterrupt:
        pass
    finally:
        minimal_publisher.destroy_node()
        rclpy.shutdown()
if __name__ == '__main__':
    main()

Important:

如何在ROS launch文件中调用Python脚本?-图3
(图片来源网络,侵删)
  • Make this file executable: chmod +x my_python_pkg/scripts/my_talker.py
  • The #!/usr/bin/env python3 shebang line is good practice.
  • The node must be importable. Make sure your package is properly built with colcon build.

Step 2: Create the Launch File

Now, create a Python launch file in the launch directory of your package.

File: my_python_pkg/launch/my_launch_file.py

# Import necessary modules
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
    """
    This function is called by the launch system to generate the launch description.
    It must return a LaunchDescription object.
    """
    # Define the action for our Python talker node
    # The 'executable' is the name of the script file.
    # The 'package' is the name of the package where the script is located.
    talker_node = Node(
        package='my_python_pkg',
        executable='my_talker',
        name='custom_talker_name'  # Optional: overrides the node name from the script
    )
    # Return the LaunchDescription object containing the node
    return LaunchDescription([
        talker_node
    ])

Step 3: Declare the Executable in package.xml

ROS 2 needs to know that my_talker.py is an executable. You do this in your package.xml.

File: my_python_pkg/package.xml

Add this line inside the <package> tag:

<exec_depend>my_python_pkg</exec_depend> <!-- This should already be there for your Python code -->
<!-- Add this line to declare the executable -->
<exec_depend>my_python_pkg</exec_depend>

Note: In ROS 2, the exec_depend on your own package is often necessary to ensure all components, including executables, are correctly recognized and installed by the build system (ament).

Step 4: Build Your Package

Navigate to your workspace's root directory and build:

colcon build --packages-select my_python_pkg

Step 5: Run the Launch File

You can now launch your Python node using the ros2 launch command.

# Navigate to your workspace root
cd ~/ros2_ws
# Run the launch file
ros2 launch my_python_pkg my_launch_file.py

You should see output from your my_talker.py script, publishing messages to the /topic every 0.5 seconds.


Key Parameters of the Node Action

The Node action is very flexible. Here are the most common parameters you'll use:

Parameter Description Example
package (Required) The name of the package where the executable is located. package='my_python_pkg'
executable (Required) The name of the executable file (without the .py extension if you use the shebang). executable='my_talker'
name The name of the ROS 2 node. This is the name that will appear in ros2 node list. If not provided, it's usually the executable name. name='my_super_talker'
output Where to redirect the stdout/stderr of the node. 'screen' (default) prints to your terminal. 'log' sends it to the log files. output='screen'
parameters A dictionary or list of dictionaries to pass parameters to the node. parameters=[{'my_param': 123}]
arguments A list of command-line arguments to pass directly to the executable. arguments=['--ros-args', '--log-level', 'info']
remappings A list of tuples to remap topics/services. remappings=[('topic', 'my_custom_topic')]

Advanced Example: Launching Multiple Nodes

A launch file's real power is launching multiple nodes and configuring them together.

Let's add a simple C++ or Python listener node and launch both.

Modified Launch File: my_python_pkg/launch/my_launch_file.py

from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
    # Node 1: Our Python talker
    talker_node = Node(
        package='my_python_pkg',
        executable='my_talker',
        name='talker',
        output='screen'
    )
    # Node 2: A listener node (let's assume it's in the 'demo_nodes_py' package)
    listener_node = Node(
        package='demo_nodes_py',
        executable='listener',
        name='listener',
        output='screen'
    )
    # Return a list of all nodes to be launched
    return LaunchDescription([
        talker_node,
        listener_node
    ])

Now, when you run ros2 launch my_python_pkg my_launch_file.py, you will see the output from both the talker and the listener in the same terminal. The listener will automatically subscribe to the topic published by the talker.


Best Practices

  1. Use launch_ros.actions.Node: Always use this action for ROS 2 nodes. It handles the complexities of starting a node within the ROS 2 environment.

  2. Separate Concerns: Keep your launch logic in .py files and your application logic in your source code (scripts/, src/).

  3. Use launch.substitutions: For making your launch files more flexible and reusable. For example, to get the current user's name:

    from launch.actions import DeclareLaunchArgument
    from launch.substitutions import LaunchConfiguration, PythonExpression
    # In generate_launch_description():
    user_name_arg = DeclareLaunchArgument(
        'user_name',
        default_value='default_user'
    )
    talker_node = Node(
        # ...
        parameters=[{
            'greeting': PythonExpression(['"Hello from ", user_name, "!"]')],
            'user_name': LaunchConfiguration('user_name')
        }]
    )
    return LaunchDescription([
        user_name_arg,
        talker_node
    ])
    # To run with a custom user name:
    # ros2 launch my_python_pkg my_launch_file.py user_name:=Alice
  4. Organize with IncludeLaunchDescription: For complex systems, break your launch files into smaller, reusable parts and include them using IncludeLaunchDescription. This is the ROS 2 equivalent of the old <include> tag in ROS 1.

分享:
扫描分享到社交APP
上一篇
下一篇