velo2cam_calibration.cpp
Go to the documentation of this file.
1 /*
2  velo2cam_calibration - Automatic calibration algorithm for extrinsic parameters of a stereo camera and a velodyne
3  Copyright (C) 2017-2018 Jorge Beltran, Carlos Guindel
4 
5  This file is part of velo2cam_calibration.
6 
7  velo2cam_calibration is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 2 of the License, or
10  (at your option) any later version.
11 
12  velo2cam_calibration is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with velo2cam_calibration. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 /*
22  velo2cam_calibration: Perform the registration step
23 */
24 
25 #define PCL_NO_PRECOMPILE
26 
27 #include "velo2cam_calibration/ClusterCentroids.h"
28 
29 #include <vector>
30 #include <ros/ros.h>
31 #include <ros/package.h>
32 #include <sensor_msgs/PointCloud2.h>
33 #include <pcl/point_cloud.h>
35 #include <pcl/common/transforms.h>
36 #include <pcl/registration/icp.h>
37 
38 #include <ctime>
39 #include "tinyxml.h"
40 
41 #ifdef TF2
42 #include <tf2_ros/buffer.h>
46 #include <tf2_sensor_msgs/tf2_sensor_msgs.h>
47 #include <geometry_msgs/TransformStamped.h>
48 #else
49 #include <tf/tf.h>
51 #include <tf/transform_listener.h>
53 #include <pcl_ros/transforms.h>
54 #endif
55 
56 
57 #include "velo2cam_utils.h"
58 
59 using namespace std;
60 using namespace sensor_msgs;
61 
65 int nFrames;
67 
68 pcl::PointCloud<pcl::PointXYZ>::Ptr laser_cloud, camera_cloud;
69 pcl::PointCloud<pcl::PointXYZI>::Ptr ilaser_cloud, icamera_cloud;
70 std::vector<pcl::PointXYZ> lv(4), cv(4);
71 
73 
74 typedef Eigen::Matrix<double, 12, 12> Matrix12d;
75 typedef Eigen::Matrix<double, 12, 1> Vector12d;
76 
78 
79 std::vector< std::tuple<int,int,pcl::PointCloud<pcl::PointXYZ>, std::vector<pcl::PointXYZ> > > laser_buffer;
80 std::vector< std::tuple<int,int,pcl::PointCloud<pcl::PointXYZ>, std::vector<pcl::PointXYZ> > > cam_buffer;
81 
85 
87 
88 std::ofstream savefile;
89 
90 const std::string currentDateTime() {
91  time_t now = time(0);
92  struct tm tstruct;
93  char buf[80];
94  tstruct = *localtime(&now);
95  // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
96  // for more information about date/time format
97  strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
98 
99  return buf;
100 }
101 
102 void calibrateExtrinsics(int seek_iter = -1){
103  // ROS_INFO("Hey man, keep calm... I'm calibrating your sensors...");
104 
105  std::vector<pcl::PointXYZ> local_lv, local_cv;
106  pcl::PointCloud<pcl::PointXYZ>::Ptr local_laser_cloud, local_camera_cloud;
107  pcl::PointCloud<pcl::PointXYZ> local_l_cloud, local_c_cloud;
108 
109  int used_stereo, used_laser;
110 
111  if (seek_iter>0){
112  if(DEBUG) ROS_INFO("Seeking %d iterations", seek_iter);
113  if(DEBUG) ROS_INFO("Last cam: %d, last laser: %d", std::get<0>(cam_buffer.back()),std::get<0>(laser_buffer.back()));
114  auto it = std::find_if(cam_buffer.begin(), cam_buffer.end(), [&seek_iter](const std::tuple<int,int,pcl::PointCloud<pcl::PointXYZ>, std::vector<pcl::PointXYZ> >& e) {return std::get<0>(e) == seek_iter;});
115  if (it == cam_buffer.end()) {
116  ROS_WARN("Could not sync cam");
117  return;
118  }
119 
120  auto it2 = std::find_if(laser_buffer.begin(), laser_buffer.end(), [&seek_iter](const std::tuple<int,int,pcl::PointCloud<pcl::PointXYZ>, std::vector<pcl::PointXYZ> >& e) {return std::get<0>(e) == seek_iter;});
121  if (it2 == laser_buffer.end()) {
122  ROS_WARN("Could not sync laser");
123  return;
124  }
125 
126  used_stereo = std::get<1>(*it);
127  used_laser = std::get<1>(*it2);
128 
129  local_cv = std::get<3>(*it);
130  local_c_cloud = std::get<2>(*it);
131  local_camera_cloud = local_c_cloud.makeShared();
132 
133  local_lv = std::get<3>(*it2);
134  local_l_cloud = std::get<2>(*it2);
135  local_laser_cloud = local_l_cloud.makeShared();
136  ROS_INFO("Synchronizing cluster centroids");
137  }else{
138  local_lv = lv;
139  local_cv = cv;
140  local_laser_cloud = laser_cloud;
141  local_camera_cloud = camera_cloud;
142  }
143 
144  sensor_msgs::PointCloud2 ros_cloud;
145  pcl::toROSMsg(*local_camera_cloud, ros_cloud);
146  ros_cloud.header.frame_id = "stereo";
147  clusters_c.publish(ros_cloud);
148 
149  pcl::toROSMsg(*local_laser_cloud, ros_cloud);
150  ros_cloud.header.frame_id = "velodyne";
151  clusters_l.publish(ros_cloud);
152 
153  Vector12d las_12;
154  las_12 << local_lv[0].x,
155  local_lv[0].y,
156  local_lv[0].z,
157  local_lv[1].x,
158  local_lv[1].y,
159  local_lv[1].z,
160  local_lv[2].x,
161  local_lv[2].y,
162  local_lv[2].z,
163  local_lv[3].x,
164  local_lv[3].y,
165  local_lv[3].z;
166 
167  Vector12d cam_12;
168  cam_12 << local_cv[0].x,
169  local_cv[0].y,
170  local_cv[0].z,
171  local_cv[1].x,
172  local_cv[1].y,
173  local_cv[1].z,
174  local_cv[2].x,
175  local_cv[2].y,
176  local_cv[2].z,
177  local_cv[3].x,
178  local_cv[3].y,
179  local_cv[3].z;
180 
181  Vector12d diff_12;
182  diff_12 = las_12-cam_12;
183 
184  Eigen::MatrixXd matrix_transl(12,3);
185  matrix_transl << 1, 0, 0, 0, 1, 0, 0, 0, 1,
186  1, 0, 0, 0, 1, 0, 0, 0, 1,
187  1, 0, 0, 0, 1, 0, 0, 0, 1,
188  1, 0, 0, 0, 1, 0, 0, 0, 1;
189 
190  Eigen::Vector3d x;
191  x = matrix_transl.colPivHouseholderQr().solve(diff_12);
192 
193  // cout << "The least-squares solution is:\n"
194  // << x << endl;
195 
196  Eigen::Matrix4f Tm;
197  Tm << 1, 0, 0, x[0],
198  0, 1, 0, x[1],
199  0, 0, 1, x[2],
200  0, 0, 0, 1;
201 
202  if(DEBUG) ROS_INFO("Step 1: Translation");
203  if(DEBUG) cout << Tm << endl;
204 
205  pcl::PointCloud<pcl::PointXYZ>::Ptr translated_pc (new pcl::PointCloud<pcl::PointXYZ> ());
206  pcl::transformPointCloud(*local_camera_cloud, *translated_pc, Tm);
207 
208  pcl::toROSMsg(*translated_pc, ros_cloud);
209  ros_cloud.header.frame_id = "velodyne";
210  t_pub.publish(ros_cloud);
211 
212  pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
213  icp.setInputSource(translated_pc);
214  icp.setInputTarget(local_laser_cloud);
215  pcl::PointCloud<pcl::PointXYZ> Final;
216  icp.align(Final);
217  icp.setMaxCorrespondenceDistance(0.2);
218  icp.setMaximumIterations(1000);
219  if (icp.hasConverged()){
220  if(DEBUG) ROS_INFO("ICP Converged. Score: %lf", icp.getFitnessScore());
221  }else{
222  ROS_WARN("ICP failed to converge");
223  return;
224  }
225  if(DEBUG) ROS_INFO("Step 2. ICP Transformation:");
226  if(DEBUG) cout << icp.getFinalTransformation() << std::endl;
227 
228  Eigen::Matrix4f transformation = icp.getFinalTransformation ();
229  Eigen::Matrix4f final_trans = transformation * Tm;
230 
231  tf::Matrix3x3 tf3d;
232  tf3d.setValue(final_trans(0,0), final_trans(0,1), final_trans(0,2),
233  final_trans(1,0), final_trans(1,1), final_trans(1,2),
234  final_trans(2,0), final_trans(2,1), final_trans(2,2));
235 
236  if(DEBUG) ROS_INFO("Final Transformation");
237  if(DEBUG) cout << final_trans << endl;
238 
239  tf::Quaternion tfqt;
240  tf3d.getRotation(tfqt);
241 
242  #ifdef TF2
243 
245  geometry_msgs::TransformStamped transformStamped;
246 
247  transformStamped.header.stamp = ros::Time::now();
248  transformStamped.header.frame_id = "velodyne";
249  transformStamped.child_frame_id = "stereo";
250  transformStamped.transform.translation.x = final_trans(0,3);
251  transformStamped.transform.translation.y = final_trans(1,3);
252  transformStamped.transform.translation.z = final_trans(2,3);
253  transformStamped.transform.rotation.x = tfqt.x();
254  transformStamped.transform.rotation.y = tfqt.y();
255  transformStamped.transform.rotation.z = tfqt.z();
256  transformStamped.transform.rotation.w = tfqt.w();
257 
258  br.sendTransform(transformStamped);
259 
260  #else
261 
262  tf::Vector3 origin;
263  origin.setValue(final_trans(0,3),final_trans(1,3),final_trans(2,3));
264 
265  transf.setOrigin(origin);
266  transf.setRotation(tfqt);
267 
268  #endif
269 
270  static tf::TransformBroadcaster br;
271  tf_velodyne_camera = tf::StampedTransform(transf, ros::Time::now(), "velodyne", "stereo");
272  if (publish_tf_) br.sendTransform(tf_velodyne_camera);
273 
274  tf::Transform inverse = tf_velodyne_camera.inverse();
275  double roll, pitch, yaw;
276  double xt = inverse.getOrigin().getX(), yt = inverse.getOrigin().getY(), zt = inverse.getOrigin().getZ();
277  inverse.getBasis().getRPY(roll, pitch, yaw);
278 
279  if (save_to_file_){
280  savefile << seek_iter << ", " << xt << ", " << yt << ", " << zt << ", " << roll << ", " << pitch << ", " << yaw << ", " << used_laser << ", " << used_stereo << endl;
281  }
282 
283  ROS_INFO("[V2C] Calibration result:");
284  ROS_INFO("x=%.4f y=%.4f z=%.4f",xt,yt,zt);
285  ROS_INFO("roll=%.4f, pitch=%.4f, yaw=%.4f",roll,pitch,yaw);
286  // ROS_INFO("Translation matrix");
287  // ROS_INFO("%.4f, %.4f, %.4f",inverse.getBasis()[0][0],inverse.getBasis()[0][1],inverse.getBasis()[0][2]);
288  // ROS_INFO("%.4f, %.4f, %.4f",inverse.getBasis()[1][0],inverse.getBasis()[1][1],inverse.getBasis()[1][2]);
289  // ROS_INFO("%.4f, %.4f, %.4f",inverse.getBasis()[2][0],inverse.getBasis()[2][1],inverse.getBasis()[2][2]);
290 
291  laserReceived = false;
292  cameraReceived = false;
293 }
294 
295 void laser_callback(const velo2cam_calibration::ClusterCentroids::ConstPtr velo_centroids){
296  // ROS_INFO("Velodyne pattern ready!");
297  laserReceived = true;
298 
299  fromROSMsg(velo_centroids->cloud, *laser_cloud);
300 
303 
304  laser_buffer.push_back(std::tuple<int,int,pcl::PointCloud<pcl::PointXYZ>, std::vector<pcl::PointXYZ> >(velo_centroids->total_iterations, velo_centroids->cluster_iterations, *laser_cloud,lv));
305  laser_count = velo_centroids->total_iterations;
306 
307  if(DEBUG) ROS_INFO("[V2C] LASER");
308 
309  for(vector<pcl::PointXYZ>::iterator it=lv.begin(); it<lv.end(); ++it){
310  if (DEBUG) cout << "l" << it - lv.begin() << "="<< "[" << (*it).x << " " << (*it).y << " " << (*it).z << "]" << endl;
311  }
312 
313  if (sync_iterations){
314  if(cam_count >= laser_count){
316  return;
317  }else{
318  if (tf_velodyne_camera.frame_id_ != ""){
319  static tf::TransformBroadcaster br;
320  tf_velodyne_camera.stamp_ = ros::Time::now();
321  if (publish_tf_) br.sendTransform(tf_velodyne_camera);
322  return;
323  }
324  }
325  }
326 
329  }else{
330  static tf::TransformBroadcaster br;
331  tf_velodyne_camera.stamp_ = ros::Time::now();
332  if (publish_tf_) br.sendTransform(tf_velodyne_camera);
333  }
334 }
335 
336 void stereo_callback(velo2cam_calibration::ClusterCentroids::ConstPtr image_centroids){
337  // if(DEBUG) ROS_INFO("Camera pattern ready!");
338 
339 #ifdef TF2
340 
341  //TODO: adapt to ClusterCentroids
342 
343  PointCloud2 xy_image_cloud;
344 
345  tf2_ros::Buffer tfBuffer;
346  tf2_ros::TransformListener tfListener(tfBuffer);
347  geometry_msgs::TransformStamped transformStamped;
348  try{
349  transformStamped = tfBuffer.lookupTransform("stereo", "stereo_camera",
350  ros::Time(0), ros::Duration(20));
351  }
352  catch (tf2::TransformException &ex) {
353  ROS_WARN("%s",ex.what());
354  ros::Duration(1.0).sleep();
355  return;
356  }
357  tf2::doTransform (*image_cloud, xy_image_cloud, transformStamped);
358  fromROSMsg(xy_image_cloud, *camera_cloud);
359 
360 #else
361 
362  pcl::PointCloud<pcl::PointXYZ>::Ptr xy_camera_cloud (new pcl::PointCloud<pcl::PointXYZ> ());
363 
364  fromROSMsg(image_centroids->cloud, *xy_camera_cloud);
365 
366  tf::TransformListener listener;
367  tf::StampedTransform transform;
368  try{
369  listener.waitForTransform("stereo", "stereo_camera", ros::Time(0), ros::Duration(20.0));
370  listener.lookupTransform ("stereo", "stereo_camera", ros::Time(0), transform);
371  }catch (tf::TransformException& ex) {
372  ROS_WARN("TF exception:\n%s", ex.what());
373  return;
374  }
375 
376  tf::Transform inverse = transform.inverse();
377  double roll, pitch, yaw;
378  inverse.getBasis().getRPY(roll, pitch, yaw);
379 
380  pcl_ros::transformPointCloud (*xy_camera_cloud, *camera_cloud, transform);
381 
382 #endif
383 
384  cameraReceived = true;
385 
388 
389  cam_buffer.push_back(std::tuple<int, int,pcl::PointCloud<pcl::PointXYZ>, std::vector<pcl::PointXYZ> >(image_centroids->total_iterations,image_centroids->cluster_iterations,*camera_cloud,cv));
390  cam_count = image_centroids->total_iterations;
391 
392  if(DEBUG) ROS_INFO("[V2C] CAMERA");
393 
394  for(vector<pcl::PointXYZ>::iterator it=cv.begin(); it<cv.end(); ++it){
395  if (DEBUG) cout << "c" << it - cv.begin() << "="<< "[" << (*it).x << " " << (*it).y << " " << (*it).z << "]"<<endl;
396  }
397 
398  if (sync_iterations){
399  if(laser_count >= cam_count){
401  return;
402  }else{
403  if (tf_velodyne_camera.frame_id_ != ""){
404  static tf::TransformBroadcaster br;
405  tf_velodyne_camera.stamp_ = ros::Time::now();
406  if (publish_tf_) br.sendTransform(tf_velodyne_camera);
407  return;
408  }
409  }
410  }
411 
413  if(DEBUG) ROS_INFO("[V2C] Calibrating...");
415  }else{
416  static tf::TransformBroadcaster br;
417  tf_velodyne_camera.stamp_ = ros::Time::now();
418  if (publish_tf_) br.sendTransform(tf_velodyne_camera);
419  }
420 }
421 
422 int main(int argc, char **argv){
423  ros::init(argc, argv, "velo2cam_calibration");
424  ros::NodeHandle nh_("~"); // LOCAL
425 
426  nh_.param<bool>("sync_iterations", sync_iterations, false);
427  nh_.param<bool>("save_to_file", save_to_file_, false);
428  nh_.param<bool>("publish_tf", publish_tf_, true);
429 
430  static tf::TransformBroadcaster br;
431  tf_velodyne_camera = tf::StampedTransform(tf::Transform::getIdentity(), ros::Time::now(), "velodyne", "stereo");
432  if (publish_tf_) br.sendTransform(tf_velodyne_camera);
433 
434  laserReceived = false;
435  laser_cloud = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>);
436  ilaser_cloud = pcl::PointCloud<pcl::PointXYZI>::Ptr(new pcl::PointCloud<pcl::PointXYZI>);
437  cameraReceived = false;
438  camera_cloud = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>);
439  icamera_cloud = pcl::PointCloud<pcl::PointXYZI>::Ptr(new pcl::PointCloud<pcl::PointXYZI>);
440 
441  ros::Subscriber laser_sub = nh_.subscribe<velo2cam_calibration::ClusterCentroids>("cloud1", 1, laser_callback);
442  ros::Subscriber stereo_sub = nh_.subscribe<velo2cam_calibration::ClusterCentroids>("cloud2", 1, stereo_callback);
443 
444  t_pub = nh_.advertise<sensor_msgs::PointCloud2>("translated_cloud", 1);
445  clusters_c = nh_.advertise<sensor_msgs::PointCloud2>("clusters_camera", 1);
446  clusters_l = nh_.advertise<sensor_msgs::PointCloud2>("clusters_laser", 1);
447 
448  if (save_to_file_){
449  ostringstream os;
450  os << getenv("HOME") << "/results_" << currentDateTime() << ".csv" ;
451  if (save_to_file_){
452  if(DEBUG) ROS_INFO("Opening %s", os.str().c_str());
453  savefile.open (os.str().c_str());
454  savefile << "it, x, y, z, r, p, y, used_l, used_c" << endl;
455  }
456  }
457 
458  ros::Rate loop_rate(30);
459  while(ros::ok()){
460  ros::spinOnce();
461  }
462 
463  if (save_to_file_) savefile.close();
464 
465  // Save calibration params to launch file for testing
466 
467  // Get time
468  time_t rawtime;
469  struct tm * timeinfo;
470  char buffer[80];
471 
472  time (&rawtime);
473  timeinfo = localtime(&rawtime);
474 
475  strftime(buffer,80,"%Y-%m-%d-%H-%M-%S", timeinfo);
476  std::string str(buffer);
477 
478  // Get tf data
479  tf::Transform inverse = tf_velodyne_camera.inverse();
480  double roll, pitch, yaw;
481  double xt = inverse.getOrigin().getX(), yt = inverse.getOrigin().getY(), zt = inverse.getOrigin().getZ();
482  inverse.getBasis().getRPY(roll, pitch, yaw);
483 
484  ROS_INFO("Calibration finished succesfully...");
485  ROS_INFO("x=%.4f y=%.4f z=%.4f",xt,yt,zt);
486  ROS_INFO("roll=%.4f, pitch=%.4f, yaw=%.4f", roll, pitch, yaw);
487 
488  std::string path = ros::package::getPath("velo2cam_calibration");
489  string backuppath = path + "/launch/calibrated_tf_"+ str +".launch";
490  path = path + "/launch/calibrated_tf.launch";
491 
492  cout << endl << "Creating .launch file with calibrated TF in: "<< endl << path.c_str() << endl;
493  // Create .launch file with calibrated TF
494  TiXmlDocument doc;
495  TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "utf-8", "");
496  doc.LinkEndChild( decl );
497  TiXmlElement * root = new TiXmlElement( "launch" );
498  doc.LinkEndChild( root );
499 
500  TiXmlElement * arg = new TiXmlElement( "arg" );
501  arg->SetAttribute("name","stdout");
502  arg->SetAttribute("default","screen");
503  root->LinkEndChild( arg );
504 
505  string stereo_rotation = "0 0 0 -1.57079632679 0 -1.57079632679 stereo stereo_camera 10";
506 
507  TiXmlElement * stereo_rotation_node = new TiXmlElement( "node" );
508  stereo_rotation_node->SetAttribute("pkg","tf");
509  stereo_rotation_node->SetAttribute("type","static_transform_publisher");
510  stereo_rotation_node->SetAttribute("name","stereo_ros_tf");
511  stereo_rotation_node->SetAttribute("args", stereo_rotation);
512  root->LinkEndChild( stereo_rotation_node );
513 
514  std::ostringstream sstream;
515  sstream << xt << " " << yt << " " << zt << " " << yaw << " " <<pitch<< " " << roll << " stereo velodyne 100";
516  string tf_args = sstream.str();
517  cout << tf_args << endl;
518 
519  TiXmlElement * node = new TiXmlElement( "node" );
520  node->SetAttribute("pkg","tf");
521  node->SetAttribute("type","static_transform_publisher");
522  node->SetAttribute("name","l2c_tf");
523  node->SetAttribute("args", tf_args);
524  root->LinkEndChild( node );
525 
526  // Save XML file and copy
527  doc.SaveFile(path);
528  doc.SaveFile(backuppath);
529 
530  if(DEBUG) cout << "Calibration process finished." << endl;
531 
532  return 0;
533 }
std::vector< std::tuple< int, int, pcl::PointCloud< pcl::PointXYZ >, std::vector< pcl::PointXYZ > > > cam_buffer
int nFrames
TFSIMD_FORCE_INLINE void setRotation(const Quaternion &q)
ros::Publisher clusters_l
pcl::PointCloud< pcl::PointXYZ >::Ptr camera_cloud
void publish(const boost::shared_ptr< M > &message) const
std::vector< std::tuple< int, int, pcl::PointCloud< pcl::PointXYZ >, std::vector< pcl::PointXYZ > > > laser_buffer
bool cameraReceived
void sortPatternCentersYZ(pcl::PointCloud< pcl::PointXYZ >::Ptr pc, vector< pcl::PointXYZ > &v)
tf::StampedTransform tf_velodyne_camera
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Publisher t_pub
TFSIMD_FORCE_INLINE Matrix3x3 & getBasis()
long int laser_count
bool sleep() const
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::ofstream savefile
ros::Publisher clusters_c
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
std::vector< pcl::PointXYZ > cv(4)
void setValue(const tfScalar &xx, const tfScalar &xy, const tfScalar &xz, const tfScalar &yx, const tfScalar &yy, const tfScalar &yz, const tfScalar &zx, const tfScalar &zy, const tfScalar &zz)
void doTransform(const T &data_in, T &data_out, const geometry_msgs::TransformStamped &transform)
bool sync_iterations
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
#define ROS_WARN(...)
bool publish_tf_
TFSIMD_FORCE_INLINE void setValue(const tfScalar &x, const tfScalar &y, const tfScalar &z)
void laser_callback(const velo2cam_calibration::ClusterCentroids::ConstPtr velo_centroids)
void getRotation(Quaternion &q) const
void calibrateExtrinsics(int seek_iter=-1)
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
bool save_to_file_
pcl::PointCloud< pcl::PointXYZ >::Ptr laser_cloud
#define DEBUG
long int cam_count
Eigen::Matrix< double, 12, 12 > Matrix12d
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
TFSIMD_FORCE_INLINE Quaternion inverse(const Quaternion &q)
ROSCPP_DECL bool ok()
void sendTransform(const StampedTransform &transform)
const std::string currentDateTime()
TFSIMD_FORCE_INLINE const tfScalar & x() const
void stereo_callback(velo2cam_calibration::ClusterCentroids::ConstPtr image_centroids)
Transform inverse() const
std::vector< pcl::PointXYZ > lv(4)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
pcl::PointCloud< pcl::PointXYZI >::Ptr icamera_cloud
void sendTransform(const geometry_msgs::TransformStamped &transform)
bool laserReceived
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
ROSLIB_DECL std::string getPath(const std::string &package_name)
pcl::PointCloud< pcl::PointXYZI >::Ptr ilaser_cloud
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const tf::Transform &transform)
void colourCenters(const pcl::PointCloud< pcl::PointXYZ >::Ptr pc, pcl::PointCloud< pcl::PointXYZI >::Ptr coloured)
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
TFSIMD_FORCE_INLINE const tfScalar & getX() const
static Time now()
static const Transform & getIdentity()
ros::Publisher aux2_pub
int main(int argc, char **argv)
ROSCPP_DECL void spinOnce()
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
tf::Transform transf
std::string frame_id_
ros::Publisher aux_pub
Eigen::Matrix< double, 12, 1 > Vector12d


velo2cam_calibration
Author(s): Jorge Beltran , Carlos Guindel
autogenerated on Thu Feb 28 2019 03:24:25