From 5917c718168e7e4abb252c258f4887683fdec888 Mon Sep 17 00:00:00 2001 From: Fernando Cladera Date: Tue, 3 Mar 2026 11:49:05 -0500 Subject: [PATCH 1/2] ci: add ROS 2 build workflow for humble and jazzy - Matrix build across humble and jazzy distros - colcon build + colcon test - Install smach dependency for test_synchronize_channel --- .github/workflows/build.yaml | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3a59447..a60031d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,10 +1,11 @@ -# ROS build pipeline based on kr_mav_control build -# https://github.com/KumarRobotics/kr_mav_control/blob/master/.github/workflows/build.yml +# ROS 2 build pipeline name: build on: push: - branches: [main] + branches: [ros2] + pull_request: + branches: [ros2] workflow_dispatch: schedule: - cron: '0 0 * * 0' @@ -13,37 +14,28 @@ jobs: build: strategy: matrix: - ros_distro: [noetic] + ros_distro: [humble, jazzy] runs-on: ubuntu-latest container: osrf/ros:${{ matrix.ros_distro }}-desktop steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Apt dependencies run: | apt-get update - apt-get install -qy g++ libeigen3-dev git python3-catkin-tools - apt-get install -qy python3-colorama python3-zmq python3-lz4 + apt-get install -qy python3-colcon-common-extensions python3-rosdep + apt-get install -qy python3-colorama python3-zmq python3-lz4 python3-pytest ros-${ROS_DISTRO}-smach rosdep update rosdep install --from-paths . --ignore-src -y -r --as-root apt:false - - name: Setup catkin workspace - run: | - . /opt/ros/${{ matrix.ros_distro }}/setup.sh - mkdir -p ${RUNNER_WORKSPACE}/catkin_ws/src - cd ${RUNNER_WORKSPACE}/catkin_ws - catkin init - catkin build -j2 --no-status -DCMAKE_BUILD_TYPE=Release - - name: Build workspace run: | . /opt/ros/${{ matrix.ros_distro }}/setup.sh - cd ${RUNNER_WORKSPACE}/catkin_ws/src - ln -s ${GITHUB_WORKSPACE} - catkin build -j2 --no-status -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=17 + colcon build --event-handlers console_direct+ - name: Run Tests run: | - cd ${RUNNER_WORKSPACE}/catkin_ws/src/MOCHA/mocha_core/scripts/core/test - ./run_tests.sh ${RUNNER_WORKSPACE}/catkin_ws + . /opt/ros/${{ matrix.ros_distro }}/setup.sh + colcon test --event-handlers console_direct+ + colcon test-result --verbose From f6bdb2a621e2507e108685e4045308a04fbe214e Mon Sep 17 00:00:00 2001 From: Fernando Cladera Date: Tue, 3 Mar 2026 11:49:09 -0500 Subject: [PATCH 2/2] style: fix pep257, flake8, and import ordering issues - Fix pep257 docstring formatting in launch files - Fix flake8 line length, whitespace, unused imports - Fix import ordering and single quotes for jazzy compatibility --- .../interface_rajant/rajant_peer_rssi.py | 195 +++++++++++------- .../launch/rajant_nodes.launch.py | 19 +- interface_rajant/setup.py | 28 +-- mocha_launch/launch/basestation.launch.py | 23 +-- mocha_launch/launch/jackal.launch.py | 23 +-- mocha_launch/launch/titan.launch.py | 23 +-- 6 files changed, 168 insertions(+), 143 deletions(-) diff --git a/interface_rajant/interface_rajant/rajant_peer_rssi.py b/interface_rajant/interface_rajant/rajant_peer_rssi.py index d956798..01a3cb2 100755 --- a/interface_rajant/interface_rajant/rajant_peer_rssi.py +++ b/interface_rajant/interface_rajant/rajant_peer_rssi.py @@ -1,31 +1,33 @@ #!/usr/bin/env python3 -import rclpy -from rclpy.executors import MultiThreadedExecutor -from rclpy.node import Node -import threading -import pdb +from collections import deque import os -import time +import queue import signal -import yaml import subprocess import sys -import queue +import threading +import time + +import rclpy +from rclpy.executors import MultiThreadedExecutor +from rclpy.node import Node import std_msgs.msg -from collections import deque +import yaml ON_POSIX = 'posix' in sys.builtin_module_names + def ping(host): - command = ["ping", "-c", "1", host] + command = ['ping', '-c', '1', host] try: result = subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) return result.returncode == 0 except Exception as e: - print(f"Error pinging {host}: {e}") + print(f'Error pinging {host}: {e}') return False + class PeerPublisher(): # QUEUE_LENGTH is used to filter repeated RSSI QUEUE_LENGTH = 3 @@ -44,8 +46,9 @@ def __init__(self, target_name, ros_node): self.repeated_counter = 0 # Create a publisher for the node - topic_name = f"mocha/rajant/rssi/{self.target_name}" - self.ros_node.get_logger().info(f"{ros_node.this_robot} - Rajant Peer RSSI - Topic /{topic_name} created") + topic_name = f'mocha/rajant/rssi/{self.target_name}' + self.ros_node.get_logger().info( + f'{ros_node.this_robot} - Rajant Peer RSSI - Topic /{topic_name} created') self.pub = self.ros_node.create_publisher(std_msgs.msg.Int32, topic_name, 10) @@ -57,18 +60,26 @@ def filter_rssi(self, ts, rssi): def publish_all(self, ts): # Skip if we did not collect info for this node in this session if self.last_registered_timestamp is None: - return + return # Check that current end timestamp and msg timestamps agree if ts != self.last_registered_timestamp: - self.ros_node.get_logger().error(f"{self.ros_node.this_robot} - Rajant Peer RSSI - Timestamp of end message different than last registered timestamp in publish_all") + self.ros_node.get_logger().error( + f'{self.ros_node.this_robot} - Rajant Peer RSSI' + ' - Timestamp of end message different than' + ' last registered timestamp in publish_all') return # Verify that all the timestamps are the same for all the radios all_ts = [i[0] for i in self.rssi_ts] if not len(all_ts): - self.ros_node.get_logger().error(f"{self.ros_node.this_robot} - Rajant Peer RSSI - Empty list of timestamps in publish_all.") + self.ros_node.get_logger().error( + f'{self.ros_node.this_robot} - Rajant Peer RSSI' + ' - Empty list of timestamps in publish_all.') return if len(set(all_ts)) != 1: - self.ros_node.get_logger().error(f"{self.ros_node.this_robot} - Rajant Peer RSSI - Multiple different timestamps for the same group in publish_all.") + self.ros_node.get_logger().error( + f'{self.ros_node.this_robot} - Rajant Peer RSSI' + ' - Multiple different timestamps for the' + ' same group in publish_all.') return # Find out the largest RSSI and sum of RSSI @@ -96,13 +107,18 @@ def publish_all(self, ts): # # print(self.published_rssi_queue, set(self.published_rssi_queue)) if len(set(self.published_rssi_queue)) == 1 and \ - len(self.published_rssi_queue) == self.QUEUE_LENGTH: + len(self.published_rssi_queue) == self.QUEUE_LENGTH: if self.repeated_counter < 4: self.repeated_counter += 1 - self.ros_node.get_logger().debug(f"{self.ros_node.this_robot} - Rajant Peer RSSI - Repeated RSSI for {self.target_name} for the last {self.QUEUE_LENGTH*3} seconds. Throttling counter {self.repeated_counter}") + self.ros_node.get_logger().debug( + f'{self.ros_node.this_robot} - Rajant Peer' + f' RSSI - Repeated RSSI for {self.target_name}' + f' for the last {self.QUEUE_LENGTH*3} seconds.' + f' Throttling counter {self.repeated_counter}') return - self.ros_node.get_logger().debug(f"{self.ros_node.this_robot} - Rajant Peer RSSI - Publishing {self.target_name}") + self.ros_node.get_logger().debug( + f'{self.ros_node.this_robot} - Rajant Peer RSSI - Publishing {self.target_name}') self.repeated_counter = 0 msg = std_msgs.msg.Int32() msg.data = max_rssi @@ -111,7 +127,7 @@ def publish_all(self, ts): class RajantPeerRSSI(Node): def __init__(self): - super().__init__("rajant_peer_rssi") + super().__init__('rajant_peer_rssi') self.logger = self.get_logger() # Handle shutdown signal @@ -120,78 +136,89 @@ def __init__(self): def signal_handler(sig, frame): if not self.shutdownTriggered.is_set(): - self.logger.warning(f"{self.this_robot} - Rajant Peer RSSI - Got SIGINT. Triggering shutdown.") + self.logger.warning( + f'{self.this_robot} - Rajant Peer RSSI - Got SIGINT. Triggering shutdown.') self.shutdown() signal.signal(signal.SIGINT, signal_handler) # Declare parameters - self.declare_parameter("robot_name", "") - self.declare_parameter("robot_configs", "") - self.declare_parameter("radio_configs", "") - self.declare_parameter("bcapi_jar_file", "") + self.declare_parameter('robot_name', '') + self.declare_parameter('robot_configs', '') + self.declare_parameter('radio_configs', '') + self.declare_parameter('bcapi_jar_file', '') - self.this_robot = self.get_parameter("robot_name").get_parameter_value().string_value + self.this_robot = self.get_parameter('robot_name').get_parameter_value().string_value if len(self.this_robot) == 0: - self.logger.error(f"{self.this_robot} - Rajant Peer RSSI - Empty robot name") - raise ValueError("Empty robot name") + self.logger.error(f'{self.this_robot} - Rajant Peer RSSI - Empty robot name') + raise ValueError('Empty robot name') # Load and check robot configs - self.robot_configs_file = self.get_parameter("robot_configs").get_parameter_value().string_value + self.robot_configs_file = self.get_parameter( + 'robot_configs').get_parameter_value().string_value try: - with open(self.robot_configs_file, "r") as f: + with open(self.robot_configs_file, 'r') as f: self.robot_configs = yaml.load(f, Loader=yaml.FullLoader) except Exception as e: - self.logger.error(f"{self.this_robot} - Rajant Peer RSSI - robot_configs file") + self.logger.error(f'{self.this_robot} - Rajant Peer RSSI - robot_configs file') raise e if self.this_robot not in self.robot_configs.keys(): - self.logger.error(f"{self.this_robot} - Rajant Peer RSSI - robot_configs file") - raise ValueError("Robot not in config file") + self.logger.error(f'{self.this_robot} - Rajant Peer RSSI - robot_configs file') + raise ValueError('Robot not in config file') # Load and check radio configs - self.radio_configs_file = self.get_parameter("radio_configs").get_parameter_value().string_value + self.radio_configs_file = self.get_parameter( + 'radio_configs').get_parameter_value().string_value try: - with open(self.radio_configs_file, "r") as f: + with open(self.radio_configs_file, 'r') as f: self.radio_configs = yaml.load(f, Loader=yaml.FullLoader) except Exception as e: - self.logger.error(f"{self.this_robot} - Rajant Peer RSSI - radio_configs file") + self.logger.error(f'{self.this_robot} - Rajant Peer RSSI - radio_configs file') raise e - self.radio = self.robot_configs[self.this_robot]["using-radio"] + self.radio = self.robot_configs[self.this_robot]['using-radio'] if self.radio not in self.radio_configs.keys(): - self.logger.error(f"{self.this_robot} - Rajant Peer RSSI - radio_configs file") - raise ValueError("Radio {self.radio} not in config file") + self.logger.error(f'{self.this_robot} - Rajant Peer RSSI - radio_configs file') + raise ValueError('Radio {self.radio} not in config file') # Get the location of the jar file for bcapi - self.bcapi_jar_file = self.get_parameter("bcapi_jar_file").get_parameter_value().string_value + self.bcapi_jar_file = self.get_parameter( + 'bcapi_jar_file').get_parameter_value().string_value if not (os.path.isfile(self.bcapi_jar_file) and self.bcapi_jar_file.endswith('.jar')): - self.get_logger().error(f"{self.this_robot} - Rajant Peer RSSI - Erroneous BCAPI jar file") - raise ValueError(f"Erroneous BCAPI file") + self.get_logger().error( + f'{self.this_robot} - Rajant Peer RSSI - Erroneous BCAPI jar file') + raise ValueError('Erroneous BCAPI file') # Get the target ip for the local rajant rajant_name = self.robot_configs[self.this_robot]['using-radio'] if rajant_name in self.radio_configs.keys(): self.target_ip = self.radio_configs[rajant_name]['computed-IP-address'] else: - self.get_logger().error(f"{self.this_robot} - Rajant Peer RSSI - Radio {rajant_name} for robot {self.this_robot} not found in configs") - raise ValueError(f"Radio {rajant_name} for robot {self.this_robot} not found in configs") + self.get_logger().error( + f'{self.this_robot} - Rajant Peer RSSI' + f' - Radio {rajant_name} for robot' + f' {self.this_robot} not found in configs') + raise ValueError( + f'Radio {rajant_name} for robot' + f' {self.this_robot} not found in configs') # Ping the local rajant if not ping(self.target_ip): - self.get_logger().error(f"{self.this_robot} - Rajant Peer RSSI - Failed to ping {self.target_ip}") - raise ValueError(f"Failed to ping {self.target_ip}") + self.get_logger().error( + f'{self.this_robot} - Rajant Peer RSSI - Failed to ping {self.target_ip}') + raise ValueError(f'Failed to ping {self.target_ip}') # Create the publishers for the peers self.peers = {} - for peer in self.robot_configs[self.this_robot]["clients"]: + for peer in self.robot_configs[self.this_robot]['clients']: # Index peer by computed IP - peer_radio = self.robot_configs[peer]["using-radio"] - computed_ip = self.radio_configs[peer_radio]["computed-IP-address"] + peer_radio = self.robot_configs[peer]['using-radio'] + computed_ip = self.radio_configs[peer_radio]['computed-IP-address'] self.peers[computed_ip] = PeerPublisher(peer, self) # Invert radio lookup - self.ip_to_radio = {self.radio_configs[radio]["computed-IP-address"]: radio - for radio in self.radio_configs} + self.ip_to_radio = {self.radio_configs[radio]['computed-IP-address']: radio + for radio in self.radio_configs} # Start the java program and thread to read output self.start_java_process_and_queue() @@ -215,8 +242,7 @@ def shutdown(self): self.enqueue_thread.join() def enqueue_output(self): - """ Saves the output of the process in a queue to be parsed - afterwards """ + """Save the output of the process in a queue to be parsed afterwards.""" for line in self.java_process.stdout: self.process_queue.put(line) # If the java process dies, we will reach the end of the thread @@ -227,12 +253,16 @@ def process_output(self): while not self.process_thread_shutdown.is_set(): if self.enqueue_thread is not None and not self.enqueue_thread.is_alive(): time.sleep(1) - self.get_logger().error(f"{self.this_robot} - Rajant Peer RSSI - Java process died, restarting") + self.get_logger().error( + f'{self.this_robot} - Rajant Peer RSSI - Java process died, restarting') self.start_java_process_and_queue() restart_count += 1 if restart_count == 5: # shutdown - self.get_logger().error(f"{self.this_robot} - Rajant Peer RSSI - Java process died too many times. Killing node.") + self.get_logger().error( + f'{self.this_robot} - Rajant Peer RSSI' + ' - Java process died too many times.' + ' Killing node.') sys.exit(1) continue try: @@ -241,27 +271,27 @@ def process_output(self): # No data, just continue the loop continue # Data comes in lines. Decide what to do based on the output - if data == "\n": + if data == '\n': continue - elif data == "ERR\n": + elif data == 'ERR\n': self.java_process.terminate() continue - elif "END," in data: + elif 'END,' in data: # End of transmission, send messages - data = data.replace("END,", "") - data = data.replace(";\n", "") + data = data.replace('END,', '') + data = data.replace(';\n', '') end_ts = int(data) for peer in self.peers: self.peers[peer].publish_all(end_ts) continue # Process regular messages - data = data.replace(";\n","") # Remove end line - ts, iface, peer, rssi = data.split(",") + data = data.replace(';\n', '') # Remove end line + ts, iface, peer, rssi = data.split(',') # Cleanup things - ts = int(ts.replace("Ts:", "")) - iface = iface.replace("Iface:", "") - peer = peer.replace("Peer:", "") - rssi = int(rssi.replace("RSSI:", "")) + ts = int(ts.replace('Ts:', '')) + iface = iface.replace('Iface:', '') + peer = peer.replace('Peer:', '') + rssi = int(rssi.replace('RSSI:', '')) # Let the right peer handle it if peer in self.peers: self.peers[peer].filter_rssi(ts, rssi) @@ -269,22 +299,29 @@ def process_output(self): # Discover the rogue peer with the radio if peer in self.ip_to_radio: rogue_radio = self.ip_to_radio[peer] - self.get_logger().debug(f"{self.this_robot} - Rajant Peer RSSI - Peer with radio {rogue_radio} not assigned to any robot") + self.get_logger().debug( + f'{self.this_robot} - Rajant Peer RSSI' + f' - Peer with radio {rogue_radio}' + ' not assigned to any robot') else: - self.get_logger().debug(f"{self.this_robot} - Rajant Peer RSSI - Peer with IP {peer} not assigned to any robot") - - + self.get_logger().debug( + f'{self.this_robot} - Rajant Peer RSSI' + f' - Peer with IP {peer}' + ' not assigned to any robot') def start_java_process_and_queue(self): # Subprocess to run the java BCAPI interface - self.get_logger().info(f"{self.this_robot} - Rajant Peer RSSI - Starting Java Process for IP {self.target_ip}") + self.get_logger().info( + f'{self.this_robot} - Rajant Peer RSSI' + f' - Starting Java Process for IP {self.target_ip}') # Run process in its own separate process group so it does not get # SIGINT. We will handle that ourselves popen_kwargs = {} popen_kwargs['preexec_fn'] = os.setpgrp - self.java_process = subprocess.Popen(['java', '-jar', self.bcapi_jar_file, - self.target_ip], stdout=subprocess.PIPE, close_fds=ON_POSIX, - text=True, **popen_kwargs) + self.java_process = subprocess.Popen( + ['java', '-jar', self.bcapi_jar_file, self.target_ip], + stdout=subprocess.PIPE, close_fds=ON_POSIX, + text=True, **popen_kwargs) self.process_queue = queue.Queue() self.enqueue_thread = threading.Thread(target=self.enqueue_output, args=()) self.enqueue_thread.start() @@ -296,7 +333,7 @@ def main(args=None): try: rajant_peer_rssi_node = RajantPeerRSSI() except Exception as e: - print(f"Node initialization failed: {e}") + print(f'Node initialization failed: {e}') rclpy.shutdown() return @@ -310,11 +347,11 @@ def main(args=None): mtexecutor.spin_once(timeout_sec=0.1) except KeyboardInterrupt: rajant_peer_rssi_node.shutdown() - print("Keyboard interrupt") + print('Keyboard interrupt') except Exception as e: - print(f"Exception: {e}") + print(f'Exception: {e}') rajant_peer_rssi_node.shutdown() -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/interface_rajant/launch/rajant_nodes.launch.py b/interface_rajant/launch/rajant_nodes.launch.py index bdc90cd..dfb3934 100644 --- a/interface_rajant/launch/rajant_nodes.launch.py +++ b/interface_rajant/launch/rajant_nodes.launch.py @@ -8,17 +8,14 @@ def generate_launch_description(): - """ - Launch Rajant interface nodes (query and parser) - """ - + """Launch Rajant interface nodes (query and parser).""" # Declare launch arguments robot_name_arg = DeclareLaunchArgument( 'robot_name', default_value='charon', description='Name of the robot' ) - + robot_configs_arg = DeclareLaunchArgument( 'robot_configs', default_value=PathJoinSubstitution([ @@ -27,7 +24,7 @@ def generate_launch_description(): ]), description='Path to robot configuration file' ) - + radio_configs_arg = DeclareLaunchArgument( 'radio_configs', default_value=PathJoinSubstitution([ @@ -36,12 +33,12 @@ def generate_launch_description(): ]), description='Path to radio configuration file' ) - + # Get launch configurations robot_name = LaunchConfiguration('robot_name') robot_configs = LaunchConfiguration('robot_configs') radio_configs = LaunchConfiguration('radio_configs') - + # Define nodes rajant_query_node = Node( package='interface_rajant', @@ -54,7 +51,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }] ) - + rajant_parser_node = Node( package='interface_rajant', executable='rajant_parser.py', @@ -66,11 +63,11 @@ def generate_launch_description(): 'radio_configs': radio_configs }] ) - + return LaunchDescription([ robot_name_arg, robot_configs_arg, radio_configs_arg, rajant_query_node, rajant_parser_node - ]) \ No newline at end of file + ]) diff --git a/interface_rajant/setup.py b/interface_rajant/setup.py index 8260bd0..5b4cb26 100644 --- a/interface_rajant/setup.py +++ b/interface_rajant/setup.py @@ -1,27 +1,27 @@ from setuptools import setup -package_name = "interface_rajant" +package_name = 'interface_rajant' setup( name=package_name, - version="0.0.0", + version='0.0.0', packages=[package_name], data_files=[ - ("share/ament_index/resource_index/packages", ["resource/" + package_name]), - ("share/" + package_name, ["package.xml"]), - ("share/" + package_name + "/launch", ["launch/rajant_nodes.launch.py"]), - ("share/" + package_name + "/thirdParty", ["thirdParty/PeerRSSI-bcapi-11.26.1.jar"]), + ('share/ament_index/resource_index/packages', ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', ['launch/rajant_nodes.launch.py']), + ('share/' + package_name + '/thirdParty', ['thirdParty/PeerRSSI-bcapi-11.26.1.jar']), ], - install_requires=["setuptools"], + install_requires=['setuptools'], zip_safe=True, - maintainer="Fernando Cladera", - maintainer_email="fclad@seas.upenn.edu", - description="The interface_rajant package", - license="BSD 3-Clause License", - tests_require=["pytest"], + maintainer='Fernando Cladera', + maintainer_email='fclad@seas.upenn.edu', + description='The interface_rajant package', + license='BSD 3-Clause License', + tests_require=['pytest'], entry_points={ - "console_scripts": [ - "rajant_peer_rssi = interface_rajant.rajant_peer_rssi:main", + 'console_scripts': [ + 'rajant_peer_rssi = interface_rajant.rajant_peer_rssi:main', ], }, ) diff --git a/mocha_launch/launch/basestation.launch.py b/mocha_launch/launch/basestation.launch.py index 101e09a..18a9159 100644 --- a/mocha_launch/launch/basestation.launch.py +++ b/mocha_launch/launch/basestation.launch.py @@ -8,17 +8,14 @@ def generate_launch_description(): - """ - Launch basestation robot with database, translators, publishers, and Rajant interface - """ - + """Launch basestation robot with database, translators, publishers, and Rajant interface.""" # Declare launch arguments robot_name_arg = DeclareLaunchArgument( 'robot_name', default_value='basestation', description='Name of the robot' ) - + robot_configs_arg = DeclareLaunchArgument( 'robot_configs', default_value=PathJoinSubstitution([ @@ -27,16 +24,16 @@ def generate_launch_description(): ]), description='Path to robot configuration file' ) - + topic_configs_arg = DeclareLaunchArgument( - 'topic_configs', + 'topic_configs', default_value=PathJoinSubstitution([ FindPackageShare('mocha_core'), 'config', 'topic_configs.yaml' ]), description='Path to topic configuration file' ) - + radio_configs_arg = DeclareLaunchArgument( 'radio_configs', default_value=PathJoinSubstitution([ @@ -45,13 +42,13 @@ def generate_launch_description(): ]), description='Path to radio configuration file' ) - + # Get launch configurations robot_name = LaunchConfiguration('robot_name') robot_configs = LaunchConfiguration('robot_configs') topic_configs = LaunchConfiguration('topic_configs') radio_configs = LaunchConfiguration('radio_configs') - + # Include database, translators and publishers launch file database_translators_publishers_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([ @@ -68,7 +65,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }.items() ) - + # Include Rajant interface launch file rajant_interface_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([ @@ -85,7 +82,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }.items() ) - + return LaunchDescription([ robot_name_arg, robot_configs_arg, @@ -93,4 +90,4 @@ def generate_launch_description(): radio_configs_arg, database_translators_publishers_launch, rajant_interface_launch - ]) \ No newline at end of file + ]) diff --git a/mocha_launch/launch/jackal.launch.py b/mocha_launch/launch/jackal.launch.py index b2131ef..ec813db 100644 --- a/mocha_launch/launch/jackal.launch.py +++ b/mocha_launch/launch/jackal.launch.py @@ -8,17 +8,14 @@ def generate_launch_description(): - """ - Launch jackal robot (callisto) with database, translators, publishers, and Rajant interface - """ - + """Launch jackal robot (callisto) with database, translators, publishers.""" # Declare launch arguments robot_name_arg = DeclareLaunchArgument( 'robot_name', default_value='callisto', description='Name of the robot' ) - + robot_configs_arg = DeclareLaunchArgument( 'robot_configs', default_value=PathJoinSubstitution([ @@ -27,16 +24,16 @@ def generate_launch_description(): ]), description='Path to robot configuration file' ) - + topic_configs_arg = DeclareLaunchArgument( - 'topic_configs', + 'topic_configs', default_value=PathJoinSubstitution([ FindPackageShare('mocha_core'), 'config', 'topic_configs.yaml' ]), description='Path to topic configuration file' ) - + radio_configs_arg = DeclareLaunchArgument( 'radio_configs', default_value=PathJoinSubstitution([ @@ -45,13 +42,13 @@ def generate_launch_description(): ]), description='Path to radio configuration file' ) - + # Get launch configurations robot_name = LaunchConfiguration('robot_name') robot_configs = LaunchConfiguration('robot_configs') topic_configs = LaunchConfiguration('topic_configs') radio_configs = LaunchConfiguration('radio_configs') - + # Include database, translators and publishers launch file database_translators_publishers_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([ @@ -68,7 +65,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }.items() ) - + # Include Rajant interface launch file rajant_interface_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([ @@ -85,7 +82,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }.items() ) - + return LaunchDescription([ robot_name_arg, robot_configs_arg, @@ -93,4 +90,4 @@ def generate_launch_description(): radio_configs_arg, database_translators_publishers_launch, rajant_interface_launch - ]) \ No newline at end of file + ]) diff --git a/mocha_launch/launch/titan.launch.py b/mocha_launch/launch/titan.launch.py index f367267..f26eb88 100644 --- a/mocha_launch/launch/titan.launch.py +++ b/mocha_launch/launch/titan.launch.py @@ -8,17 +8,14 @@ def generate_launch_description(): - """ - Launch titan robot with database, translators, publishers, and Rajant interface - """ - + """Launch titan robot with database, translators, publishers, and Rajant interface.""" # Declare launch arguments robot_name_arg = DeclareLaunchArgument( 'robot_name', default_value='titan', description='Name of the robot' ) - + robot_configs_arg = DeclareLaunchArgument( 'robot_configs', default_value=PathJoinSubstitution([ @@ -27,16 +24,16 @@ def generate_launch_description(): ]), description='Path to robot configuration file' ) - + topic_configs_arg = DeclareLaunchArgument( - 'topic_configs', + 'topic_configs', default_value=PathJoinSubstitution([ FindPackageShare('mocha_core'), 'config', 'topic_configs.yaml' ]), description='Path to topic configuration file' ) - + radio_configs_arg = DeclareLaunchArgument( 'radio_configs', default_value=PathJoinSubstitution([ @@ -45,13 +42,13 @@ def generate_launch_description(): ]), description='Path to radio configuration file' ) - + # Get launch configurations robot_name = LaunchConfiguration('robot_name') robot_configs = LaunchConfiguration('robot_configs') topic_configs = LaunchConfiguration('topic_configs') radio_configs = LaunchConfiguration('radio_configs') - + # Include database, translators and publishers launch file database_translators_publishers_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([ @@ -68,7 +65,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }.items() ) - + # Include Rajant interface launch file rajant_interface_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([ @@ -85,7 +82,7 @@ def generate_launch_description(): 'radio_configs': radio_configs }.items() ) - + return LaunchDescription([ robot_name_arg, robot_configs_arg, @@ -93,4 +90,4 @@ def generate_launch_description(): radio_configs_arg, database_translators_publishers_launch, rajant_interface_launch - ]) \ No newline at end of file + ])