raw_snapshot.cpp
Go to the documentation of this file.
1 
34 #include <functional>
35 
36 #include <ros/ros.h>
37 #include <ros/topic.h>
38 #include <rosbag/bag.h>
39 #include <multisense_ros/DeviceInfo.h>
40 #include <multisense_ros/RawCamConfig.h>
41 #include <multisense_ros/RawCamCal.h>
42 #include <multisense_ros/RawCamData.h>
43 #include <multisense_ros/RawLidarData.h>
44 #include <multisense_ros/RawLidarCal.h>
45 #include <multisense_lib/MultiSenseTypes.hh>
46 #include <stdio.h>
47 #include <ros/callback_queue.h>
48 
49 #include <dynamic_reconfigure/DoubleParameter.h>
50 #include <dynamic_reconfigure/StrParameter.h>
51 #include <dynamic_reconfigure/Reconfigure.h>
52 #include <dynamic_reconfigure/Config.h>
53 
54 namespace { // anonymous
55 
56 #define TOPIC_DEVICE_INFO "/multisense/calibration/device_info"
57 #define TOPIC_RAW_CAM_CAL "/multisense/calibration/raw_cam_cal"
58 #define TOPIC_RAW_CAM_CONFIG "/multisense/calibration/raw_cam_config"
59 #define TOPIC_RAW_CAM_DATA "/multisense/calibration/raw_cam_data"
60 #define TOPIC_RAW_LIDAR "/multisense/calibration/raw_lidar_data"
61 #define TOPIC_RAW_LIDAR_CAL "/multisense/calibration/raw_lidar_cal"
62 
63 //
64 // Helper class for getting a full rotation of laser scan data
65 
66 class LaserHelper {
67 public:
68 
69  LaserHelper() : motion_started_(false) {}
70 
71  void callback(const multisense_ros::RawLidarData::ConstPtr& msg)
72  {
73  //
74  // Keep around one scan until the head starts spinning, then
75  // start collecting
76 
77  if (motion_started_ || 0 == scans_.size())
78  scans_.push_back(msg);
79 
80  if (!motion_started_) {
81  std::list<multisense_ros::RawLidarData::ConstPtr>::const_iterator it = scans_.begin();
82 
83  if (msg->angle_start != (*it)->angle_start) {
84  motion_started_ = true;
85  scans_.clear();
86  scans_.push_back(msg);
87  }
88  }
89  }
90 
91  //
92  // Check if we have received an entire rotation of laser data
93  // return True if we have a full rotation of data data
94 
95  bool done() const
96  {
97  std::list<multisense_ros::RawLidarData::ConstPtr>::const_iterator it;
98 
99  //
100  // If we have no scans, then we're definitely not done
101 
102  it = scans_.begin();
103  if (scans_.end() == it)
104  return false;
105 
106  //
107  // Calculate the total angle swept through all the scans, accounting for wrap-around
108 
109  double previous_start = (*it)->angle_start / 1000000.0;
110  double total_swept = 0.0;
111 
112  for (it = scans_.begin(); it != scans_.end(); it++) {
113 
114  double current_start = (*it)->angle_start / 1000000.0;
115  double current_swept = current_start - previous_start;
116 
117  //
118  // Unwrap the swept angle
119 
120  while(current_swept > M_PI)
121  current_swept -= 2*M_PI;
122  while(current_swept < -M_PI)
123  current_swept += 2*M_PI;
124 
125  //
126  // Accumulate
127 
128  total_swept += current_swept;
129 
130  //
131  // Save the previous start angle
132 
133  previous_start = current_start;
134  }
135 
136  return ( fabs(total_swept) > 2.0 * M_PI);
137  }
138 
139  //
140  // Gets an entire rotation of laser data. This method constructs it own subscriber
141  // and callback queue, and services them itself.
142  // It will return list of the captured messages for this single rotation
143 
144  bool getRotation(std::list<multisense_ros::RawLidarData::ConstPtr>& scan_collection)
145  {
146  scans_.clear();
147  ros::NodeHandle nh;
148  nh.setCallbackQueue(&queue_);
149 
150  ros::Subscriber sub_ = nh.subscribe<multisense_ros::RawLidarData>(TOPIC_RAW_LIDAR, 5,
151  std::bind(&LaserHelper::callback, this, std::placeholders::_1));
152 
153  ros::Time start = ros::Time::now();
154 
155  //
156  // Service our own callback queue
157 
158  while(1) {
159 
160  queue_.callOne(ros::WallDuration(1.0));
161 
162  if (done()) {
163  scan_collection = scans_;
164  return true;
165  }
166 
167  if ((ros::Time::now().toSec() - start.toSec()) >= SCAN_COLLECT_TIMEOUT)
168  return false;
169  }
170  }
171 
172 private:
173 
174 #if __cplusplus >= 201103
175  static constexpr double SCAN_COLLECT_TIMEOUT = 20.0; // seconds
176 #else
177  static const double SCAN_COLLECT_TIMEOUT = 20.0; // seconds
178 #endif
179 
180  bool motion_started_;
181  ros::CallbackQueue queue_;
182  std::list<multisense_ros::RawLidarData::ConstPtr> scans_;
183 };
184 
185 void setConf(const dynamic_reconfigure::Config& conf)
186 {
187  dynamic_reconfigure::ReconfigureRequest srv_req;
188  dynamic_reconfigure::ReconfigureResponse srv_resp;
189 
190  srv_req.config = conf;
191 
192  ros::service::call("/multisense/set_parameters", srv_req, srv_resp);
193 }
194 
195 void setMotorSpeed(double radPerSec)
196 {
197  dynamic_reconfigure::DoubleParameter double_param;
198  dynamic_reconfigure::Config conf;
199 
200  double_param.name = "motor_speed";
201  double_param.value = radPerSec;
202  conf.doubles.push_back(double_param);
203 
204  setConf(conf);
205 }
206 
207 void setResolution(const std::string& res)
208 {
209  dynamic_reconfigure::StrParameter str_param;
210  dynamic_reconfigure::Config conf;
211 
212  str_param.name = "resolution";
213  str_param.value = res;
214  conf.strs.push_back(str_param);
215 
216  setConf(conf);
217 }
218 
219 } // anonymous
220 
221 int main(int argc,
222  char** argvPP)
223 {
224  ros::init(argc, argvPP, "raw_snapshot");
225  ros::NodeHandle nh;
226 
227  if (argc != 2 ||
228  std::string(argvPP[1]) == "--help" ||
229  std::string(argvPP[1]) == "-h") {
230 
231  printf("Usage: %s <out_bag_filename>\n", argvPP[0]);
232  return -1;
233  }
234 
235  std::string outfile(argvPP[1]);
236 
237  printf("Capturing device information... "); fflush(stdout);
238  multisense_ros::DeviceInfo::ConstPtr device_info = ros::topic::waitForMessage<multisense_ros::DeviceInfo>(TOPIC_DEVICE_INFO, nh);
239  if (!device_info) {
240  printf(" Error capturing DeviceInfo. Exiting\n");
241  return -1;
242  }
243  printf(" Success\n");
244 
245  switch(device_info->imagerType) {
248  printf("Imager type is CMV2000; setting resolution to 1024x544x128... ");
249  setResolution("1024x544x128");
250  break;
253  printf("Imager type is CMV4000; setting resolution to 1024x1024x128... ");
254  setResolution("1024x1024x128");
255  break;
256  default:
257  printf("Imager type is not recognized; not setting resolution... ");
258  printf(" Error setting imager resolution. Exiting\n");
259  return -1;
260  break;
261  }
262  ros::Duration(1.0).sleep();
263 
264  printf("Capturing lidar calibration... ");
265  multisense_ros::RawLidarCal::ConstPtr lidar_cal = ros::topic::waitForMessage<multisense_ros::RawLidarCal>(TOPIC_RAW_LIDAR_CAL, nh);
266  if (!lidar_cal) {
267  printf(" Error capturing RawLidarCal. Exiting\n");
268  return -1;
269  }
270  printf(" Success\n");
271 
272  printf("Capturing camera calibration... "); fflush(stdout);
273  multisense_ros::RawCamCal::ConstPtr cam_cal = ros::topic::waitForMessage<multisense_ros::RawCamCal>(TOPIC_RAW_CAM_CAL, nh);
274  if (!cam_cal) {
275  printf(" Error capturing RawCamCal. Exiting\n");
276  return -1;
277  }
278  printf(" Success\n");
279 
280  printf("Capturing camera config... "); fflush(stdout);
281  multisense_ros::RawCamConfig::ConstPtr cam_config = ros::topic::waitForMessage<multisense_ros::RawCamConfig>(TOPIC_RAW_CAM_CONFIG, nh);
282  if (!cam_config) {
283  printf(" Error capturing RawCamConfig. Exiting\n");
284  return -1;
285  }
286  printf(" Success\n");
287 
288  printf("Capturing a single left-rectified/disparity image pair... "); fflush(stdout);
289  multisense_ros::RawCamData::ConstPtr cam_data = ros::topic::waitForMessage<multisense_ros::RawCamData>(TOPIC_RAW_CAM_DATA, nh);
290  if (!cam_data) {
291  printf(" Error capturing RawCamData. Exiting\n");
292  return -1;
293  }
294  printf(" Success\n");
295 
296  printf("Capturing a full rotation of lidar scans... "); fflush(stdout);
297 
298  setMotorSpeed(0.785);
299 
300  LaserHelper laser_helper;
301  std::list<multisense_ros::RawLidarData::ConstPtr> raw_lidar_data;
302 
303  if (false == laser_helper.getRotation(raw_lidar_data)) {
304  printf(" Error capturing RawLidarData...\n");
305  return -1;
306  }
307  printf(" Captured %zu lidar scans\n", raw_lidar_data.size());
308 
309  setMotorSpeed(0.0);
310 
311  //
312  // Save all of the data to a bag file
313 
314  printf("Saving data to file [%s]\n", outfile.c_str());
315  rosbag::Bag bag;
316  bag.open(outfile, rosbag::bagmode::Write);
317 
318  bag.write(TOPIC_DEVICE_INFO, ros::TIME_MIN, *device_info);
319  bag.write(TOPIC_RAW_LIDAR_CAL, ros::TIME_MIN, *lidar_cal);
320  bag.write(TOPIC_RAW_CAM_CAL, ros::TIME_MIN, *cam_cal);
321  bag.write(TOPIC_RAW_CAM_CONFIG, ros::TIME_MIN, *cam_config);
322  bag.write(TOPIC_RAW_CAM_DATA, ros::TIME_MIN, *cam_data);
323 
324  std::list<multisense_ros::RawLidarData::ConstPtr>::const_iterator it;
325  for (it = raw_lidar_data.begin(); it != raw_lidar_data.end(); it++)
326  bag.write(TOPIC_RAW_LIDAR, ros::TIME_MIN, **it);
327 
328  bag.close();
329  printf(" Success\n");
330 
331  return 0;
332 }
333 
#define TOPIC_RAW_LIDAR
static CRL_CONSTEXPR uint32_t IMAGER_TYPE_CMV4000_COLOR
void open(std::string const &filename, uint32_t mode=bagmode::Read)
static CRL_CONSTEXPR uint32_t IMAGER_TYPE_CMV2000_GREY
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
#define TOPIC_DEVICE_INFO
bool call(const std::string &service_name, MReq &req, MRes &res)
int main(int argc, char **argvPP)
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
#define TOPIC_RAW_CAM_DATA
#define TOPIC_RAW_LIDAR_CAL
static CRL_CONSTEXPR uint32_t IMAGER_TYPE_CMV4000_GREY
void setCallbackQueue(CallbackQueueInterface *queue)
#define TOPIC_RAW_CAM_CAL
#define TOPIC_RAW_CAM_CONFIG
ROSTIME_DECL const Time TIME_MIN
static Time now()
static CRL_CONSTEXPR uint32_t IMAGER_TYPE_CMV2000_COLOR


multisense_ros
Author(s):
autogenerated on Sun Mar 14 2021 02:34:55