feat(jetson): night vision mode — IR emitter, headlight, ambient-light FSM, IR SLAM bridge (#168) #175

Merged
sl-jetson merged 1 commits from sl-perception/issue-168-night-vision into main 2026-03-02 10:36:56 -05:00
Collaborator

Summary

  • light_analyser: histogram intensity FSM with hysteresis — day → twilight → night → ir_only
  • camera_controller: drives D435i IR emitter via realsense2_camera parameter service; sets IMX219 gain/exposure via v4l2-ctl
  • gpio_headlight: physical pin 33 on Jetson 40-pin J26; Jetson.GPIO PWM primary, sysfs fallback
  • light_monitor_node: subscribes IMX219 front camera (or IR1 fallback), publishes /saltybot/ambient_light + /saltybot/vision_mode @ 2 Hz
  • night_vision_controller_node: reacts to mode changes, coordinates emitter + gain + headlight
  • ir_slam_bridge_node: republishes D435i infra1 mono8 as rgb8 so RTAB-Map loop-closure continues in darkness

Topics

Topic Type Direction
/saltybot/vision_mode std_msgs/String publish
/saltybot/ambient_light std_msgs/Float32 publish
/saltybot/night_vision_status std_msgs/String (JSON) publish
/saltybot/ir_bridge/image_raw sensor_msgs/Image publish (dark modes only)
/saltybot/ir_bridge/camera_info sensor_msgs/CameraInfo publish (dark modes only)

Test plan

  • 18 unit tests pass (pytest test/test_night_vision.py) — no ROS2 or hardware required
  • Deploy on Jetson Orin Nano Super — confirm vision_mode transitions at day/twilight/night/ir_only light levels
  • Verify D435i emitter toggles: ros2 param get /camera/camera depth_module.emitter_enabled
  • Confirm GPIO headlight dimming on physical pin 33
  • Check IR bridge active only in dark modes: ros2 topic hz /saltybot/ir_bridge/image_raw
  • Validate RTAB-Map continues loop-closing from IR bridge feed at night

🤖 Generated with Claude Code

## Summary - **light_analyser**: histogram intensity FSM with hysteresis — `day → twilight → night → ir_only` - **camera_controller**: drives D435i IR emitter via `realsense2_camera` parameter service; sets IMX219 gain/exposure via `v4l2-ctl` - **gpio_headlight**: physical pin 33 on Jetson 40-pin J26; Jetson.GPIO PWM primary, sysfs fallback - **light_monitor_node**: subscribes IMX219 front camera (or IR1 fallback), publishes `/saltybot/ambient_light` + `/saltybot/vision_mode` @ 2 Hz - **night_vision_controller_node**: reacts to mode changes, coordinates emitter + gain + headlight - **ir_slam_bridge_node**: republishes D435i `infra1` mono8 as `rgb8` so RTAB-Map loop-closure continues in darkness ## Topics | Topic | Type | Direction | |---|---|---| | `/saltybot/vision_mode` | `std_msgs/String` | publish | | `/saltybot/ambient_light` | `std_msgs/Float32` | publish | | `/saltybot/night_vision_status` | `std_msgs/String` (JSON) | publish | | `/saltybot/ir_bridge/image_raw` | `sensor_msgs/Image` | publish (dark modes only) | | `/saltybot/ir_bridge/camera_info` | `sensor_msgs/CameraInfo` | publish (dark modes only) | ## Test plan - [x] 18 unit tests pass (`pytest test/test_night_vision.py`) — no ROS2 or hardware required - [ ] Deploy on Jetson Orin Nano Super — confirm `vision_mode` transitions at day/twilight/night/ir_only light levels - [ ] Verify D435i emitter toggles: `ros2 param get /camera/camera depth_module.emitter_enabled` - [ ] Confirm GPIO headlight dimming on physical pin 33 - [ ] Check IR bridge active only in dark modes: `ros2 topic hz /saltybot/ir_bridge/image_raw` - [ ] Validate RTAB-Map continues loop-closing from IR bridge feed at night 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sl-perception added 1 commit 2026-03-02 10:36:43 -05:00
Implements ambient-light-aware night vision mode for the D435i + IMX219
stack on the Jetson Orin Nano Super:

• light_analyser.py       — histogram-based intensity FSM with hysteresis:
                            day → twilight → night → ir_only
• camera_controller.py   — D435i IR emitter via realsense2_camera param
                            service + IMX219 gain/exposure via v4l2-ctl
• gpio_headlight.py      — physical pin 33 headlight; Jetson.GPIO PWM
                            primary, sysfs on/off fallback, sim mode
• light_monitor_node.py  — subscribes IMX219/IR1, publishes
                            /saltybot/ambient_light + /saltybot/vision_mode
• night_vision_controller_node.py — reacts to mode changes; drives
                            D435i emitter, IMX219 gain, headlight
• ir_slam_bridge_node.py — mono8 IR1 → rgb8 republish so RTAB-Map
                            keeps loop-closing in darkness
• launch/night_vision.launch.py + config/night_vision_params.yaml
• test/test_night_vision.py — 18 unit tests (18/18 pass, no ROS2 needed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sl-jetson merged commit d2cada00a0 into main 2026-03-02 10:36:56 -05:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#175
No description provided.