LibMultiSense/ImageCalUtility/ImageCalUtility.cc
Go to the documentation of this file.
1 
37 #ifdef WIN32
38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
40 #endif
41 
42 #include <windows.h>
43 #include <winsock2.h>
44 #else
45 #include <unistd.h>
46 #endif
47 
48 #include <chrono>
49 #include <csignal>
50 #include <filesystem>
51 #include <fstream>
52 #include <iostream>
53 #include <string.h>
54 
55 #include <MultiSense/MultiSenseChannel.hh>
56 
57 #include "CalibrationYaml.hh"
58 #include "getopt/getopt.h"
59 
60 namespace lms = multisense;
61 
62 namespace
63 {
64 
65 void usage(const char *name)
66 {
67  std::cerr << "USAGE: " << name << " -e <extrinsics-file> -i <intrinsics-file> [<options>]" << std::endl;
68  std::cerr << "Where <options> are:" << std::endl;
69  std::cerr << "\t-a <current_address> : CURRENT IPV4 address (default=10.66.171.21)" << std::endl;
70  std::cerr << "\t-m <mtu> : MTU to use to communicate with the camera (default=1500)" << std::endl;
71  std::cerr << "\t-s : Set the input calibration(default=false)" << std::endl;
72  std::cerr << "\t-y : Disable confirmation prompt (default=false)" << std::endl;
73  exit(1);
74 }
75 
76 template <size_t H, size_t W>
77 std::array<std::array<float, W>, H> convert_matrix(const std::vector<float> &source)
78 {
79  if ((H * W) != source.size())
80  {
81  throw std::runtime_error("Matrix sizes do not match");
82  }
83 
84  std::array<std::array<float, W>, H> output;
85 
86  memcpy(&output[0][0], source.data(), sizeof(float) * source.size());
87 
88  return output;
89 }
90 
91 lms::CameraCalibration::DistortionType get_distortion_type(size_t length)
92 {
93  switch (length)
94  {
95  case 0:
96  return lms::CameraCalibration::DistortionType::NONE;
97  case 5:
98  return lms::CameraCalibration::DistortionType::PLUMBBOB;
99  case 8:
100  return lms::CameraCalibration::DistortionType::RATIONAL_POLYNOMIAL;
101  }
102 
103  return lms::CameraCalibration::DistortionType::NONE;
104 }
105 
106 lms::CameraCalibration read_cal(const std::map<std::string, std::vector<float>> &intrinsics,
107  const std::map<std::string, std::vector<float>> &extrinsics,
108  size_t index)
109 {
110  lms::CameraCalibration output{};
111 
112  output.K = convert_matrix<3, 3>(intrinsics.at("M" + std::to_string(index)));
113  output.R = convert_matrix<3, 3>(extrinsics.at("R" + std::to_string(index)));
114  output.P = convert_matrix<3, 4>(extrinsics.at("P" + std::to_string(index)));
115  output.D = intrinsics.at("D" + std::to_string(index));
116  output.distortion_type = get_distortion_type(output.D.size());
117 
118  return output;
119 }
120 
121 void write_cal(std::ofstream &intrinsics, std::ofstream &extrinsics, const lms::CameraCalibration &cal, size_t index)
122 {
123  writeMatrix(intrinsics, "M" + std::to_string(index), 3, 3, &cal.K[0][0]);
124  writeMatrix(intrinsics, "D" + std::to_string(index), 1, cal.D.size(), cal.D.data());
125  writeMatrix(extrinsics, "P" + std::to_string(index), 3, 4, &cal.P[0][0]);
126  writeMatrix(extrinsics, "R" + std::to_string(index), 3, 3, &cal.R[0][0]);
127 }
128 
129 }
130 
131 int main(int argc, char** argv)
132 {
133  std::string ip_address = "10.66.171.21";
134  int16_t mtu = 1500;
135  std::filesystem::path intrinsics_path{};
136  std::filesystem::path extrinsics_path{};
137  bool set_cal = false;
138  bool disable_confirmation = false;
139 
140  int c;
141  while(-1 != (c = getopt(argc, argv, "a:m:e:i:sy")))
142  {
143  switch(c)
144  {
145  case 'a': ip_address = std::string(optarg); break;
146  case 'm': mtu = static_cast<uint16_t>(atoi(optarg)); break;
147  case 'i': intrinsics_path = optarg; break;
148  case 'e': extrinsics_path = optarg; break;
149  case 's': set_cal = true; break;
150  case 'y': disable_confirmation = true; break;
151  default: usage(*argv); break;
152  }
153  }
154 
155  if (set_cal && (!std::filesystem::exists(intrinsics_path) || !std::filesystem::exists(extrinsics_path)))
156  {
157  std::cerr << "Invalid input or calibration paths" << std::endl;
158  usage(*argv);
159  return 1;
160  }
161 
162  if (!set_cal && !disable_confirmation &&
163  (std::filesystem::exists(intrinsics_path) || std::filesystem::exists(extrinsics_path)))
164  {
165  std::cout << "One or both of the input file already exists\n" << std::endl;
166  std::cout << "Really overwrite these files? (y/n):" << std::endl;
167 
168  if (const int reply = getchar(); reply != 'Y' && reply != 'y')
169  {
170  std::cerr << "Aborting" << std::endl;
171  return 1;
172  }
173  }
174 
175  const auto channel = lms::Channel::create(lms::Channel::Config{ip_address, mtu});
176  if (!channel)
177  {
178  std::cerr << "Failed to create channel" << std::endl;
179  return 1;
180  }
181 
182  auto calibration = channel->get_calibration();
183 
184  if (set_cal)
185  {
186  std::cout << "Attempting to set the MultiSense calibration" << std::endl;
187  std::ifstream intrinsics{};
188  std::ifstream extrinsics{};
189 
190  intrinsics.open(intrinsics_path);
191  extrinsics.open(extrinsics_path);
192 
193  if (!intrinsics.is_open() || !extrinsics.is_open())
194  {
195  std::cerr << "Error opening calibration files" << std::endl;
196  return 1;
197  }
198 
199  std::map<std::string, std::vector<float>> intrinsics_data{};
200  parseYaml(intrinsics, intrinsics_data);
201 
202  std::map<std::string, std::vector<float>> extrinsics_data{};
203  parseYaml(extrinsics, extrinsics_data);
204 
205  calibration.left = read_cal(intrinsics_data, extrinsics_data, 1);
206  calibration.right = read_cal(intrinsics_data, extrinsics_data, 2);
207 
208  if (calibration.aux)
209  {
210  calibration.aux = read_cal(intrinsics_data, extrinsics_data, 3);
211  }
212 
213  if (const auto status = channel->set_calibration(calibration); status != lms::Status::OK)
214  {
215  std::cerr << "Unable to set the calibration" << std::endl;
216  return 1;
217  }
218 
219  std::cout << "Image calibration successfully updated" << std::endl;
220  }
221  else
222  {
223  std::ofstream intrinsics{};
224  std::ofstream extrinsics{};
225 
226  intrinsics.open(intrinsics_path, std::ios_base::out | std::ios_base::trunc);
227  extrinsics.open(extrinsics_path, std::ios_base::out | std::ios_base::trunc);
228 
229  if (!intrinsics.is_open() || !extrinsics.is_open())
230  {
231  std::cerr << "Error opening calibration files" << std::endl;
232  return 1;
233  }
234 
235  intrinsics << "%YAML:1.0\n";
236  extrinsics << "%YAML:1.0\n";
237 
238  write_cal(intrinsics, extrinsics, calibration.left, 1);
239  write_cal(intrinsics, extrinsics, calibration.right, 2);
240 
241  if (calibration.aux)
242  {
243  write_cal(intrinsics, extrinsics, calibration.aux.value(), 3);
244  }
245  }
246 
247  return 0;
248 }
249 
usage
static void usage()
Definition: FirmwareUpdateUtility.cc:51
multisense::CameraCalibration::R
std::array< std::array< float, 3 >, 3 > R
Rotation matrix which takes points in the unrectified camera frame and transform them in to the recti...
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:136
getopt.h
getopt
int getopt(int argc, char **argv, char *opts)
Definition: getopt.c:31
image_cal_utility.write_cal
def write_cal(intrinsics, extrinsics, index, camera_cal)
Definition: image_cal_utility.py:62
multisense::CameraCalibration::P
std::array< std::array< float, 4 >, 3 > P
Rectified projection matrix which takes points in the origin camera coordinate frame and projects the...
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:142
multisense::CameraCalibration::K
std::array< std::array< float, 3 >, 3 > K
Unrectified camera projection matrix stored in row-major ordering.
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:130
parseYaml
std::istream & parseYaml(std::istream &stream, std::map< std::string, std::vector< float > > &data)
Definition: CalibrationYaml.hh:146
multisense::CameraCalibration::D
std::vector< float > D
Coefficients for the distortion model.
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:152
writeMatrix
std::ostream & writeMatrix(std::ostream &stream, std::string const &name, uint32_t rows, uint32_t columns, T const *data)
Definition: CalibrationYaml.hh:45
image_cal_utility.read_cal
def read_cal(intrinsics, extrinsics, index)
Definition: image_cal_utility.py:45
main
int main(int argc, char **argv)
Definition: LibMultiSense/ImageCalUtility/ImageCalUtility.cc:131
multisense::Channel::create
static std::unique_ptr< Channel > create(const Config &config, const ChannelImplementation &impl=ChannelImplementation::LEGACY)
Factory create function which allows for switching between different channel implementations.
Definition: factory.cc:42
multisense::CameraCalibration::DistortionType
DistortionType
Distortion type.
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:120
multisense
Definition: factory.cc:39
CalibrationYaml.hh
optarg
char * optarg
Definition: getopt.c:29
multisense::CameraCalibration
Definition: LibMultiSense/include/MultiSense/MultiSenseTypes.hh:115
multisense::to_string
std::string to_string(const Status &status)
Convert a status object to a user readable string.
Definition: utilities.cc:137


multisense_lib
Author(s):
autogenerated on Thu Apr 17 2025 02:49:09