mono_camera.cpp
Go to the documentation of this file.
2 
5 
6 MonoCamera::MonoCamera(ros::NodeHandle nh, std::string serial, std::string fileCameraPath, bool fixed,
7  std::string cameraFrame, std::string targetFrame, std::string linkFrame)
8  : Camera(nh, std::move(serial), std::move(fileCameraPath), fixed, std::move(cameraFrame), std::move(targetFrame),
9  std::move(linkFrame))
10 {
11  cameraInfo = boost::make_shared<sensor_msgs::CameraInfo>();
12  rectifiedCameraInfo = boost::make_shared<sensor_msgs::CameraInfo>();
13 
15  ::make_unique<RequestDataMonoServer>(nh, "request_data", boost::bind(&MonoCamera::onRequestData, this, _1));
17  ::make_unique<LocatePatternMonoServer>(nh, "locate_pattern", boost::bind(&MonoCamera::onLocatePattern, this, _1));
18 
19  image_transport::ImageTransport imageTransport(nh);
20  rawImagePublisher = imageTransport.advertiseCamera("raw/image", 1);
21  rectifiedImagePublisher = imageTransport.advertiseCamera("rectified/image", 1);
22 }
23 
25 {
26  ROS_DEBUG("Capturing an image...");
27 
28  NxLibCommand capture(cmdCapture, serial);
29  capture.parameters()[itmCameras] = serial;
30  capture.execute();
31 
32  NxLibItem imageNode = cameraNode[itmImages][itmRaw];
33  if (imageNode.isArray())
34  {
35  imageNode = imageNode[0];
36  }
37 
38  if (isFileCamera)
39  {
40  // This workaround is needed, because the timestamp of captures from file cameras will not change over time. When
41  // looking up the current tf tree, this will result in errors, because the time of the original timestamp is
42  // requested, which lies in the past (and most often longer than the tfBuffer will store the transform!)
43  return ros::Time::now();
44  }
45 
46  return timestampFromNxLibNode(imageNode);
47 }
48 
50 {
51  Camera::open();
52 
54 
55  return true;
56 }
57 
59 {
62 }
63 
64 void MonoCamera::fillCameraInfoFromNxLib(sensor_msgs::CameraInfoPtr const& info, bool rectified)
65 {
67 
68  NxLibItem calibrationNode = cameraNode[itmCalibration];
69 
70  info->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
71  info->D.clear();
72 
73  if(rectified) {
74  info->D.resize(5,0.);
75  } else {
76  fillDistortionParamsFromNxLib(calibrationNode[itmDistortion], info);
77  }
78 
79  info->K.fill(0);
80  info->P.fill(0);
81  info->R.fill(0);
82  for (int row = 0; row < 3; row++)
83  {
84  for (int column = 0; column < 3; column++)
85  {
86  info->K[3 * row + column] = calibrationNode[itmCamera][column][row].asDouble();
87  info->P[4 * row + column] = info->K[3 * row + column];
88  if (row == column)
89  {
90  info->R[3 * row + column] = 1.0f;
91  }
92  }
93  }
94 }
95 
97 {
99  requestDataServer->start();
100  locatePatternServer->start();
101 }
102 
103 void MonoCamera::onRequestData(ensenso_camera_msgs::RequestDataMonoGoalConstPtr const& goal)
104 {
105  START_NXLIB_ACTION(RequestDataMono, requestDataServer)
106 
107  ensenso_camera_msgs::RequestDataMonoResult result;
108  ensenso_camera_msgs::RequestDataMonoFeedback feedback;
109 
110  bool publishResults = goal->publish_results;
111  if (!goal->publish_results && !goal->include_results_in_response)
112  {
113  publishResults = true;
114  }
115 
116  bool requestRectified = goal->request_rectified_images;
117  if (!goal->request_rectified_images && !goal->request_raw_images)
118  {
119  requestRectified = true;
120  }
121 
122  capture();
123 
125 
126  feedback.images_acquired = true;
127  requestDataServer->publishFeedback(feedback);
128 
129  if (goal->request_raw_images)
130  {
131  auto rawImages = imagesFromNxLibNode(cameraNode[itmImages][itmRaw], cameraFrame);
132  cameraInfo->header.stamp = rawImages[0]->header.stamp;
133  cameraInfo->header.frame_id = cameraFrame;
134  if (goal->include_results_in_response)
135  {
136  for (auto const& image : rawImages)
137  {
138  result.raw_images.push_back(*image);
139  }
140  result.camera_info = *cameraInfo;
141  }
142  if (publishResults)
143  {
144  rawImagePublisher.publish(rawImages[0], cameraInfo);
145  }
146  }
147 
149 
150  if (requestRectified)
151  {
152  NxLibCommand rectify(cmdRectifyImages, serial);
153  rectify.parameters()[itmCameras] = serial;
154  rectify.execute();
155 
156  auto rectifiedImages = imagesFromNxLibNode(cameraNode[itmImages][itmRectified], cameraFrame);
157  rectifiedCameraInfo->header.stamp = rectifiedImages[0]->header.stamp;
158  rectifiedCameraInfo->header.frame_id = cameraFrame;
159  if (goal->include_results_in_response)
160  {
161  for (auto const& image : rectifiedImages)
162  {
163  result.rectified_images.push_back(*image);
164  }
165  result.rectified_camera_info = *rectifiedCameraInfo;
166  }
167  if (publishResults)
168  {
170  }
171  }
172 
173  requestDataServer->setSucceeded(result);
174 
175  FINISH_NXLIB_ACTION(RequestDataMono)
176 }
177 
178 void MonoCamera::onSetParameter(ensenso_camera_msgs::SetParameterGoalConstPtr const& goal)
179 {
181 
182  ensenso_camera_msgs::SetParameterResult result;
183 
184  loadParameterSet(goal->parameter_set);
185 
186  result.parameter_file_applied = false;
187  if (!goal->parameter_file.empty())
188  {
189  result.parameter_file_applied = loadSettings(goal->parameter_file);
190  if (!result.parameter_file_applied)
191  {
192  server->setAborted(result);
193  return;
194  }
195  }
196 
197  // Synchronize to make sure that we read back the correct values.
198  NxLibCommand synchronize(cmdSynchronize, serial);
199  synchronize.parameters()[itmCameras] = serial;
200  synchronize.execute();
201 
202  saveParameterSet(goal->parameter_set);
203 
204  // Calibration could have changed after setting new parameters
206 
207  // Read back the actual values.
208  for (auto const& parameter : goal->parameters)
209  {
210  result.results.push_back(*readParameter(parameter.key));
211  }
212 
213  setParameterServer->setSucceeded(result);
214 
215  FINISH_NXLIB_ACTION(SetParameter)
216 }
217 
218 void MonoCamera::onLocatePattern(ensenso_camera_msgs::LocatePatternMonoGoalConstPtr const& goal)
219 {
220  START_NXLIB_ACTION(LocatePatternMono, locatePatternServer)
221 
222  ensenso_camera_msgs::LocatePatternMonoResult result;
223  ensenso_camera_msgs::LocatePatternMonoFeedback feedback;
224 
225  loadParameterSet(goal->parameter_set);
226 
227  int numberOfShots = goal->number_of_shots;
228  if (numberOfShots < 1)
229  {
230  numberOfShots = 1;
231  }
232 
233  std::vector<MonoCalibrationPattern> patterns;
234  ros::Time imageTimestamp;
235  for (int i = 0; i < numberOfShots; i++)
236  {
238 
239  ros::Time timestamp = capture();
240  if (i == 0)
241  imageTimestamp = timestamp;
242 
244 
245  if (i == (numberOfShots - 1))
246  {
247  // The last image has been captured.
248  feedback.images_acquired = true;
249  locatePatternServer->publishFeedback(feedback);
250  }
251 
252  bool clearBuffer = (i == 0);
253  patterns = collectPattern(clearBuffer);
254  if (patterns.empty())
255  {
256  result.found_pattern = false;
257  locatePatternServer->setSucceeded(result);
258  return;
259  }
260 
261  if (patterns.size() > 1)
262  {
263  // Cannot average multiple shots of multiple patterns. We will cancel the
264  // capturing and estimate the pose of each pattern individually.
265  break;
266  }
267  }
268 
269  result.found_pattern = true;
270  result.mono_patterns.resize(patterns.size());
271  for (size_t i = 0; i < patterns.size(); i++)
272  {
273  patterns[i].writeToMessage(result.mono_patterns[i]);
274  }
275 
277 
278  std::string patternFrame = targetFrame;
279  if (!goal->target_frame.empty())
280  {
281  patternFrame = goal->target_frame;
282  }
283 
284  result.frame = patternFrame;
285 
286  if (patterns.size() > 1)
287  {
288  // Estimate the pose of all the patterns we found.
289  auto patternPoses = estimatePatternPoses(imageTimestamp, patternFrame);
290 
291  result.mono_pattern_poses.resize(patternPoses.size());
292  for (size_t i = 0; i < patternPoses.size(); i++)
293  {
294  result.mono_pattern_poses[i] = stampedPoseFromTransform(patternPoses[i]);
295  }
296  }
297  else
298  {
299  // Estimate the pose of a single pattern, averaging over the different
300  // shots.
301  auto patternPose = estimatePatternPose(imageTimestamp, patternFrame);
302 
303  result.mono_pattern_poses.resize(1);
304  result.mono_pattern_poses[0] = stampedPoseFromTransform(patternPose);
305  }
306 
307  if (!goal->tf_frame.empty())
308  {
309  if (patterns.size() == 1)
310  {
311  geometry_msgs::TransformStamped transform = transformFromPose(result.mono_pattern_poses[0], goal->tf_frame);
312  transformBroadcaster->sendTransform(transform);
313  }
314  else
315  {
316  ROS_WARN("Cannot publish the pattern pose in TF, because there are "
317  "multiple patterns!");
318  }
319  }
320 
321  locatePatternServer->setSucceeded(result);
322 
323  FINISH_NXLIB_ACTION(LocatePatternMono)
324 }
325 
326 std::vector<MonoCalibrationPattern> MonoCamera::collectPattern(bool clearBuffer) const
327 {
328  if (clearBuffer)
329  {
330  NxLibCommand(cmdDiscardPatterns, serial).execute();
331  }
332 
333  NxLibCommand collectPattern(cmdCollectPattern, serial);
334  collectPattern.parameters()[itmCameras] = serial;
335  collectPattern.parameters()[itmDecodeData] = true;
336  try
337  {
338  collectPattern.execute();
339  }
340  catch (NxLibException& e)
341  {
342  if (e.getErrorCode() == NxLibExecutionFailed)
343  {
344  if (collectPattern.result()[itmErrorSymbol] == errPatternNotFound ||
345  collectPattern.result()[itmErrorSymbol] == errPatternNotDecodable)
346  {
347  return {};
348  }
349  }
350  throw;
351  }
352 
353  std::vector<MonoCalibrationPattern> result;
354 
355  for (int i = 0; i < collectPattern.result()[itmPatterns][0][serial].count(); i++)
356  {
357  result.emplace_back(collectPattern.result()[itmPatterns][0][serial][i][itmPattern]);
358  }
359 
360  // Extract the pattern's image points from the result.
361  NxLibItem pattern = collectPattern.result()[itmPatterns][0][serial];
362 
363  for (size_t i = 0; i < result.size(); i++)
364  {
365  for (int j = 0; j < pattern[i][itmPoints].count(); j++)
366  {
367  NxLibItem pointNode = pattern[i][itmPoints][j];
368 
369  ensenso_camera_msgs::ImagePoint point;
370  point.x = pointNode[0].asDouble();
371  point.y = pointNode[1].asDouble();
372  result[i].points.push_back(point);
373  }
374  }
375 
376  return result;
377 }
378 
379 geometry_msgs::TransformStamped MonoCamera::estimatePatternPose(ros::Time imageTimestamp,
380  std::string const& targetFrame,
381  bool latestPatternOnly) const
382 {
383  updateGlobalLink(imageTimestamp, targetFrame);
384 
385  NxLibCommand estimatePatternPose(cmdEstimatePatternPose, serial);
386  estimatePatternPose.parameters()[itmType] = itmMonocular;
387  if (latestPatternOnly)
388  {
389  estimatePatternPose.parameters()[itmAverage] = false;
390 
391  int patternCount = NxLibItem()[itmParameters][itmPatternCount].asInt();
392  estimatePatternPose.parameters()[itmFilter][itmOr][0][itmAnd][0][itmType] = valIndex;
393  estimatePatternPose.parameters()[itmFilter][itmOr][0][itmAnd][0][itmValue] = patternCount - 1;
394  }
395  else
396  {
397  estimatePatternPose.parameters()[itmAverage] = true;
398  }
399  estimatePatternPose.execute();
400 
401  ROS_ASSERT(estimatePatternPose.result()[itmPatterns].count() == 1);
402 
403  return poseFromNxLib(estimatePatternPose.result()[itmPatterns][0][itmPatternPose], cameraFrame, targetFrame);
404 }
405 
406 std::vector<geometry_msgs::TransformStamped> MonoCamera::estimatePatternPoses(ros::Time imageTimestamp,
407  std::string const& targetFrame) const
408 {
409  updateGlobalLink(imageTimestamp, targetFrame);
410 
411  NxLibCommand estimatePatternPose(cmdEstimatePatternPose, serial);
412  estimatePatternPose.parameters()[itmAverage] = false;
413  estimatePatternPose.parameters()[itmType] = itmMonocular;
414  estimatePatternPose.parameters()[itmFilter][itmCameras] = serial;
415 
416  estimatePatternPose.execute();
417 
418  int numberOfPatterns = estimatePatternPose.result()[itmPatterns].count();
419 
420  std::vector<geometry_msgs::TransformStamped> result;
421  result.reserve(numberOfPatterns);
422 
423  for (int i = 0; i < numberOfPatterns; i++)
424  {
425  result.push_back(
426  poseFromNxLib(estimatePatternPose.result()[itmPatterns][i][itmPatternPose], targetFrame, cameraFrame));
427  }
428 
429  return result;
430 }
void fillDistortionParamsFromNxLib(NxLibItem const &distortionItem, sensor_msgs::CameraInfoPtr const &info)
void publish(const sensor_msgs::Image &image, const sensor_msgs::CameraInfo &info) const
std::string targetFrame
Definition: camera.h:201
void onRequestData(ensenso_camera_msgs::RequestDataMonoGoalConstPtr const &goal)
ros::Time timestampFromNxLibNode(NxLibItem const &node)
std::unique_ptr< LocatePatternMonoServer > locatePatternServer
Definition: mono_camera.h:18
MonoCamera(ros::NodeHandle nh, std::string serial, std::string fileCameraPath, bool fixed, std::string cameraFrame, std::string targetFrame, std::string linkFrame)
Definition: mono_camera.cpp:6
ros::NodeHandle nh
Definition: camera.h:203
void updateGlobalLink(ros::Time time=ros::Time::now(), std::string frame="", bool useCachedTransformation=false) const
Definition: camera.cpp:259
ros::Time capture() const override
Definition: mono_camera.cpp:24
void fillCameraInfoFromNxLib(sensor_msgs::CameraInfoPtr const &info, bool rectified=false)
Definition: mono_camera.cpp:64
sensor_msgs::CameraInfoPtr rectifiedCameraInfo
Definition: mono_camera.h:15
image_transport::CameraPublisher rectifiedImagePublisher
Definition: mono_camera.h:21
virtual bool open()
Definition: camera.cpp:427
std::string cameraFrame
Definition: camera.h:199
#define ROS_WARN(...)
std::unique_ptr< SetParameterServer > setParameterServer
Definition: camera.h:217
std::string serial
Definition: camera.h:190
void onSetParameter(ensenso_camera_msgs::SetParameterGoalConstPtr const &goal) override
std::vector< geometry_msgs::TransformStamped > estimatePatternPoses(ros::Time imageTimestamp=ros::Time::now(), std::string const &targetFrame="") const override
std::vector< MonoCalibrationPattern > collectPattern(bool clearBuffer=false) const
bool open() override
Definition: mono_camera.cpp:49
void onLocatePattern(ensenso_camera_msgs::LocatePatternMonoGoalConstPtr const &goal)
geometry_msgs::TransformStamped estimatePatternPose(ros::Time imageTimestamp=ros::Time::now(), std::string const &targetFrame="", bool latestPatternOnly=false) const override
geometry_msgs::TransformStamped transformFromPose(geometry_msgs::PoseStamped const &pose, std::string const &childFrame)
std::unique_ptr< RequestDataMonoServer > requestDataServer
Definition: mono_camera.h:17
bool isFileCamera
Definition: camera.h:182
NxLibItem cameraNode
Definition: camera.h:191
virtual void startServers() const
Definition: camera.cpp:48
void startServers() const override
Definition: mono_camera.cpp:96
void loadParameterSet(std::string name)
Definition: camera.cpp:525
geometry_msgs::PoseStamped stampedPoseFromTransform(geometry_msgs::TransformStamped const &transform)
image_transport::CameraPublisher rawImagePublisher
Definition: mono_camera.h:20
tf2::Transform poseFromNxLib(NxLibItem const &node)
static Time now()
#define START_NXLIB_ACTION(ACTION_NAME, ACTION_SERVER)
Definition: camera.h:91
#define PREEMPT_ACTION_IF_REQUESTED
Definition: camera.h:134
sensor_msgs::CameraInfoPtr cameraInfo
Definition: mono_camera.h:14
void updateCameraInfo() override
Definition: mono_camera.cpp:58
std::vector< sensor_msgs::ImagePtr > imagesFromNxLibNode(NxLibItem const &node, std::string const &frame)
void saveParameterSet(std::string name)
Definition: camera.cpp:512
void fillBasicCameraInfoFromNxLib(sensor_msgs::CameraInfoPtr const &info) const
Definition: camera.cpp:242
#define ROS_ASSERT(cond)
Definition: camera.h:179
virtual ensenso_camera_msgs::ParameterPtr readParameter(std::string const &key) const
Definition: camera.cpp:355
#define FINISH_NXLIB_ACTION(ACTION_NAME)
Definition: camera.h:102
bool loadSettings(std::string const &jsonFile, bool saveAsDefaultParameters=false)
Definition: camera.cpp:57
#define ROS_DEBUG(...)
std::unique_ptr< tf2_ros::TransformBroadcaster > transformBroadcaster
Definition: camera.h:212


ensenso_camera
Author(s): Ensenso
autogenerated on Thu May 6 2021 02:50:06