00001
00002
00003
00004 #pragma once
00005 #ifndef LIBREALSENSE_ZR300_H
00006 #define LIBREALSENSE_ZR300_H
00007
00008 #include "motion-module.h"
00009 #include "ds-device.h"
00010 #include "sync.h"
00011
00012 #include <deque>
00013 #include <cmath>
00014 #include <math.h>
00015
00016 namespace rsimpl
00017 {
00018
00019 struct IMU_version
00020 {
00021 byte ver[4];
00022 byte size;
00023 byte CRC32[4];
00024 };
00025 #pragma pack(push, 1)
00026 struct serial_number
00027 {
00028 IMU_version ver;
00029 byte MM_s_n[6];
00030 byte DS4_s_n[6];
00031 byte reserved[235];
00032 };
00033
00034 struct fisheye_intrinsic
00035 {
00036 IMU_version ver;
00037 float kf[9];
00038 float distf[5];
00039 byte reserved[191];
00040
00041 int get_data_size() const
00042 {
00043 return sizeof(kf) + sizeof(distf);
00044 };
00045
00046 bool has_data() const
00047 {
00048 return check_not_all_zeros({(byte*)&kf, ((byte*)&kf) + get_data_size()});
00049 }
00050
00051 operator rs_intrinsics () const
00052 {
00053 return{ 640, 480, kf[2], kf[5], kf[0], kf[4], RS_DISTORTION_FTHETA, { distf[0], 0, 0, 0, 0 } };
00054 }
00055 };
00056
00057
00058 struct mm_extrinsic
00059 {
00060 float rotation[9];
00061 float translation[3];
00062
00063 operator rs_extrinsics () const {
00064 return{ { rotation[0], rotation[1], rotation[2],
00065 rotation[3], rotation[4], rotation[5],
00066 rotation[6], rotation[7], rotation[8] },
00067 { translation[0], translation[1], translation[2] } };
00068 }
00069
00070 int get_data_size() const
00071 {
00072 return sizeof(rotation) + sizeof(translation);
00073 }
00074
00075 bool has_data() const
00076 {
00077 return check_not_all_zeros({ (byte*)&rotation, ((byte*)&rotation) + get_data_size() });
00078 }
00079 };
00080 struct IMU_extrinsic
00081 {
00082 IMU_version ver;
00083 mm_extrinsic fe_to_imu;
00084 mm_extrinsic fe_to_depth;
00085 mm_extrinsic rgb_to_imu;
00086 mm_extrinsic depth_to_imu;
00087 byte reserved[55];
00088
00089 int get_data_size() const
00090 {
00091 return sizeof(fe_to_imu) + sizeof(fe_to_depth) + sizeof(rgb_to_imu) + sizeof(depth_to_imu);
00092 };
00093 };
00094
00095 struct MM_intrinsics
00096 {
00097
00098
00099
00100
00101 float val[3][4];
00102 };
00103
00104
00105 struct IMU_intrinsic
00106 {
00107 IMU_version ver;
00108 MM_intrinsics acc_intrinsic;
00109 MM_intrinsics gyro_intrinsic;
00110 float acc_bias_variance[3];
00111 float acc_noise_variance[3];
00112 float gyro_bias_variance[3];
00113 float gyro_noise_variance[3];
00114 byte reserved[103];
00115
00116 int get_data_size() const
00117 {
00118 return sizeof(acc_intrinsic) + sizeof(gyro_intrinsic) +
00119 sizeof(acc_bias_variance) + sizeof(acc_noise_variance) + sizeof(gyro_bias_variance) + sizeof(gyro_noise_variance);
00120 };
00121
00122 bool has_data() const
00123 {
00124 return check_not_all_zeros({(byte*)&acc_intrinsic, ((byte*)&acc_intrinsic) + get_data_size()});
00125 }
00126
00127 rs_motion_device_intrinsic convert(const MM_intrinsics& intrin, const float bias_variance[3], const float noises_variance[3]) const
00128 {
00129 rs_motion_device_intrinsic res;
00130
00131 for (auto i = 0; i < 3; i++)
00132 {
00133 for (auto j = 0; j < 4; j++)
00134 {
00135 res.data[i][j] = intrin.val[i][j];
00136 }
00137 }
00138
00139 for (auto i = 0; i < 3; i++)
00140 {
00141 res.noise_variances[i] = noises_variance[i];
00142 res.bias_variances[i] = bias_variance[i];
00143 }
00144 return res;
00145 }
00146 rs_motion_device_intrinsic get_acc_intrinsic() const
00147 {
00148 return convert(acc_intrinsic, acc_bias_variance, acc_noise_variance);
00149 }
00150
00151 rs_motion_device_intrinsic get_gyro_intrinsic() const
00152 {
00153 return convert(gyro_intrinsic, gyro_bias_variance, gyro_noise_variance);
00154 }
00155
00156 operator rs_motion_intrinsics() const{
00157
00158 return{ get_acc_intrinsic(), get_gyro_intrinsic() };
00159 }
00160 };
00161
00162 struct calibration
00163 {
00164 fisheye_intrinsic fe_intrinsic;
00165 IMU_extrinsic mm_extrinsic;
00166 IMU_intrinsic imu_intrinsic;
00167 };
00168 struct motion_module_calibration
00169 {
00170 serial_number sn;
00171 calibration calib;
00172 };
00173 #pragma pack(pop)
00174
00175
00176
00177 enum class auto_exposure_modes {
00178 static_auto_exposure = 0,
00179 auto_exposure_anti_flicker,
00180 auto_exposure_hybrid
00181 };
00182
00183 class fisheye_auto_exposure_state
00184 {
00185 public:
00186 fisheye_auto_exposure_state() :
00187 is_auto_exposure(true),
00188 mode(auto_exposure_modes::auto_exposure_hybrid),
00189 rate(60),
00190 sample_rate(1),
00191 skip_frames(2)
00192 {}
00193
00194 unsigned get_auto_exposure_state(rs_option option) const;
00195 void set_auto_exposure_state(rs_option option, double value);
00196
00197 private:
00198 bool is_auto_exposure;
00199 auto_exposure_modes mode;
00200 unsigned rate;
00201 unsigned sample_rate;
00202 unsigned skip_frames;
00203 };
00204
00205 class zr300_camera;
00206 class auto_exposure_algorithm {
00207 public:
00208 void modify_exposure(float& exposure_value, bool& exp_modified, float& gain_value, bool& gain_modified);
00209 bool analyze_image(const rs_frame_ref* image);
00210 auto_exposure_algorithm(fisheye_auto_exposure_state auto_exposure_state);
00211 void update_options(const fisheye_auto_exposure_state& options);
00212
00213 private:
00214 struct histogram_metric { int under_exposure_count; int over_exposure_count; int shadow_limit; int highlight_limit; int lower_q; int upper_q; float main_mean; float main_std; };
00215 enum class rounding_mode_type { round, ceil, floor };
00216
00217 inline void im_hist(const uint8_t* data, const int width, const int height, const int rowStep, int h[]);
00218 void increase_exposure_target(float mult, float& target_exposure);
00219 void decrease_exposure_target(float mult, float& target_exposure);
00220 void increase_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00221 void decrease_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00222 void static_increase_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00223 void static_decrease_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00224 void anti_flicker_increase_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00225 void anti_flicker_decrease_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00226 void hybrid_increase_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00227 void hybrid_decrease_exposure_gain(const float& target_exposure, const float& target_exposure0, float& exposure, float& gain);
00228
00229 #if defined(_WINDOWS) || defined(WIN32) || defined(WIN64)
00230 inline float round(float x) { return std::round(x); }
00231 #else
00232 inline float round(float x) { return x < 0.0 ? std::ceil(x - 0.5f) : std::floor(x + 0.5f); }
00233 #endif
00234
00235 float exposure_to_value(float exp_ms, rounding_mode_type rounding_mode);
00236 float gain_to_value(float gain, rounding_mode_type rounding_mode);
00237 template <typename T> inline T sqr(const T& x) { return (x*x); }
00238 void histogram_score(std::vector<int>& h, const int total_weight, histogram_metric& score);
00239
00240
00241 float minimal_exposure = 0.1f, maximal_exposure = 20.f, base_gain = 2.0f, gain_limit = 15.0f;
00242 float exposure = 10.0f, gain = 2.0f, target_exposure = 0.0f;
00243 uint8_t under_exposure_limit = 5, over_exposure_limit = 250; int under_exposure_noise_limit = 50, over_exposure_noise_limit = 50;
00244 int direction = 0, prev_direction = 0; float hysteresis = 0.075f;
00245 float eps = 0.01f, exposure_step = 0.1f, minimal_exposure_step = 0.01f;
00246 fisheye_auto_exposure_state state; float flicker_cycle; bool anti_flicker_mode = true;
00247 std::recursive_mutex state_mutex;
00248 };
00249
00250 class auto_exposure_mechanism {
00251 public:
00252 auto_exposure_mechanism(zr300_camera* dev, fisheye_auto_exposure_state auto_exposure_state);
00253 ~auto_exposure_mechanism();
00254 void add_frame(rs_frame_ref* frame, std::shared_ptr<rsimpl::frame_archive> archive);
00255 void update_auto_exposure_state(fisheye_auto_exposure_state& auto_exposure_state);
00256 struct exposure_and_frame_counter {
00257 exposure_and_frame_counter() : exposure(0), frame_counter(0) {};
00258 exposure_and_frame_counter(double exposure, unsigned long long frame_counter) : exposure(exposure), frame_counter(frame_counter){}
00259 double exposure;
00260 unsigned long long frame_counter;
00261 };
00262
00263 private:
00264 void push_back_data(rs_frame_ref* data);
00265 bool try_pop_front_data(rs_frame_ref** data);
00266 size_t get_queue_size();
00267 void clear_queue();
00268 unsigned get_skip_frames(const fisheye_auto_exposure_state& auto_exposure_state) { return auto_exposure_state.get_auto_exposure_state(RS_OPTION_FISHEYE_AUTO_EXPOSURE_SKIP_FRAMES); }
00269 void push_back_exp_and_cnt(exposure_and_frame_counter exp_and_cnt);
00270 bool try_get_exp_by_frame_cnt(double& exposure, const unsigned long long frame_counter);
00271
00272 const std::size_t max_size_of_exp_and_cnt_queue = 10;
00273 zr300_camera* device;
00274 auto_exposure_algorithm auto_exposure_algo;
00275 std::shared_ptr<rsimpl::frame_archive> sync_archive;
00276 std::shared_ptr<std::thread> exposure_thread;
00277 std::condition_variable cv;
00278 std::atomic<bool> keep_alive;
00279 std::deque<rs_frame_ref*> data_queue;
00280 std::mutex queue_mtx;
00281 std::atomic<unsigned> frames_counter;
00282 std::atomic<unsigned> skip_frames;
00283 std::deque<exposure_and_frame_counter> exposure_and_frame_counter_queue;
00284 std::mutex exp_and_cnt_queue_mtx;
00285 };
00286
00287 class zr300_camera final : public ds::ds_device
00288 {
00289 motion_module::motion_module_control motion_module_ctrl;
00290 motion_module::mm_config motion_module_configuration;
00291 fisheye_auto_exposure_state auto_exposure_state;
00292 std::shared_ptr<auto_exposure_mechanism> auto_exposure;
00293 std::atomic<bool> to_add_frames;
00294
00295 protected:
00296 void toggle_motion_module_power(bool bOn);
00297 void toggle_motion_module_events(bool bOn);
00298 void on_before_callback(rs_stream , rs_frame_ref *, std::shared_ptr<rsimpl::frame_archive>) override;
00299
00300 std::timed_mutex usbMutex;
00301
00302 public:
00303 zr300_camera(std::shared_ptr<uvc::device> device, const static_device_info & info, motion_module_calibration fe_intrinsic, calibration_validator validator);
00304 ~zr300_camera();
00305
00306 void get_option_range(rs_option option, double & min, double & max, double & step, double & def) override;
00307 void set_options(const rs_option options[], size_t count, const double values[]) override;
00308 void get_options(const rs_option options[], size_t count, double values[]) override;
00309 void send_blob_to_device(rs_blob_type type, void * data, int size) override;
00310 bool supports_option(rs_option option) const override;
00311
00312 void start_motion_tracking() override;
00313 void stop_motion_tracking() override;
00314
00315 void start(rs_source source) override;
00316 void stop(rs_source source) override;
00317
00318 rs_stream select_key_stream(const std::vector<rsimpl::subdevice_mode_selection> & selected_modes) override;
00319
00320 rs_motion_intrinsics get_motion_intrinsics() const override;
00321 rs_extrinsics get_motion_extrinsics_from(rs_stream from) const override;
00322 unsigned long long get_frame_counter_by_usb_cmd();
00323
00324
00325 private:
00326 unsigned get_auto_exposure_state(rs_option option);
00327 void set_auto_exposure_state(rs_option option, double value);
00328 void set_fw_logger_option(double value);
00329 unsigned get_fw_logger_option();
00330
00331 bool validate_motion_extrinsics(rs_stream) const;
00332 bool validate_motion_intrinsics() const;
00333
00334 motion_module_calibration fe_intrinsic;
00335 };
00336 motion_module_calibration read_fisheye_intrinsic(uvc::device & device);
00337 std::shared_ptr<rs_device> make_zr300_device(std::shared_ptr<uvc::device> device);
00338 }
00339
00340 #endif