# Unified USB Camera Launch Design ## Goal Make the camera behavior of `hobot_usb_cam.launch.py` and `hobot_usb_cam_websocket.launch.py` identical. The WebSocket variant must add only the WebSocket service. ## Configuration Add `config/usb_camera.yaml` as the single source of runtime camera parameters: - `video_device`: `/dev/video0` - `image_width`: `1280` - `image_height`: `720` - `framerate`: `30` - `pixel_format`: `mjpeg` - `io_method`: `mmap` - `zero_copy`: `false` - `frame_id`: `default_usb_cam` The calibration data remains in `usb_camera_calibration.yaml`; it is not mixed with ROS runtime parameters. The shared base launch resolves its installed path and applies it to the camera node after loading the runtime YAML. Both launch variants therefore receive the same calibration path without a source-tree absolute path. ## Launch Structure `hobot_usb_cam.launch.py` will: 1. Declare one `camera_config` launch argument whose default is the installed `config/usb_camera.yaml` path. 2. Start the shared-memory environment once. 3. Resolve the installed `usb_camera_calibration.yaml` path. 4. Start one `hobot_usb_cam` node with the YAML file as its parameter source and the resolved calibration resource path. `hobot_usb_cam_websocket.launch.py` will: 1. Include `hobot_usb_cam.launch.py` without overriding camera parameters. 2. Include the WebSocket launch configured for `/image`, MJPEG input, image-only display, and a 30 FPS output limit. It will not start `hobot_codec`, duplicate the shared-memory launch, or carry camera parameter literals. ## Data Flow Without WebSocket: `/dev/video0 -> hobot_usb_cam -> /image (CompressedImage)` With WebSocket: `/dev/video0 -> hobot_usb_cam -> /image (CompressedImage) -> WebSocket` No RGB conversion or second JPEG encode is performed. ## Validation An automated structural check will verify that: - the YAML contains the required 1280x720, 30 FPS, native MJPEG parameters; - the base launch loads that YAML; - the WebSocket launch includes the base launch; - the WebSocket launch does not define a camera node, codec node, or camera parameter overrides. After building, each launch will be started separately. Both must publish one `sensor_msgs/msg/CompressedImage` topic at approximately 30 FPS with decoded dimensions of 1280x720. Only the WebSocket launch may create the WebSocket node and port 8080 service. ## Operational Notes The two launch files cannot run concurrently because they both own `/dev/video0`. Runtime validation is sequential and stops the first launch before starting the second. Any separately started `usb_cam_node_exe` must also be stopped before validation because V4L2 permits only one active capture owner for this camera.