Files
dora-zed/src/zed/camera.h
T
cesarandClaude Opus 5 5822a870bb
validate / validate (push) Successful in 59m1s
validate / validate (pull_request) Successful in 59m2s
fix the camera blocking the dora event loop by moving it to its own thread
Hardware testing showed the tick-driven recovery state machine did not work.
async_grab_camera_recovery does not make grab() prompt on a disconnected ZED-M
under SDK 5.3: grabs took ~3 s each while the link was down and then blocked
indefinitely. The event loop stopped turning, so Stop went unanswered, the
30 s patience timer and the backoff were never reached, and replugging the
camera did nothing. Measured: 122 s frozen, then dora stop needed 10 s and a
forced kill.

Move everything that can block onto a capture thread. zed::Capture owns the
camera and runs open, warmup, grab, blank and stall detection, backoff and
escalation; it packs each frame into owned buffers and hands the newest one to
the reader by swapping under a mutex. The dora event loop now only drains that
buffer and publishes, so it never calls into the SDK and stays responsive
however long the SDK blocks.

The newest frame wins and uncollected frames are dropped, which is what a
consumer wants from a camera source. Swapping rather than assigning returns the
previous frame's buffers to the capture thread, so steady state does not
reallocate. The point cloud is now copied out of the SDK buffer rather than
published in place, since the reader is another thread.

On exit the loop waits 2 s for the thread and then _Exit()s if it is still
inside the SDK, so Stop is always answered promptly.

This also removes the blocking warmup from the event loop: it stays a blocking
burst, which is harmless on the capture thread.

Verified on a ZED-M: unplug leaves the node responsive and logs the backoff
1, 2, 5 then 10 s; replug gives "camera recovered after 13 attempt(s)" and
publishing resumes without restarting the dataflow; dora stop with the camera
unplugged returns in 0.70 s with the thread joining gracefully.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7g2cBJ5e3r15ZbJ9WZn8c
2026-09-08 12:04:35 -03:00

76 lines
2.1 KiB
C++

#pragma once
#include <sl/Camera.hpp>
#include <cstdint>
#include <string>
#include <vector>
namespace zed {
enum class PcMode { FULL, HALF };
struct Config {
int resolution = 1080;
int fps = 15;
sl::DEPTH_MODE depth_mode = sl::DEPTH_MODE::NEURAL;
int depth_min_mm = 200;
int depth_max_mm = 600;
bool depth_fill = false;
bool point_cloud = false;
PcMode pc_mode = PcMode::FULL;
int confidence_threshold = 60;
int texture_confidence_threshold = 100;
std::string flip = "ON";
int warmup_frames = 30;
static Config from_env();
};
struct Calibration {
float fx = 0, fy = 0, cx = 0, cy = 0;
std::vector<double> distortion;
};
class Camera {
public:
explicit Camera(const Config& config);
~Camera();
// One attempt, returning whether it succeeded. The caller decides when to try
// again, so a camera that is down never blocks the dora event loop.
bool open();
void close();
// Close the handle and reset the device over USB, where the model allows it.
void reset();
void warmup();
bool grab();
bool is_open() const;
// True while the SDK is reconnecting the camera after a link hiccup.
bool recovering() const;
// True when the last grabbed frame carries no picture at all. A camera whose
// link has dropped does not necessarily fail its grabs: it can keep reporting
// success and hand back a uniform frame.
bool image_is_blank();
Calibration calibration() const;
int64_t device_timestamp_ns();
sl::Mat& image();
sl::Mat& depth();
sl::Mat& point_cloud();
private:
Config config_;
sl::Camera zed_;
sl::InitParameters init_params_;
sl::RuntimeParameters runtime_params_;
sl::Mat image_mat_;
sl::Mat depth_mat_;
sl::Mat point_cloud_mat_;
// Read off the device once it is open and kept afterwards: resetting a wedged
// camera needs the serial and the model, and by then the handle is gone.
unsigned int serial_number_ = 0;
sl::MODEL model_ = sl::MODEL::LAST;
bool recovering_ = false;
};
} // namespace zed