fwt_software/include/fgc/TarisCameraSource.h

82 lines
3.5 KiB
C++

#pragma once
#include "fgc/Config.h"
#include "fgc/ICameraSource.h"
#include "fgc/IrbgrabApi.h"
#include <functional>
#include <memory>
#include <string>
namespace fgc {
// The thermal camera: an InfraTec TarisIR mini through the IRBGRAB SDK
// (IrbgrabApi.h), one camera per source.
//
// The camera is kept grabbing from open() to close(), whatever the scan does:
// a microbolometer that is stopped and restarted starts with zero frames and a
// fresh NUC. A worker thread owns every SDK call - connecting, polling the
// newest frame of counts, switching the calibration profile, reconnecting
// when the camera goes quiet - so nothing here ever blocks the control loop.
// trigger() hands over the newest frame if it is fresh enough, and otherwise
// says no at once: the thermal picture of a waypoint is best effort, the
// colour camera's is not.
//
// A camera that is missing, unlicensed or unreachable is not a startup error.
// The source reports why in offline(), keeps retrying, and the scan goes on
// without it.
class TarisCameraSource : public ICameraSource {
public:
struct Options {
std::string serial; // the camera's serial number
int calib_profile = 0;
double frame_rate_hz = 5.0;
int max_frame_age_ms = 400;
std::string library = "libirbgrab_linux.so";
std::string interface; // for diagnostics only; may be empty
int stall_ms = 5000; // connected but no frame this long: reconnect
int retry_min_ms = 2000; // between connection attempts, doubling...
int retry_max_ms = 30000;// ...up to this
int calib_timeout_ms = 15000;// a profile switch takes about 3 s
};
static Options fromSpec(const CameraSpec& spec);
// api: the SDK, or null to load opts.library when the worker starts.
// has_net_raw: may this process open a raw socket (the SDK needs one)?
// Null: read the effective capabilities from /proc/self/status.
explicit TarisCameraSource(Options opts, std::shared_ptr<const irbgrab::Api> api = nullptr,
std::function<bool()> has_net_raw = nullptr);
~TarisCameraSource() override;
void open() override;
void close() override;
// Only open and close delivery; the camera keeps grabbing either way.
void start() override;
void stop() override;
bool trigger() override;
void setFrameCallback(FrameCallback cb) override;
int cameraCount() const override { return 1; }
std::vector<CameraDeviceInfo> deviceInfo() override;
std::string offline(int camera_index) override;
bool grabFrame(int camera_index, Frame& out, int timeout_ms) override;
// "CalibProfile" (index), "KelvinPerCount", "HousingTemperature" (degC).
bool readFeature(int camera_index, const std::string& name, double& value) override;
// "CalibProfile": switch, and wait until the camera has (seconds).
bool setFeature(int camera_index, const std::string& name, const std::string& value) override;
// Disconnect and connect again; waits until it is back or gives up.
bool resetCamera(int camera_index) override;
// The counts' scale the profiles are documented to have (TarisIR mini):
// 0.01 K for profile 0, 0.02 K for profile 1; 0 for any other.
static double expectedKelvinPerCount(int calib_profile);
// Does /proc/self/status grant CAP_NET_RAW?
static bool processHasNetRaw();
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace fgc