k-to-dsm.cpp
Go to the documentation of this file.
1 
4 #include "k-to-dsm.h"
5 #include "optimizer.h"
6 #include "debug.h"
7 #include "utils.h"
8 #include <math.h>
9 
11 
12 
13 std::ostream &
15  rs2_dsm_params_double const & self )
16 {
17  s << "[ ";
18  switch( self.model )
19  {
20  case RS2_DSM_CORRECTION_NONE: break;
21  case RS2_DSM_CORRECTION_AOT: s << "AoT "; break;
22  case RS2_DSM_CORRECTION_TOA: s << "ToA "; break;
23  }
24  s << "x[" << self.h_scale << " " << self.v_scale << "] ";
25  if( self.h_offset || self.v_offset )
26  s << "+[" << self.h_offset << " " << self.v_offset;
27  if( self.rtd_offset )
28  s << " rtd " << self.rtd_offset;
29  s << " ]";
30  return s;
31 }
32 
33 
35 {
36  rs2_intrinsics_double res = k_mat;
37  res.ppx = k_mat.width - 1 - k_mat.ppx;
38  res.ppy = k_mat.height - 1 - k_mat.ppy;
39 
40  return res;
41 }
42 
43 k_to_DSM::k_to_DSM( const rs2_dsm_params_double & orig_dsm_params,
44  algo_calibration_info const & cal_info,
45  algo_calibration_registers const & cal__regs,
46  const double & max_scaling_step )
47  : _regs( cal_info )
48  , _dsm_regs( cal__regs )
49  , _max_scaling_step( max_scaling_step )
50 {
51 }
52 
55  const algo_calibration_registers & dsm_regs,
56  const ac_to_dsm_dir & type )
57 {
59 
60  if (type == direct) // convert from original model to modified model
61  {
62  switch (ac_data.model)
63  {
65  res = dsm_regs;
66  break;
68  res.EXTLdsmXscale = (double)dsm_regs.EXTLdsmXscale * ac_data.h_scale ;
69  res.EXTLdsmYscale = (double)dsm_regs.EXTLdsmYscale * ac_data.v_scale ;
70  res.EXTLdsmXoffset
71  = ( (double)dsm_regs.EXTLdsmXoffset + (double)ac_data.h_offset )
72  / (double)ac_data.h_scale ;
73  res.EXTLdsmYoffset
74  = ( (double)dsm_regs.EXTLdsmYoffset + (double)ac_data.v_offset )
75  / (double)ac_data.v_scale ;
76  break;
78  res.EXTLdsmXscale = (double)dsm_regs.EXTLdsmXscale * ac_data.h_scale ;
79  res.EXTLdsmYscale = (double)dsm_regs.EXTLdsmYscale * ac_data.v_scale ;
80  res.EXTLdsmXoffset
81  = ( (double)dsm_regs.EXTLdsmXoffset + (double)ac_data.h_offset )
82  / (double)dsm_regs.EXTLdsmXscale ;
83  res.EXTLdsmYoffset
84  = ( (double)dsm_regs.EXTLdsmYoffset + (double)ac_data.v_offset )
85  / (double)dsm_regs.EXTLdsmYscale ;
86  break;
87  default:
88  throw std::runtime_error( "invalid model " + std::to_string( ac_data.model ) );
89  }
90  }
91  else if (type == inverse) // revert from modified model to original model
92  {
93  switch (ac_data.model)
94  {
96  res = dsm_regs;
97  break;
99  res.EXTLdsmXscale = (double)dsm_regs.EXTLdsmXscale / (double)ac_data.h_scale;
100  res.EXTLdsmYscale = (double)dsm_regs.EXTLdsmYscale / (double)ac_data.v_scale;
101  res.EXTLdsmXoffset = (double)dsm_regs.EXTLdsmXoffset* (double)ac_data.h_scale - (double)ac_data.h_offset;
102  res.EXTLdsmYoffset = (double)dsm_regs.EXTLdsmYoffset* (double)ac_data.v_scale - (double)ac_data.v_offset;
103  break;
105  res.EXTLdsmXscale = (double)dsm_regs.EXTLdsmXscale / (double)ac_data.h_scale;
106  res.EXTLdsmYscale = (double)dsm_regs.EXTLdsmYscale / (double)ac_data.v_scale;
107  res.EXTLdsmXoffset = (double)dsm_regs.EXTLdsmXoffset - (double)ac_data.h_offset / (double)res.EXTLdsmXscale;
108  res.EXTLdsmYoffset = (double)dsm_regs.EXTLdsmYoffset - (double)ac_data.v_offset / (double)res.EXTLdsmYscale;
109  break;
110  default:
111  throw std::runtime_error( "invalid valid model " + std::to_string( ac_data.model ) );
112  break;
113  }
114  }
115  return res;
116 }
117 
120  const rs2_dsm_params_double & ac_data )
121 {
123  switch (ac_data.model)
124  {
126  res.los_scaling_x = 1;
127  res.los_scaling_y = 1;
128  res.los_shift_x = 0;
129  res.los_shift_y = 0;
130  break;
132  res.los_scaling_x = 1/ (double)ac_data.h_scale;
133  res.los_scaling_y = 1/ (double)ac_data.v_scale;
134  res.los_shift_x = -(double)ac_data.h_offset*res.los_scaling_x;
135  res.los_shift_y = -(double)ac_data.v_offset*res.los_scaling_y;
136  break;
138  res.los_scaling_x = 1 / (double)ac_data.h_scale;
139  res.los_scaling_y = 1 / (double)ac_data.v_scale;
140 
141  auto dsm_orig = apply_ac_res_on_dsm_model(ac_data, dsm_regs, inverse);
142 
143  res.los_shift_x = -(double)ac_data.h_offset / (double)dsm_orig.EXTLdsmXscale - (double)dsm_orig.EXTLdsmXoffset*(1 - res.los_scaling_x);
144  res.los_shift_y = -(double)ac_data.v_offset / (double)dsm_orig.EXTLdsmYscale - (double)dsm_orig.EXTLdsmYoffset*(1 - res.los_scaling_y);
145  break;
146  }
147  return res;
148 }
149 
151 (
152  const algo_calibration_info& regs,
153  const rs2_dsm_params_double& ac_data,
155  const rs2_intrinsics_double& orig_k_raw,
156  const std::vector<uint8_t>& relevant_pixels_image,
158 )
159 {
161  res.orig_k = orig_k_raw;
162  res.relevant_pixels_image_rot = relevant_pixels_image;
163  res.last_los_error = convert_ac_data_to_los_error(algo_calibration_registers, ac_data);
164 
165  res.vertices_orig = calc_relevant_vertices(relevant_pixels_image, orig_k_raw);
166  auto dsm_res_orig = apply_ac_res_on_dsm_model(ac_data, algo_calibration_registers, inverse);
167 
168  convert_norm_vertices_to_los_data* vertices_to_los_data = nullptr;
169  if (data)
170  vertices_to_los_data = &data->k2dsm_data_p.first_norm_vertices_to_los_data;
171 
172  res.los_orig = convert_norm_vertices_to_los(regs, dsm_res_orig, res.vertices_orig, vertices_to_los_data);
173  return res;
174 }
175 
177 (
178  const rs2_intrinsics_double& old_k,
179  const rs2_intrinsics_double& new_k,
180  const z_frame_data& z,
181  std::vector<double3> & new_vertices,
182  rs2_dsm_params_double const & previous_dsm_params,
183  algo_calibration_registers& new_dsm_regs,
184  data_collect* data
185 )
186 {
187  if (data)
188  {
189  data->k2dsm_data_p.inputs.old_k = old_k;
190  data->k2dsm_data_p.inputs.new_k = new_k;
191  data->k2dsm_data_p.inputs.z = z;
192  data->k2dsm_data_p.inputs.new_vertices = new_vertices;
193  data->k2dsm_data_p.inputs.previous_dsm_params = previous_dsm_params;
194  data->k2dsm_data_p.inputs.new_dsm_regs = new_dsm_regs;
195  }
196 
197 
198  auto w = old_k.width;
199  auto h = old_k.height;
200 
201  auto old_k_raw = rotate_k_mat(old_k);
202  auto new_k_raw = rotate_k_mat(new_k);
203 
204  auto dsm_orig = apply_ac_res_on_dsm_model( previous_dsm_params, new_dsm_regs, inverse);
205 
206  std::vector<uint8_t> relevant_pixels_image_rot(z.relevant_pixels_image.size(), 0);
207  rotate_180(z.relevant_pixels_image.data(), relevant_pixels_image_rot.data(), w, h);
208 
209  _pre_process_data = pre_processing(_regs, previous_dsm_params, new_dsm_regs, old_k_raw, relevant_pixels_image_rot, data);
210 
211  auto new_los_scaling = convert_k_to_los_error(_regs, new_dsm_regs, new_k_raw, data);
212  double2 los_shift = { 0 };
213  auto ac_data_cand = convert_los_error_to_ac_data( previous_dsm_params, new_dsm_regs, los_shift, new_los_scaling);
214  auto dsm_regs_cand = apply_ac_res_on_dsm_model(ac_data_cand, dsm_orig, direct);
215 
216  auto sc_vertices = new_vertices;
217 
218  for (auto i = 0; i < sc_vertices.size(); i++)
219  {
220  sc_vertices[i].x *= -1;
221  sc_vertices[i].y *= -1;
222  }
223 
224  convert_norm_vertices_to_los_data* vertices_to_los_data = nullptr;
225  if (data)
226  vertices_to_los_data = &data->k2dsm_data_p.second_norm_vertices_to_los_data;
227  auto los_orig = convert_norm_vertices_to_los(_regs, new_dsm_regs, sc_vertices, vertices_to_los_data);
228  new_vertices = convert_los_to_norm_vertices(_regs, dsm_regs_cand, los_orig, data);
229 
230  if (data)
231  {
232  data->k2dsm_data_p.dsm_regs_orig = dsm_orig;
233  data->k2dsm_data_p.relevant_pixels_image_rot = relevant_pixels_image_rot;
234  data->k2dsm_data_p.new_los_scaling = new_los_scaling;
235  data->k2dsm_data_p.dsm_regs_cand = dsm_regs_cand;
236  data->k2dsm_data_p.los_orig = los_orig;
237  }
238 
239  for (auto i = 0; i < new_vertices.size(); i++)
240  {
241  new_vertices[i].x = new_vertices[i].x / new_vertices[i].z * sc_vertices[i].z;
242  new_vertices[i].y = new_vertices[i].y / new_vertices[i].z * sc_vertices[i].z;
243  new_vertices[i].z = new_vertices[i].z / new_vertices[i].z * sc_vertices[i].z;
244 
245  new_vertices[i].x *= -1;
246  new_vertices[i].y *= -1;
247  }
248 
249  AC_LOG( DEBUG,
250  " new DSM params: " << AC_D_PREC << ac_data_cand << "; vertices are changed" );
251  new_dsm_regs = dsm_regs_cand;
252  return ac_data_cand;
253 }
254 
256 {
257  return _pre_process_data;
258 }
259 
261 (
262  algo_calibration_info const & regs,
263  algo_calibration_registers const &dsm_regs,
264  rs2_intrinsics_double const & new_k_raw,
265  data_collect* data
266 )
267 {
268  double2 focal_scaling;
269 
270  focal_scaling.x = new_k_raw.fx / _pre_process_data.orig_k.fx;
271  focal_scaling.y = new_k_raw.fy / _pre_process_data.orig_k.fy;
272 
273  double coarse_grid[5] = { -1, -0.5, 0, 0.5, 1 };
274  double fine_grid[5] = { -1, -0.5, 0, 0.5, 1 };
275 
276  double coarse_grid_x[5];
277  double coarse_grid_y[5];
278 
279  for (auto i = 0; i < 5; i++)
280  {
281  coarse_grid_x[i] = coarse_grid[i] * _max_scaling_step + (double)_pre_process_data.last_los_error.los_scaling_x;
282  coarse_grid_y[i] = coarse_grid[i] * _max_scaling_step + (double)_pre_process_data.last_los_error.los_scaling_y;
283  fine_grid[i] = fine_grid[i] * 0.6* _max_scaling_step;
284  }
285 
286  double grid_y[SIZE_OF_GRID_X];
287  double grid_x[SIZE_OF_GRID_X];
288  ndgrid_my(coarse_grid_y, coarse_grid_x, grid_y, grid_x);
289 
290  auto opt_scaling = run_scaling_optimization_step(regs, dsm_regs, grid_x, grid_y, focal_scaling, data);
291 
292  if (data)
293  {
294  data->k2dsm_data_p.focal_scaling = focal_scaling;
295  data->k2dsm_data_p.opt_scaling = opt_scaling;
296  }
297 
298 
299  double fine_grid_x[SIZE_OF_GRID_X] = { 0 };
300  double fine_grid_y[SIZE_OF_GRID_X] = { 0 };
301 
302  for (auto i = 0; i < 5; i++)
303  {
304  fine_grid_x[i] = fine_grid[i] + opt_scaling.x;
305  fine_grid_y[i] = fine_grid[i] + opt_scaling.y;
306  }
307 
308  ndgrid_my(fine_grid_y, fine_grid_x, grid_y, grid_x);
309  auto los_scaling = run_scaling_optimization_step(regs, dsm_regs, grid_x, grid_y, focal_scaling);
310 
311  auto max_step_with_margin = 1.01*_max_scaling_step;
312 
313  los_scaling.x
314  = std::min( std::max( los_scaling.x, _pre_process_data.last_los_error.los_scaling_x
315  - max_step_with_margin ),
316  _pre_process_data.last_los_error.los_scaling_x + max_step_with_margin );
317  los_scaling.y
318  = std::min( std::max( los_scaling.y, _pre_process_data.last_los_error.los_scaling_y
319  - max_step_with_margin ),
320  _pre_process_data.last_los_error.los_scaling_y + max_step_with_margin );
321 
322  return los_scaling;
323 }
324 
326 (
327  const rs2_dsm_params_double& ac_data,
328  const algo_calibration_registers& dsm_regs,
329  double2 los_shift,
330  double2 los_scaling
331 )
332 {
333  rs2_dsm_params_double ac_data_out = ac_data;
334  ac_data_out.model = ac_data.model;
335  switch (ac_data_out.model)
336  {
338  ac_data_out.h_scale = 1;
339  ac_data_out.v_scale = 1;
340  ac_data_out.h_offset = 0;
341  ac_data_out.v_offset = 0;
342  break;
344  ac_data_out.h_scale = 1 / los_scaling.x ;
345  ac_data_out.v_scale = 1 / los_scaling.y ;
346  ac_data_out.h_offset = -los_shift.x / los_scaling.x;
347  ac_data_out.v_offset = -los_shift.y / los_scaling.y;
348  break;
350  ac_data_out.h_scale = 1 / los_scaling.x;
351  ac_data_out.v_scale = 1 / los_scaling.y;
352  _dsm_regs = apply_ac_res_on_dsm_model(ac_data, dsm_regs, inverse); // the one used for assessing LOS error
353  ac_data_out.h_offset
354  = -( _dsm_regs.EXTLdsmXoffset * ( 1 - los_scaling.x ) + los_shift.x )
356  ac_data_out.v_offset
357  = -( _dsm_regs.EXTLdsmYoffset * ( 1 - los_scaling.y ) + los_shift.y )
359  break;
360 
361  }
362  return ac_data_out;
363 }
364 
366 (
367  algo_calibration_info const & regs,
368  algo_calibration_registers const &dsm_regs,
369  double scaling_grid_x[SIZE_OF_GRID_X],
370  double scaling_grid_y[SIZE_OF_GRID_X],
371  double2 focal_scaling,
372  data_collect* data)
373 {
374  auto opt_k = optimize_k_under_los_error(regs, dsm_regs, scaling_grid_x, scaling_grid_y);
375 
376  double fx_scaling_on_grid[SIZE_OF_GRID_X];
377  double fy_scaling_on_grid[SIZE_OF_GRID_X];
378 
379  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
380  {
381  fx_scaling_on_grid[i] = opt_k[i].mat[0][0] / _pre_process_data.orig_k.fx;
382  fy_scaling_on_grid[i] = opt_k[i].mat[1][1] / _pre_process_data.orig_k.fy;
383  }
384  double err_l2[SIZE_OF_GRID_X];
385  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
386  {
387  err_l2[i] = std::sqrt(std::pow(fx_scaling_on_grid[i] - focal_scaling.x, 2) + std::pow(fy_scaling_on_grid[i] - focal_scaling.y, 2));
388  }
389 
390  double sg_mat[SIZE_OF_GRID_X][SIZE_OF_GRID_Y];
391 
392  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
393  {
394  sg_mat[i][0] = scaling_grid_x[i] * scaling_grid_x[i];
395  sg_mat[i][1] = scaling_grid_y[i] * scaling_grid_y[i];
396  sg_mat[i][2] = scaling_grid_x[i] * scaling_grid_y[i];
397  sg_mat[i][3] = scaling_grid_x[i];
398  sg_mat[i][4] = scaling_grid_y[i];
399  sg_mat[i][5] = 1;
400  }
401 
402  double sg_mat_tag_x_sg_mat[36] = { 0 };
403  double sg_mat_tag_x_err_l2[6] = { 0 };
404 
405  for (auto i = 0; i < 6; i++)
406  {
407  for (auto j = 0; j < 6; j++)
408  {
409  for (auto l = 0; l < 25; l++)
410  {
411  sg_mat_tag_x_sg_mat[i * 6 + j] += sg_mat[l][i] * sg_mat[l][j];
412  }
413 
414  }
415  }
416 
417  for (auto j = 0; j < 6; j++)
418  {
419  for (auto l = 0; l < 25; l++)
420  {
421  sg_mat_tag_x_err_l2[j] += sg_mat[l][j] * err_l2[l];
422  }
423  }
424 
425  double quad_coef[6];
426  direct_inv_6x6(sg_mat_tag_x_sg_mat, sg_mat_tag_x_err_l2, quad_coef);
427 
428 
429 
430  double A[4] = { quad_coef[0], quad_coef[2] / 2, quad_coef[2] / 2, quad_coef[1] };
431  double B[2] = { quad_coef[3] , quad_coef[4] };
432  double opt_scaling[2];
433 
434  direct_inv_2x2(A, B, opt_scaling);
435  opt_scaling[0] = -opt_scaling[0] / 2;
436  opt_scaling[1] = -opt_scaling[1] / 2;
437 
438  if (data)
439  {
440  data->k2dsm_data_p.errL2 = std::vector<double>(std::begin(err_l2), std::end(err_l2));
441 
442  data->k2dsm_data_p.sg_mat.resize(SIZE_OF_GRID_X);
443  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
444  {
445  data->k2dsm_data_p.sg_mat[i].resize(SIZE_OF_GRID_Y);
446  for (auto j = 0; j < SIZE_OF_GRID_Y; j++)
447  {
448  data->k2dsm_data_p.sg_mat[i][j] = sg_mat[i][j];
449  }
450  }
451 
452  data->k2dsm_data_p.sg_mat_tag_x_sg_mat = std::vector<double>(std::begin(sg_mat_tag_x_sg_mat), std::end(sg_mat_tag_x_sg_mat));
453  data->k2dsm_data_p.sg_mat_tag_x_err_l2 = std::vector<double>(std::begin(sg_mat_tag_x_err_l2), std::end(sg_mat_tag_x_err_l2));
454  data->k2dsm_data_p.quad_coef = std::vector<double>(std::begin(quad_coef), std::end(quad_coef));
455  data->k2dsm_data_p.opt_scaling_1 = { opt_scaling[0], opt_scaling[1] };
456  }
457  // sanity check
458 
459  double min_x, min_y, max_x, max_y;
460  min_x = max_x = scaling_grid_x[0];
461  min_y = max_y = scaling_grid_y[0];
462 
463  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
464  {
465  if (min_x > scaling_grid_x[i])
466  min_x = scaling_grid_x[i];
467 
468  if (min_y > scaling_grid_y[i])
469  min_y = scaling_grid_y[i];
470 
471  if (max_x < scaling_grid_x[i])
472  max_x = scaling_grid_x[i];
473 
474  if (max_y < scaling_grid_y[i])
475  max_y = scaling_grid_y[i];
476  }
477 
478  auto is_pos_def = (quad_coef[0] + quad_coef[1]) > 0 && (quad_coef[0] * quad_coef[1] - quad_coef[2] * quad_coef[2] / 4) > 0;
479  auto is_with_in_lims = (opt_scaling[0] > min_x) && (opt_scaling[0] < max_x) && (opt_scaling[1] > min_y) && (opt_scaling[1] < max_y);
480 
481  if (!is_pos_def || !is_with_in_lims)
482  {
483  double min_err = err_l2[0];
484  int ind_min = 0;
485  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
486  {
487  if (min_err > err_l2[i])
488  {
489  min_err = err_l2[i];
490  ind_min = i;
491  }
492  }
493  opt_scaling[0] = scaling_grid_x[ind_min];
494  opt_scaling[1] = scaling_grid_y[ind_min];
495  }
496  return { opt_scaling[0], opt_scaling[1] };
497 }
498 
499 std::vector<double3x3> k_to_DSM::optimize_k_under_los_error
500 (
501  algo_calibration_info const & regs,
502  algo_calibration_registers const &dsm_regs,
503  double scaling_grid_x[SIZE_OF_GRID_X],
504  double scaling_grid_y[SIZE_OF_GRID_X]
505 )
506 {
507  auto orig_k = _pre_process_data.orig_k;
508 
509  std::vector<double3x3> res(SIZE_OF_GRID_X, { 0 });
510 
511  for (auto i = 0; i < SIZE_OF_GRID_X; i++)
512  {
513  std::vector<double2> los(_pre_process_data.los_orig.size());
514  std::vector<double3> updated_pixels(_pre_process_data.los_orig.size());
515 
516  for (auto j = 0; j < updated_pixels.size(); j++)
517  {
518  los[j].x = scaling_grid_x[i] * _pre_process_data.los_orig[j].x;
519  los[j].y = scaling_grid_y[i] * _pre_process_data.los_orig[j].y;
520  }
521  auto updated_vertices = convert_los_to_norm_vertices(regs, dsm_regs, los);
522 
523  for (auto i = 0; i < updated_vertices.size(); i++)
524  {
525  updated_pixels[i].x = updated_vertices[i].x*orig_k.fx + updated_vertices[i].z*orig_k.ppx;
526  updated_pixels[i].y = updated_vertices[i].y*orig_k.fy + updated_vertices[i].z*orig_k.ppy;
527  updated_pixels[i].z = updated_vertices[i].z;
528  }
529 
530  std::vector<double2> v1(updated_pixels.size());
531  std::vector<double2> v2(updated_pixels.size());
532  std::vector<double> p1(updated_pixels.size());
533  std::vector<double> p2(updated_pixels.size());
534 
535  for (auto i = 0; i < v1.size(); i++)
536  {
538  v1[i].y = 0;
539 
540  v2[i].x = 0;
542 
543  p1[i] = updated_pixels[i].x - orig_k.ppx*_pre_process_data.vertices_orig[i].z;
544  p2[i] = updated_pixels[i].y - orig_k.ppy*_pre_process_data.vertices_orig[i].z;
545  }
546  v1.insert(v1.end(), v2.begin(), v2.end());
547  p1.insert(p1.end(), p2.begin(), p2.end());
548 
549  double vtag_x_v[4] = { 0 };
550  double vtag_x_p[2] = { 0 };
551 
552  for (auto i = 0; i < v1.size(); i++)
553  {
554  vtag_x_v[0] += v1[i].x*v1[i].x;
555  vtag_x_v[1] += v1[i].x*v1[i].y;
556  vtag_x_v[2] += v1[i].y*v1[i].x;
557  vtag_x_v[3] += v1[i].y*v1[i].y;
558 
559  vtag_x_p[0] += v1[i].x*p1[i];
560  vtag_x_p[1] += v1[i].y*p1[i];
561  }
562 
563  double inv[2];
564 
565  direct_inv_2x2(vtag_x_v, vtag_x_p, inv);
566 
567  double3x3 mat = { inv[0],0.0,orig_k.ppx ,
568  0.0,inv[1],orig_k.ppy ,
569  0.0,0.0,1.0 };
570 
571  res[i] = mat;
572  }
573  return res;
574 }
575 
576 std::vector<double3> k_to_DSM::convert_los_to_norm_vertices
577 (
578  algo_calibration_info const & regs,
579  algo_calibration_registers const &dsm_regs,
580  std::vector<double2> los,
581  data_collect* data
582 )
583 {
584  std::vector<double3> fove_x_indicent_direction(los.size());
585  std::vector<double3> fove_y_indicent_direction(los.size());
586 
587  auto laser_incident = laser_incident_direction({ (double)regs.FRMWlaserangleH , (double)regs.FRMWlaserangleV + 180 });
588 
589  std::vector<double2> dsm(los.size());
590 
591  for (auto i = 0; i < los.size(); i++)
592  {
593  dsm[i].x = (los[i].x + (double)dsm_regs.EXTLdsmXoffset)*(double)dsm_regs.EXTLdsmXscale - (double)2047;
594  dsm[i].y = (los[i].y + (double)dsm_regs.EXTLdsmYoffset)*(double)dsm_regs.EXTLdsmYscale - (double)2047;
595 
596  auto dsm_x = dsm[i].x;
597  auto dsm_y = dsm[i].y;
598 
599  auto dsm_x_corr_coarse = dsm_x + (dsm_x / 2047)*(double)regs.FRMWpolyVars[0] +
600  std::pow(dsm_x / 2047, 2)*(double)regs.FRMWpolyVars[1] +
601  std::pow(dsm_x / 2047, 3)*(double)regs.FRMWpolyVars[2];
602 
603  auto dsm_y_corr_coarse = dsm_y + (dsm_x / 2047)*(double)regs.FRMWpitchFixFactor;
604 
605  auto dsm_x_corr = dsm_x_corr_coarse + (dsm_x_corr_coarse / 2047)*(double)regs.FRMWundistAngHorz[0] +
606  std::pow(dsm_x_corr_coarse / 2047, 2)*(double)regs.FRMWundistAngHorz[1] +
607  std::pow(dsm_x_corr_coarse / 2047, 3)*(double)regs.FRMWundistAngHorz[2] +
608  std::pow(dsm_x_corr_coarse / 2047, 4)*(double)regs.FRMWundistAngHorz[3];
609 
610  auto dsm_y_corr = dsm_y_corr_coarse;
611 
612  auto mode = 1;
613  auto ang_x = dsm_x_corr * ((double)regs.FRMWxfov[mode] * 0.25 / 2047);
614  auto ang_y = dsm_y_corr * ((double)regs.FRMWyfov[mode] * 0.25 / 2047);
615 
616  auto mirror_normal_direction = laser_incident_direction({ ang_x ,ang_y });
617 
618  fove_x_indicent_direction[i] = laser_incident - mirror_normal_direction*(2 * (mirror_normal_direction*laser_incident));
619  }
620 
621  if (data)
622  data->k2dsm_data_p.dsm = dsm;
623 
624  for (auto i = 0; i < fove_x_indicent_direction.size(); i++)
625  {
626  fove_x_indicent_direction[i].x /= sqrt(fove_x_indicent_direction[i].get_norm());
627  fove_x_indicent_direction[i].y /= sqrt(fove_x_indicent_direction[i].get_norm());
628  fove_x_indicent_direction[i].z /= sqrt(fove_x_indicent_direction[i].get_norm());
629  }
630 
631  auto outbound_direction = fove_x_indicent_direction;
632  if (regs.FRMWfovexExistenceFlag)
633  {
634  std::fill(outbound_direction.begin(), outbound_direction.end(), double3{ 0,0,0 });
635  for (auto i = 0; i < fove_x_indicent_direction.size(); i++)
636  {
637  auto ang_pre_exp = rad_to_deg(std::acos(fove_x_indicent_direction[i].z));
638  auto ang_post_exp = ang_pre_exp + ang_pre_exp * (double)regs.FRMWfovexNominal[0] +
639  std::pow(ang_pre_exp, 2) * (double)regs.FRMWfovexNominal[1] +
640  std::pow(ang_pre_exp, 3) * (double)regs.FRMWfovexNominal[2] +
641  std::pow(ang_pre_exp, 4) * (double)regs.FRMWfovexNominal[3];
642 
643  outbound_direction[i].z = std::cos(deg_to_rad(ang_post_exp));
644  auto xy_norm = fove_x_indicent_direction[i].x*fove_x_indicent_direction[i].x +
645  fove_x_indicent_direction[i].y*fove_x_indicent_direction[i].y;
646 
647  auto xy_factor = std::sqrt((1 - outbound_direction[i].z*outbound_direction[i].z) / xy_norm);
648  outbound_direction[i].x = fove_x_indicent_direction[i].x*xy_factor;
649  outbound_direction[i].y = fove_x_indicent_direction[i].y*xy_factor;
650  };
651 
652  }
653  for (auto i = 0; i < outbound_direction.size(); i++)
654  {
655  outbound_direction[i].x /= outbound_direction[i].z;
656  outbound_direction[i].y /= outbound_direction[i].z;
657  outbound_direction[i].z /= outbound_direction[i].z;
658  }
659  return outbound_direction;
660 }
661 
662 std::vector<double3> k_to_DSM::calc_relevant_vertices
663 (
664  const std::vector<uint8_t>& relevant_pixels_image,
665  const rs2_intrinsics_double & k
666 )
667 {
668  std::vector<double3> res;
669 
670  double k_arr[9] = { k.fx, 0, 0,
671  0, k.fy, 0,
672  k.ppx , k.ppy, 1 };
673 
674  double k_arr_inv[9] = { 0 };
675 
676  inv(k_arr, k_arr_inv);
677 
678  double k_t[9] = { 0 };
679 
680  transpose(k_arr_inv, k_t);
681 
682  for (auto i = 0; i < k.height; i++)
683  {
684  for (auto j = 0; j < k.width; j++)
685  {
686  if (relevant_pixels_image[i*k.width + j])
687  {
688  double3 ver;
689  double3 pix = { (double)j, (double)i, (double)1 };
690 
691  ver.x = pix.x*k_t[0] + pix.y*k_t[1] + pix.z*k_t[2];
692  ver.y = pix.x*k_t[3] + pix.y*k_t[4] + pix.z*k_t[5];
693  ver.z = pix.x*k_t[6] + pix.y*k_t[7] + pix.z*k_t[8];
694 
695  res.push_back(ver);
696  }
697  }
698  }
699  return res;
700 }
701 
702 std::vector<double2> k_to_DSM::convert_norm_vertices_to_los
703 (
704  algo_calibration_info const &regs,
705  algo_calibration_registers const &dsm_regs,
706  std::vector< double3 > const & vertices,
708 )
709 {
710  const size_t angle = 45;
711  auto directions = transform_to_direction(vertices);
712 
713  auto fovex_indicent_direction = directions;
715  {
716  std::fill(fovex_indicent_direction.begin(), fovex_indicent_direction.end(), double3{ 0,0,0 });
717  std::vector<double> ang_post_exp(fovex_indicent_direction.size(), 0);
718  for (auto i = 0; i < ang_post_exp.size(); i++)
719  {
720  ang_post_exp[i] = std::acos(directions[i].z)* (double)180. / (double)M_PI;
721  }
722 
723  std::vector<double> ang_grid(angle, 0);
724  std::vector<double> ang_out_on_grid(angle, 0);
725 
726  for (auto i = 0; i < angle; i++)
727  {
728  ang_grid[i] = i;
729  auto fovex_nominal = std::pow(i,1)* (double)regs.FRMWfovexNominal[0] +
730  std::pow(i, 2)* (double)regs.FRMWfovexNominal[1] +
731  std::pow(i, 3)* (double)regs.FRMWfovexNominal[2] +
732  std::pow(i, 4)* (double)regs.FRMWfovexNominal[3];
733 
734  ang_out_on_grid[i] = (double)i + fovex_nominal;
735  }
736  std::vector<double> ang_pre_exp = interp1(ang_out_on_grid, ang_grid, ang_post_exp);
737  //std::vector<double> xy_norm(directions.size(), 0);
738  for (auto i = 0; i < fovex_indicent_direction.size(); i++)
739  {
740  fovex_indicent_direction[i].z = std::cos(ang_pre_exp[i] * M_PI / (double)180.);
741  auto xy_norm = directions[i].x*directions[i].x + directions[i].y*directions[i].y;
742  auto xy_factor = sqrt(((double)1 - (fovex_indicent_direction[i].z* fovex_indicent_direction[i].z)) / xy_norm);
743  fovex_indicent_direction[i].x = directions[i].x*xy_factor;
744  fovex_indicent_direction[i].y = directions[i].y*xy_factor;
745  }
746  }
747 
748  auto laser_incident = laser_incident_direction({ (double)_regs.FRMWlaserangleH , (double)_regs.FRMWlaserangleV + (double)180 });
749 
750  std::vector<double3> mirror_normal_direction(fovex_indicent_direction.size());
751  std::vector<double> dsm_x_corr(fovex_indicent_direction.size());
752  std::vector<double> dsm_y_corr(fovex_indicent_direction.size());
753  std::vector<double> ang_x(fovex_indicent_direction.size());
754  std::vector<double> ang_y(fovex_indicent_direction.size());
755 
756  for (auto i = 0; i < fovex_indicent_direction.size(); i++)
757  {
758  mirror_normal_direction[i].x = fovex_indicent_direction[i].x - laser_incident[0];
759  mirror_normal_direction[i].y = fovex_indicent_direction[i].y - laser_incident[1];
760  mirror_normal_direction[i].z = fovex_indicent_direction[i].z - laser_incident[2];
761 
762  auto norm = sqrt(mirror_normal_direction[i].x*mirror_normal_direction[i].x +
763  mirror_normal_direction[i].y* mirror_normal_direction[i].y +
764  mirror_normal_direction[i].z* mirror_normal_direction[i].z);
765 
766  mirror_normal_direction[i].x /= norm;
767  mirror_normal_direction[i].y /= norm;
768  mirror_normal_direction[i].z /= norm;
769 
770  ang_x[i] = std::atan(mirror_normal_direction[i].x / mirror_normal_direction[i].z)* (double)180. / (double)M_PI;
771  ang_y[i] = std::asin(mirror_normal_direction[i].y)* (double)180. / (double)M_PI;
772 
773  int mirror_mode = 1/*_regs.frmw.mirrorMovmentMode*/;
774 
775  dsm_x_corr[i] = ang_x[i] / (double)(regs.FRMWxfov[mirror_mode - 1] * (double)0.25 / (double)2047);
776  dsm_y_corr[i] = ang_y[i] / (double)(regs.FRMWyfov[mirror_mode - 1] * (double)0.25 / (double)2047);
777  }
778 
779  std::vector<double> dsm_grid(421);
780 
781  auto ind = 0;
782  for (auto i = -2100; i <= 2100; i += 10)
783  {
784  dsm_grid[ind++] = i;
785  }
786 
787  std::vector<double> dsm_x_coarse_on_grid(dsm_grid.size());
788  std::vector<double> dsm_x_corr_on_grid(dsm_grid.size());
789  for (auto i = 0; i < dsm_grid.size(); i ++)
790  {
791  double rot[3] = { std::pow((dsm_grid[i] / (double)2047), 1), std::pow((dsm_grid[i] / 2047), 2), std::pow((dsm_grid[i] / 2047), 3) };
792  dsm_x_coarse_on_grid[i] = dsm_grid[i] + rot[0] * (double)_regs.FRMWpolyVars[0] + rot[1] * (double)_regs.FRMWpolyVars[1] + rot[2] * (double)_regs.FRMWpolyVars[2];
793  auto val = dsm_x_coarse_on_grid[i] / (double)2047;
794  double vals2[4] = { std::pow(val , 1),std::pow(val , 2), std::pow(val , 3) , std::pow(val , 4) };
795  dsm_x_corr_on_grid[i] = dsm_x_coarse_on_grid[i] + vals2[0] * (double)_regs.FRMWundistAngHorz[0] +
796  vals2[1] * (double)_regs.FRMWundistAngHorz[1] +
797  vals2[2] * (double)_regs.FRMWundistAngHorz[2] +
798  vals2[3] * (double)_regs.FRMWundistAngHorz[3];
799  }
800 
801  auto dsm_x = interp1(dsm_x_corr_on_grid, dsm_grid, dsm_x_corr);
802  std::vector<double> dsm_y(dsm_x.size());
803 
804  for (auto i = 0; i < dsm_y.size(); i++)
805  {
806  dsm_y[i] = dsm_y_corr[i] - (dsm_x[i] / (double)2047)*(double)_regs.FRMWpitchFixFactor;
807  }
808 
809  std::vector<double2> res(dsm_x.size());
810 
811  if (data)
812  {
813  data->laser_incident = laser_incident;
814  data->fovex_indicent_direction = fovex_indicent_direction;
815  data->mirror_normal_direction = mirror_normal_direction;
816  data->ang_x = ang_x;
817  data->ang_y = ang_y;
818  data->dsm_x_corr = dsm_x_corr;
819  data->dsm_y_corr = dsm_y_corr;
820  data->dsm_y = dsm_y;
821  data->dsm_x = dsm_x;
822  data->dsm_y = dsm_y;
823  }
824  for (auto i = 0; i < res.size(); i++)
825  {
826  res[i].x = (dsm_x[i] + 2047.) / (double)dsm_regs.EXTLdsmXscale - (double)dsm_regs.EXTLdsmXoffset;
827  res[i].y = (dsm_y[i] + 2047.) / (double)dsm_regs.EXTLdsmYscale - (double)dsm_regs.EXTLdsmYoffset;
828  }
829  return res;
830 }
831 
833 {
834  double2 angle_deg = { angle_rad.x * (double)M_PI / (double)180., (angle_rad.y)* (double)M_PI / (double)180. };
835 
836  double3 laser_incident_direction = { std::cos(angle_deg.y)*std::sin(angle_deg.x),
837  std::sin(angle_deg.y),
838  std::cos(angle_deg.y)*std::cos(angle_deg.x) };
839 
841 }
842 
843 std::vector< double3 > k_to_DSM::transform_to_direction( std::vector< double3 > const & vec )
844 {
845  std::vector< double3 > res( vec.size() );
846 
847  for( auto i = 0; i < vec.size(); i++ )
848  {
849  auto norm = sqrt( vec[i].x * vec[i].x + vec[i].y * vec[i].y + vec[i].z * vec[i].z );
850  res[i] = { vec[i].x / norm, vec[i].y / norm, vec[i].z / norm };
851  }
852  return res;
853 }
double2 run_scaling_optimization_step(algo::depth_to_rgb_calibration::algo_calibration_info const &regs, algo_calibration_registers const &dsm_regs, double scaling_grid_x[SIZE_OF_GRID_X], double scaling_grid_y[SIZE_OF_GRID_X], double2 focal_scaling, data_collect *data=nullptr)
Definition: k-to-dsm.cpp:366
pre_process_data pre_processing(const algo_calibration_info &regs, const rs2_dsm_params_double &ac_data, const algo_calibration_registers &algo_calibration_registers, const rs2_intrinsics_double &k_raw, const std::vector< uint8_t > &relevant_pixels_image, data_collect *data=nullptr)
Definition: k-to-dsm.cpp:151
algo::depth_to_rgb_calibration::algo_calibration_info _regs
Definition: k-to-dsm.h:256
GLuint GLuint end
GLint y
void direct_inv_2x2(const double A[4], const double B[2], double C[2])
GLdouble s
rs2_dsm_params_double convert_los_error_to_ac_data(const rs2_dsm_params_double &ac_data, const algo_calibration_registers &dsm_regs, double2 los_shift, double2 los_scaling)
Definition: k-to-dsm.cpp:326
algo::depth_to_rgb_calibration::algo_calibration_registers _dsm_regs
Definition: k-to-dsm.h:257
std::vector< double3x3 > optimize_k_under_los_error(algo::depth_to_rgb_calibration::algo_calibration_info const &regs, algo_calibration_registers const &dsm_regs, double scaling_grid_x[25], double scaling_grid_y[25])
Definition: k-to-dsm.cpp:500
GLfloat angle
Definition: glext.h:6819
GLdouble GLdouble GLdouble w
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:1960
GLdouble GLdouble z
std::vector< double > interp1(const std::vector< double > &ind, const std::vector< double > &vals, const std::vector< double > &intrp)
GLuint GLfloat * val
rs2_intrinsics_double rotate_k_mat(const rs2_intrinsics_double &k_mat)
Definition: k-to-dsm.cpp:34
const pre_process_data & get_pre_process_data() const
Definition: k-to-dsm.cpp:255
not_this_one begin(...)
rs2_dsm_params_double convert_new_k_to_DSM(const rs2_intrinsics_double &old_k, const rs2_intrinsics_double &new_k, const z_frame_data &z, std::vector< double3 > &new_vertices, rs2_dsm_params_double const &previous_dsm_params, algo_calibration_registers &new_dsm_regs, data_collect *data=nullptr)
Definition: k-to-dsm.cpp:177
GLenum mode
GLdouble x
GLint j
void rotate_180(const uint8_t *A, uint8_t *B, uint32_t w, uint32_t h)
algo_calibration_registers apply_ac_res_on_dsm_model(const rs2_dsm_params_double &ac_data, const algo_calibration_registers &regs, const ac_to_dsm_dir &type)
Definition: k-to-dsm.cpp:54
double2 convert_k_to_los_error(algo::depth_to_rgb_calibration::algo_calibration_info const &regs, algo_calibration_registers const &dsm_regs, rs2_intrinsics_double const &k_raw, data_collect *data=nullptr)
Definition: k-to-dsm.cpp:261
convert_norm_vertices_to_los_data second_norm_vertices_to_los_data
Definition: optimizer.h:216
#define AC_LOG(TYPE, MSG)
GLdouble GLdouble GLint GLint GLdouble v1
k_to_DSM(const rs2_dsm_params_double &orig_dsm_params, algo_calibration_info const &cal_info, algo_calibration_registers const &cal_regs, const double &max_scaling_step)
Definition: k-to-dsm.cpp:43
static const struct @18 vertices[3]
convert_norm_vertices_to_los_data first_norm_vertices_to_los_data
Definition: optimizer.h:202
GLenum type
int min(int a, int b)
Definition: lz4s.c:73
std::ostream & operator<<(std::ostream &, rs2_dsm_params_double const &)
Definition: k-to-dsm.cpp:14
los_shift_scaling convert_ac_data_to_los_error(const algo_calibration_registers &algo_calibration_registers, const rs2_dsm_params_double &ac_data)
Definition: k-to-dsm.cpp:119
int i
GLuint res
Definition: glext.h:8856
const GLdouble * v2
std::vector< double2 > convert_norm_vertices_to_los(const algo_calibration_info &regs, const algo_calibration_registers &algo_calibration_registers, std::vector< double3 > const &vertices, convert_norm_vertices_to_los_data *data=nullptr)
Definition: k-to-dsm.cpp:703
std::vector< double3 > transform_to_direction(std::vector< double3 > const &)
Definition: k-to-dsm.cpp:843
std::vector< double3 > calc_relevant_vertices(const std::vector< uint8_t > &relevant_pixels_image, const rs2_intrinsics_double &k)
Definition: k-to-dsm.cpp:663
void direct_inv_6x6(const double A[36], const double B[6], double C[6])
void ndgrid_my(const double vec1[5], const double vec2[5], double yScalingGrid[25], double xScalingGrid[25])
std::vector< double3 > convert_los_to_norm_vertices(algo::depth_to_rgb_calibration::algo_calibration_info const &regs, algo_calibration_registers const &dsm_regs, std::vector< double2 > los, data_collect *data=nullptr)
Definition: k-to-dsm.cpp:577
Definition: parser.hpp:150
std::string to_string(T value)


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:21