Skip to content

Bug: refresh_camera_data return value ignored in camera_subprocess_func, causing stale frames to be written to SHM #57

Description

@heuljupupup

Bug Description

In instinct_onboard/ros_nodes/camera_base.py, the camera_subprocess_func
loop ignores the return value of camera.refresh_camera_data(). This can
cause stale frames to be re-written to shared memory with an incremented
frame_counter, making the main process believe a new frame arrived.

Location

instinct_onboard/ros_nodes/camera_base.py, lines ~227-242 (depth) and
~244-251 (color), inside camera_subprocess_func.

Root Cause

  1. CameraBase.refresh_camera_data() returns bool indicating whether new
    data was acquired (True) or not (False).
  2. RealsenseCamera.refresh_camera_data() only updates self._depth_data
    when frames.get_depth_frame() is not None. If the depth frame is missing
    from the frameset, _depth_data retains the previous frame.
  3. The subprocess loop discards the return value:
    camera.refresh_camera_data()          # return value ignored
    if depth_buffer is not None:
        depth_data = camera.get_depth_image()
        if depth_data is not None:        # passes — stale data is not None
            depth_buffer[:] = depth_data
            depth_header.frame_counter += 1   # counter incorrectly incremented
            ...

Consequence

  • When get_depth_frame() returns None, the previous frame is written to SHM
    again with a new frame_counter and timestamp.
  • The main process (CameraProcessSpawner.refresh_camera_data) sees
    frame_counter changed and treats the stale data as a fresh frame.
  • Downstream agents receive an out-of-date depth observation with an updated
    timestamp, which is indistinguishable from a real new frame.
  • The same issue affects the color stream.

Trigger Condition

Rare: pipeline.wait_for_frames() succeeds but frames.get_depth_frame()
returns None (USB bandwidth jitter, IR projector transient, firmware sync
loss).

Suggested Fix

Option A — respect the return value in the subprocess loop:

got_new = camera.refresh_camera_data()
if depth_buffer is not None and got_new:
    depth_data = camera.get_depth_image()
    ...

(Note: got_new is True if either depth or color was acquired, so this
is a coarse fix. A per-stream status would be more precise.)

Option B — invalidate the cached data when no new frame arrives:

# In RealsenseCamera.refresh_camera_data, when depth_frame is None:
self._depth_data = None

This makes the existing if depth_data is not None check correct, but
changes the "keep last frame" behavior that single-process consumers may
rely on.

Environment

  • Ubuntu 22.04, ROS2 Humble
  • Jetson Orin NX (ARM, weak memory order — the memory barriers in this file
    suggest ARM is a deployment target)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions