diff --git a/README.md b/README.md index 66e8bb9f..4c1bb6bf 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,16 @@ All packages to be installed on the pi compute module live in the `pi` directory All packages to be installed on the float live in the `float` directory. +## Namespaces + +All nodes running on the pi will be in the pi namespace. + +All nodes running on the surface will be in the surface namespace. + +Any topics or services communicating across will be renamed first into the tether namespace. + +![Picture of rqt with namespaces](/doc/images/namespaces.png) + ## Documentation Structure Documentation will take place at 3 levels: diff --git a/doc/images/namespaces.png b/doc/images/namespaces.png new file mode 100644 index 00000000..7ae83e0d Binary files /dev/null and b/doc/images/namespaces.png differ diff --git a/src/pi/camera_streamer/launch/camera_launch.py b/src/pi/camera_streamer/launch/camera_launch.py index 3b1b58cb..6bdafa40 100644 --- a/src/pi/camera_streamer/launch/camera_launch.py +++ b/src/pi/camera_streamer/launch/camera_launch.py @@ -20,7 +20,7 @@ def generate_launch_description() -> LaunchDescription: {"image_size": [640, 480]}, {"time_per_frame": [1, 30]} ], - remappings=[("/pi/front_cam/image_raw", "/front_cam/image_raw")], + remappings=[("/pi/front_cam/image_raw", "/tether/front_cam/image_raw")], emulate_tty=True, output='screen' ) @@ -37,7 +37,7 @@ def generate_launch_description() -> LaunchDescription: {"image_size": [640, 480]}, {"time_per_frame": [1, 30]} ], - remappings=[("/pi/bottom_cam/image_raw", "/bottom_cam/image_raw")], + remappings=[("/pi/bottom_cam/image_raw", "/tether/bottom_cam/image_raw")], emulate_tty=True, output='screen' ) diff --git a/src/pi/pi_main/launch/pi_launch.py b/src/pi/pi_main/launch/pi_launch.py index 935bc1bf..a1e5ce48 100644 --- a/src/pi/pi_main/launch/pi_launch.py +++ b/src/pi/pi_main/launch/pi_launch.py @@ -10,15 +10,15 @@ def generate_launch_description() -> LaunchDescription: NS = 'pi' # Manipulator Controller - manip_path: str = get_package_share_directory('manipulators') - - manip_launch = IncludeLaunchDescription( - PythonLaunchDescriptionSource([ - os.path.join( - manip_path, 'launch', 'manip_launch.py' - ) - ]) - ) + # manip_path: str = get_package_share_directory('manipulators') + # + # manip_launch = IncludeLaunchDescription( + # PythonLaunchDescriptionSource([ + # os.path.join( + # manip_path, 'launch', 'manip_launch.py' + # ) + # ]) + # ) # Camera Streamer cam_path: str = get_package_share_directory('camera_streamer') @@ -57,7 +57,7 @@ def generate_launch_description() -> LaunchDescription: namespace_launch = GroupAction( actions=[ PushRosNamespace(NS), - manip_launch, + # manip_launch, pixhawk_launch, cam_launch, # realsense_launch diff --git a/src/pi/pixhawk_communication/launch/mavros_launch.py b/src/pi/pixhawk_communication/launch/mavros_launch.py index b58742e0..796cf701 100644 --- a/src/pi/pixhawk_communication/launch/mavros_launch.py +++ b/src/pi/pixhawk_communication/launch/mavros_launch.py @@ -19,8 +19,8 @@ def generate_launch_description() -> LaunchDescription: {"plugin_allowlist": ["sys_status", "rc_io", "command"]}, {"fcu_url": "/dev/ttyPixhawk"} ], - remappings=[('/pi/mavros/rc/override', '/mavros/rc/override'), - ('/pi/mavros/cmd/arming', '/mavros/cmd/arming')] + remappings=[('/pi/mavros/rc/override', '/tether/mavros/rc/override'), + ('/pi/mavros/cmd/arming', '/tether/mavros/cmd/arming')] ) return LaunchDescription([ diff --git a/src/surface/gui/gui/event_nodes/client.py b/src/surface/gui/gui/event_nodes/client.py index 46fee109..90fcc24d 100644 --- a/src/surface/gui/gui/event_nodes/client.py +++ b/src/surface/gui/gui/event_nodes/client.py @@ -17,7 +17,7 @@ class GUIEventClient(Node): def __init__(self, srv_type: SrvType, topic: str, signal: pyqtBoundSignal): # Name this node with a sanitized version of the topic - self.name: str = f'client{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' + self.name: str = f'client_{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' super().__init__(self.name, parameter_overrides=[]) self.srv_type = srv_type diff --git a/src/surface/gui/gui/event_nodes/publisher.py b/src/surface/gui/gui/event_nodes/publisher.py index ad2c7b73..dd4d5876 100644 --- a/src/surface/gui/gui/event_nodes/publisher.py +++ b/src/surface/gui/gui/event_nodes/publisher.py @@ -11,7 +11,7 @@ class GUIEventPublisher(Node): def __init__(self, msg_type: MsgType, topic: str, qos_profile: QoSProfile = qos_profile_system_default) -> None: # Name this node with a sanitized version of the topic - name: str = f'publisher{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' + name: str = f'publisher_{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' super().__init__(name, parameter_overrides=[]) self.publisher = self.create_publisher(msg_type, topic, qos_profile) diff --git a/src/surface/gui/gui/event_nodes/server.py b/src/surface/gui/gui/event_nodes/server.py index 189fdce3..cf5df851 100644 --- a/src/surface/gui/gui/event_nodes/server.py +++ b/src/surface/gui/gui/event_nodes/server.py @@ -19,7 +19,7 @@ def __init__(self, srv_type: SrvType, topic: str, Remember to use a signal to update the GUI! """ # Name this node with a sanitized version of the topic - name: str = f'server{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' + name: str = f'server_{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' super().__init__(name, parameter_overrides=[]) self.srv: Service = self.create_service(srv_type, topic, callback) diff --git a/src/surface/gui/gui/event_nodes/subscriber.py b/src/surface/gui/gui/event_nodes/subscriber.py index b73ca79f..f2a96f39 100644 --- a/src/surface/gui/gui/event_nodes/subscriber.py +++ b/src/surface/gui/gui/event_nodes/subscriber.py @@ -14,7 +14,7 @@ class GUIEventSubscriber(Node): def __init__(self, msg_type: type, topic: str, signal: pyqtBoundSignal, qos_profile: QoSProfile = qos_profile_system_default): # Name this node with a sanitized version of the topic - name: str = f'subscriber{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' + name: str = f'subscriber_{re.sub(r"[^a-zA-Z0-9_]", "_", topic)}' super().__init__(name, parameter_overrides=[]) self.subscription = self.create_subscription( diff --git a/src/surface/gui/gui/pilot_app.py b/src/surface/gui/gui/pilot_app.py index 2ee2a62d..7c5e4e90 100644 --- a/src/surface/gui/gui/pilot_app.py +++ b/src/surface/gui/gui/pilot_app.py @@ -14,13 +14,13 @@ def __init__(self) -> None: layout: QHBoxLayout = QHBoxLayout() self.setLayout(layout) - self.video_area = SwitchableVideoWidget(["/front_cam/image_raw", - "/bottom_cam/image_raw", - "/camera/color/image_raw"], + self.video_area = SwitchableVideoWidget(["front_cam/image_raw", + "bottom_cam/image_raw", + "camera/color/image_raw"], ["Front Camera", "Bottom Camera", "Depth Camera"], - "/camera_switch") + "camera_switch") layout.addWidget(self.video_area, alignment=Qt.AlignmentFlag.AlignCenter) self.arm: Arm = Arm() diff --git a/src/surface/gui/gui/widgets/arm.py b/src/surface/gui/gui/widgets/arm.py index c77aa167..0875f655 100644 --- a/src/surface/gui/gui/widgets/arm.py +++ b/src/surface/gui/gui/widgets/arm.py @@ -48,7 +48,7 @@ def __init__(self) -> None: self.arm_client: GUIEventClient = GUIEventClient( CommandBool, - "/mavros/cmd/arming", + "mavros/cmd/arming", self.signal ) diff --git a/src/surface/gui/gui/widgets/seagrass.py b/src/surface/gui/gui/widgets/seagrass.py index 2ac464dc..fbb8d51d 100644 --- a/src/surface/gui/gui/widgets/seagrass.py +++ b/src/surface/gui/gui/widgets/seagrass.py @@ -41,7 +41,7 @@ def __init__(self) -> None: before_layout.addStretch() # Bottom cam - self.bottom_cam = PauseableVideoWidget("/bottom_cam/image_raw", "Bottom Cam", + self.bottom_cam = PauseableVideoWidget("bottom_cam/image_raw", "Bottom Cam", widget_width=640, widget_height=360) # After layout diff --git a/src/surface/gui/gui/widgets/task_selector.py b/src/surface/gui/gui/widgets/task_selector.py index 357b2c3a..b7e0be6a 100644 --- a/src/surface/gui/gui/widgets/task_selector.py +++ b/src/surface/gui/gui/widgets/task_selector.py @@ -52,7 +52,7 @@ def __init__(self) -> None: # self.scheduler_response_signal.connect( # self.handle_scheduler_response) self.task_changed_client: GUIEventClient = GUIEventClient( - TaskRequest, '/task_request', self.scheduler_response_signal) + TaskRequest, 'task_request', self.scheduler_response_signal) # Server doesn't spin, so we init in main thread # self.update_task_dropdown_signal.connect(self.update_task_dropdown) diff --git a/src/surface/gui/launch/operator_launch.py b/src/surface/gui/launch/operator_launch.py index 64e603ec..1f9f4dec 100644 --- a/src/surface/gui/launch/operator_launch.py +++ b/src/surface/gui/launch/operator_launch.py @@ -1,6 +1,7 @@ from launch.launch_description import LaunchDescription from launch.substitutions import LaunchConfiguration -from launch_ros.actions import Node +from launch_ros.actions import Node, PushRosNamespace +from launch.actions import GroupAction def generate_launch_description() -> LaunchDescription: @@ -8,11 +9,20 @@ def generate_launch_description() -> LaunchDescription: gui_node: Node = Node( package='gui', executable='run_operator', - namespace='gui', - parameters=[ - {'theme': LaunchConfiguration('theme', default='dark')}], + parameters=[{'theme': LaunchConfiguration('theme', default='dark')}], + remappings=[("/surface/gui/bottom_cam/image_raw", "/tether/bottom_cam/image_raw"), + ("/surface/gui/task_request", "/surface/task_request"), + ("/surface/gui/task_feedback", "/surface/task_feedback") + ], emulate_tty=True, output='screen' ) - return LaunchDescription([gui_node]) + namespace_launch = GroupAction( + actions=[ + PushRosNamespace('gui'), + gui_node + ] + ) + + return LaunchDescription([namespace_launch]) diff --git a/src/surface/gui/launch/pilot_launch.py b/src/surface/gui/launch/pilot_launch.py index 5e43ac20..feffc3d0 100644 --- a/src/surface/gui/launch/pilot_launch.py +++ b/src/surface/gui/launch/pilot_launch.py @@ -1,6 +1,7 @@ +from launch.actions import GroupAction from launch.launch_description import LaunchDescription from launch.substitutions import LaunchConfiguration -from launch_ros.actions import Node +from launch_ros.actions import Node, PushRosNamespace def generate_launch_description() -> LaunchDescription: @@ -8,13 +9,20 @@ def generate_launch_description() -> LaunchDescription: gui_node: Node = Node( package='gui', executable='run_pilot', - namespace='gui', - parameters=[ - {'theme': LaunchConfiguration('theme', default='dark')}], - remappings=[("/surface/gui/mavros/cmd/arming", "/mavros/cmd/arming"), - ("/surface/gui/camera_switch", "/surface/camera_switch")], + parameters=[{'theme': LaunchConfiguration('theme', default='dark')}], + remappings=[("/surface/gui/mavros/cmd/arming", "/tether/mavros/cmd/arming"), + ("/surface/gui/camera_switch", "/surface/camera_switch"), + ("/surface/gui/bottom_cam/image_raw", "/tether/bottom_cam/image_raw"), + ("/surface/gui/front_cam/image_raw", "/tether/front_cam/image_raw")], emulate_tty=True, output='screen' ) - return LaunchDescription([gui_node]) + namespace_launch = GroupAction( + actions=[ + PushRosNamespace('gui'), + gui_node + ] + ) + + return LaunchDescription([namespace_launch]) diff --git a/src/surface/surface_main/launch/surface_operator_launch.py b/src/surface/surface_main/launch/surface_operator_launch.py index 139dc69c..691fa818 100644 --- a/src/surface/surface_main/launch/surface_operator_launch.py +++ b/src/surface/surface_main/launch/surface_operator_launch.py @@ -31,7 +31,7 @@ def generate_launch_description() -> LaunchDescription: namespace_launch = GroupAction( actions=[ - PushRosNamespace("/surface"), + PushRosNamespace("surface"), gui_launch, task_selector_launch, ] diff --git a/src/surface/surface_main/launch/surface_pilot_launch.py b/src/surface/surface_main/launch/surface_pilot_launch.py index d0d4d34f..6e55f1a5 100644 --- a/src/surface/surface_main/launch/surface_pilot_launch.py +++ b/src/surface/surface_main/launch/surface_pilot_launch.py @@ -31,7 +31,7 @@ def generate_launch_description() -> LaunchDescription: namespace_launch = GroupAction( actions=[ - PushRosNamespace("/surface"), + PushRosNamespace("surface"), gui_launch, controller_launch, ] diff --git a/src/surface/task_selector/launch/task_scheduler_launch.py b/src/surface/task_selector/launch/task_scheduler_launch.py index 4eb649d1..0d2321ac 100644 --- a/src/surface/task_selector/launch/task_scheduler_launch.py +++ b/src/surface/task_selector/launch/task_scheduler_launch.py @@ -16,8 +16,9 @@ def generate_launch_description() -> LaunchDescription: manual_control_node: Node = Node( package='task_selector', executable='manual_control_node', - remappings=[('/surface/manipulator_control', '/manipulator_control'), - ('/surface/mavros/rc/override', '/mavros/rc/override')], + remappings=[('/surface/manipulator_control', '/tether/manipulator_control'), + ('/surface/mavros/rc/override', '/tether/mavros/rc/override'), + ('/tether/mavros/rc/override', '/surface/mavros/rc/override')], emulate_tty=True, output='screen' ) diff --git a/src/surface/task_selector/task_selector/manual_control_node.py b/src/surface/task_selector/task_selector/manual_control_node.py index 96277b26..8a37c813 100644 --- a/src/surface/task_selector/task_selector/manual_control_node.py +++ b/src/surface/task_selector/task_selector/manual_control_node.py @@ -74,7 +74,7 @@ def __init__(self) -> None: ) self.rc_pub: Publisher = self.create_publisher( OverrideRCIn, - '/mavros/rc/override', + 'mavros/rc/override', qos_profile_system_default ) self.subscription: Subscription = self.create_subscription( diff --git a/src/surface/task_selector/task_selector/task_selector.py b/src/surface/task_selector/task_selector/task_selector.py index bada2670..a5301516 100644 --- a/src/surface/task_selector/task_selector/task_selector.py +++ b/src/surface/task_selector/task_selector/task_selector.py @@ -19,10 +19,10 @@ def __init__(self) -> None: # create service to handle requests for task switching self.request_server = self.create_service( - TaskRequest, '/task_request', self.request_task_callback) + TaskRequest, 'task_request', self.request_task_callback) self.feedback_server = self.create_publisher( - TaskFeedback, '/task_feedback', qos_profile_system_default) + TaskFeedback, 'task_feedback', qos_profile_system_default) # instantiates new action clients with inputs of node, # action type, action name