99from rclpy .node import Node
1010from rclpy .qos import qos_profile_system_default
1111
12- from rov_msgs .msg import Heartbeat , Manip , VehicleState
12+ from rov_msgs .msg import Heartbeat , Manip , VehicleState , VideoWidgetSwitch
1313from rov_msgs .srv import VehicleArming
1414
1515os .environ ['MAVLINK20' ] = '1' # Force mavlink 2.0 for pymavlink
@@ -159,6 +159,10 @@ def __init__(self) -> None:
159159 VehicleArming , 'arming' , callback = self .arming_service_callback
160160 )
161161
162+ self .right_stream_switch_publisher = self .create_publisher (
163+ VideoWidgetSwitch , 'switch_right_stream' , qos_profile_system_default
164+ )
165+
162166 self .invert_controls = False
163167
164168 # Unix timestamp of the last mavlink heartbeat from the pi
@@ -178,6 +182,7 @@ def controller_callback(self, joy_state: JoystickState) -> None:
178182 joy_state : JoystickState
179183 The current state of the joystick buttons and axes
180184 """
185+ # MARK: CTRLR CALLBACK
181186 self .process_arming_buttons (joy_state )
182187 self .send_mavlink_control (joy_state )
183188 self .manip_callback (joy_state )
@@ -197,6 +202,7 @@ def joystick_map(raw: float) -> float:
197202 float
198203 The output of the mapping, between -1 and 1
199204 """
205+ # MARK: JOY MAP
200206 return math .copysign (math .fabs (raw ) ** JOY_MAP_STRENGTH , raw ) * GLOBAL_THROTTLE
201207
202208 def send_mavlink_control (self , joy_state : JoystickState ) -> None :
@@ -207,6 +213,7 @@ def send_mavlink_control(self, joy_state: JoystickState) -> None:
207213 joy_state : JoystickState
208214 The state of the joystick buttons and axes
209215 """
216+ # MARK: SEND MAV CTRL
210217 axes = joy_state .axes
211218 buttons = joy_state .buttons
212219
@@ -242,6 +249,7 @@ def manip_callback(self, joy_state: JoystickState) -> None:
242249 joy_state : JoystickState
243250 The state of the joystick buttons and axes
244251 """
252+ # MARK: MANIP CALLBACK
245253 buttons = joy_state .buttons
246254 for button_id , manip_button in self .manip_buttons .items ():
247255 just_pressed = buttons [button_id ] == PRESSED
@@ -261,6 +269,7 @@ def set_armed(self, *, arm: bool) -> None:
261269 arm : bool
262270 Whether the vehicle should be armed (True) or disarmed (False)
263271 """
272+ # MARK: SET ARMED
264273 self .mavlink .mav .command_long_send (
265274 self .mavlink .target_system ,
266275 self .mavlink .target_component ,
@@ -292,6 +301,7 @@ def arming_service_callback(
292301 VehicleArming.Response
293302 The filled ROS service response
294303 """
304+ # MARK: ARM CALLBACK
295305 self .set_armed (arm = request .arm )
296306
297307 response .message_sent = True
@@ -305,6 +315,7 @@ def process_arming_buttons(self, joy_state: JoystickState) -> None:
305315 joy_state : JoystickState
306316 The state of the joystick buttons and axes
307317 """
318+ # MARK: PROC ARM BUTTONS
308319 buttons = joy_state .buttons
309320
310321 if buttons [self .profile .disarm_button ] == PRESSED :
@@ -322,19 +333,21 @@ def process_camera_buttons(self, joy_state: JoystickState) -> None:
322333 joy_state : JoystickState
323334 The state of the joystick buttons and axess
324335 """
336+ # MARK: PROC CAM BUTTONS
325337 # Camera switching uses the DPAD, currently not remapable with the controller profile system
326338 # because DPADs are presented as axes not buttons and using any other axis is non-sensible
327339 if joy_state .buttons [self .profile .cam_front_button ]:
328- # TODO: Message camera manager and gui to swap cameras
340+ self . right_stream_switch_publisher . publish ( VideoWidgetSwitch ( relative = False , index = 0 ))
329341 self .invert_controls = False
330342 elif joy_state .buttons [self .profile .cam_back_button ]:
331- # TODO: Message camera manager and gui to swap cameras
343+ self . right_stream_switch_publisher . publish ( VideoWidgetSwitch ( relative = False , index = 1 ))
332344 self .invert_controls = True
333345
334346 def poll_mavlink (self ) -> None :
335347 """Check for incoming mavlink messages from the vehicle and send state updates if
336348 the vehicle state has changed.
337349 """
350+ # MARK: POLL MAVLINK
338351 new_state = self .poll_mavlink_for_new_state ()
339352
340353 # Check pi timeeout
@@ -364,6 +377,7 @@ def poll_mavlink_for_new_state(self) -> VehicleState:
364377 VehicleState
365378 The updated state of the vehicle
366379 """
380+ # MARK: POLL MAV NEW STATE
367381 new_state = VehicleState (
368382 pi_connected = self .vehicle_state .pi_connected ,
369383 ardusub_connected = self .vehicle_state .ardusub_connected ,
@@ -404,6 +418,7 @@ def pi_heartbeat_callback(self, _: Heartbeat) -> None:
404418 _ : Heartbeat
405419 The heartbeat message
406420 """
421+ # MARK: PI HEARTBEAT
407422 self .last_pi_heartbeat = time .time ()
408423
409424 if not self .vehicle_state .pi_connected :
@@ -415,6 +430,7 @@ def poll_subscribers(self) -> None:
415430 """Check for ros subsribers to our vehicle state topic, and send a state update whenever
416431 a new one subscribes.
417432 """
433+ # MARK: POLL SUBSCRIBERS
418434 # Whenever a node subscribes to vehicle state updates, send the current state
419435 subscriber_count = self .state_publisher .get_subscription_count ()
420436 if subscriber_count > self .last_state_subscriber_count :
@@ -424,6 +440,7 @@ def poll_subscribers(self) -> None:
424440
425441 def handle_pygame_events (self ) -> None :
426442 """Poll pygame for joystick connection and disconnection events."""
443+ # MARK: HANDLE PYGAME
427444 for event in pygame .event .get ():
428445 if event .type == pygame .JOYDEVICEADDED :
429446 new_joy = joystick .Joystick (event .device_index )
@@ -445,6 +462,7 @@ def handle_pygame_events(self) -> None:
445462
446463 def poll_joystick (self ) -> None :
447464 """Read the current state of the joystick and send a mavlink message."""
465+ # MARK: POLL JOYSTICK
448466 self .handle_pygame_events ()
449467
450468 if self .current_joystick_id is not None :
0 commit comments