joint_imager.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2008, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34 
35 #include <cstdio>
37 #include <ros/console.h>
38 
39 using namespace laser_joint_processor;
40 using namespace std;
41 
43 {
44 
45 
46 
47 }
48 
50 {
51 }
52 
53 bool JointImager::update(const calibration_msgs::DenseLaserSnapshot& snapshot,
55  const ros::Duration& max_interp)
56 {
57  if (cache.size() == 0)
58  return false;
59 
60  unsigned int num_channels = cache.back().channels_.size();
61 
62  // Size the openCV datatypes accordingly
63  allocateImages(snapshot.num_scans, snapshot.readings_per_scan, num_channels);
64 
65  vector<double> cur_positions;
66 
67  //bool success;
68 
69  unsigned int after_index = 0;
70  for (unsigned int i=0; i<snapshot.num_scans; i++)
71  {
72  for (unsigned int j=0; j<snapshot.readings_per_scan; j++)
73  {
74  ros::Time pixel_time = snapshot.scan_start[i] + ros::Duration(snapshot.time_increment * j);
75  while(after_index < cache.size() && cache[after_index].header.stamp < pixel_time)
76  after_index++;
77  assert(after_index < cache.size()); // Should never encounter this, if we already did our bounds checking on the snapshot
78  assert(after_index > 0);
79 
80  // Sanity check: Determine how far apart are the elems we're interpolating between
81  ros::Duration interp_diff = cache[after_index].header.stamp - cache[after_index-1].header.stamp;
82  if (interp_diff > max_interp)
83  {
84  ROS_WARN("Interpolating between elems that are [%.2fs] apart. Probably dopped some messages. Going to ignore this snapshot", interp_diff.toSec());
85  return false;
86  }
87 
88  settlerlib::Deflated::interp(cache[after_index-1], cache[after_index], pixel_time, cur_positions);
89 
90  // Populate position field [Channel 0] in each joint image
91  for (unsigned int k=0;k<num_channels;k++)
92  images[k](i,j)[0] = cur_positions[k];
93  }
94  ros::Time scan_start_time = snapshot.scan_start[i];
95  ros::Time scan_end_time = snapshot.scan_start[i] + ros::Duration(snapshot.time_increment * (snapshot.readings_per_scan-1));
96 
97  for (unsigned int k=0; k<num_channels; k++)
98  {
99  float start_pos = images[k](i,0)[0];
100  float end_pos = images[k](i,snapshot.readings_per_scan-1)[0];
101  float vel = (end_pos - start_pos) / (scan_end_time-scan_start_time).toSec();
102  // Walk along image row, populating the velocity channel. (Every other float is a velocity).
103  float* vel_ptr = &images[k](i,0)[1];
104  for (unsigned int j=0; j<snapshot.readings_per_scan; j++)
105  {
106  *vel_ptr = vel;
107  vel_ptr += 2;
108  }
109  }
110  }
111 
112  /* (Inefficient implementation)
113  // Iterate over scan
114  for (unsigned int i=0; i<snapshot.num_scans; i++)
115  {
116  ros::Time scan_start_time = snapshot.scan_start[i];
117  ros::Time scan_end_time = snapshot.scan_start[i] + ros::Duration(snapshot.time_increment * (snapshot.readings_per_scan-1));
118 
119  success = computeVelocity(scan_start_time, scan_end_time, cache, cur_velocities);
120  if (!success)
121  {
122  ROS_ERROR("Error computing velocity");
123  return false;
124  }
125 
126  // Iterate over each ray in a scan
127  for (unsigned int j=0; j<snapshot.readings_per_scan; j++)
128  {
129  ros::Time pixel_time = snapshot.scan_start[i] + ros::Duration(snapshot.time_increment * j);
130  success = interpPosition(pixel_time, cache, cur_positions);
131  if (!success)
132  {
133  ROS_ERROR("Error interpolating for pixel position");
134  return false;
135  }
136  for (unsigned int k=0;k<num_channels;k++)
137  {
138  *(((float*)(images[k]->imageData + images[k]->widthStep*i))+2*j + 0) = cur_positions[k];
139  *(((float*)(images[k]->imageData + images[k]->widthStep*i))+2*j + 1) = cur_velocities[k];
140  }
141  }
142  }
143  */
144  return true;
145 }
146 
147 void JointImager::displayImage(unsigned int i)
148 {
149  cv::Mat_<cv::Vec2f> image = getJointImage(i);
150 
151  for (int i=0; i<image.rows; i++)
152  {
153  for (int j=0; j<image.cols; j++)
154  {
155  printf("%5.2f ", image(i,j)[0]);
156  }
157  printf("\n");
158  }
159 }
160 
161 void JointImager::writeImage(unsigned int i, const string& filename)
162 {
163  FILE* file = fopen(filename.c_str(), "w");
164 
165  if (file)
166  printf("About to write to file %s\n", filename.c_str());
167 
168  cv::Mat_<cv::Vec2f> image = getJointImage(i);
169 
170  for (int i=0; i<image.rows; i++)
171  {
172  for (int j=0; j<image.cols; j++)
173  {
174  fprintf(file, "% 3.2f ", image(i,j)[0]);
175  }
176  fprintf(file, "\n");
177  }
178 
179  fclose(file);
180 }
181 
182 
185  vector<double>& result)
186 {
187  bool success;
190 
191  success = cache.getElemBeforeTime(target, before);
192  if (!success)
193  {
194  ROS_ERROR("Couldn't find elem before time");
195  return false;
196  }
197  success = cache.getElemAfterTime(target, after);
198  if (!success)
199  {
200  ROS_ERROR("Couldn't find elem after time");
201  return false;
202  }
203  if (before.channels_.size() != after.channels_.size())
204  {
205  ROS_ERROR("# of joints has changed in the middle of a run");
206  return false;
207  }
208 
209  success = settlerlib::Deflated::interp(before, after, target, result);
210  if (!success)
211  {
212  ROS_ERROR("Error performing interpolation");
213  return false;
214  }
215 
216  return true;
217 }
218 
219 bool JointImager::computeVelocity(const ros::Time& start, const ros::Time& end,
221  vector<double>& result)
222 {
223  vector<double> start_positions;
224  vector<double> end_positions;
225 
226  bool success;
227  success = interpPosition(start, cache, start_positions);
228  if (!success)
229  {
230  ROS_ERROR("Error extracting start position");
231  return false;
232  }
233 
234  success = interpPosition(end, cache, end_positions);
235  if (!success)
236  {
237  ROS_ERROR("Error extracting start position");
238  return false;
239  }
240 
241  if (start_positions.size() != end_positions.size())
242  {
243  ROS_ERROR("# of joints has changed during run. Can't compute velocity between samples");
244  return false;
245  }
246 
247  const unsigned int N = start_positions.size();
248 
249  result.resize(N);
250  for (unsigned int i=0; i<N; i++)
251  result[i] = (end_positions[i] - start_positions[i]) / (end-start).toSec();
252 
253  return true;
254 }
255 
256 void JointImager::allocateImages(unsigned int height, unsigned int width, unsigned int channels)
257 {
258  images.resize(channels);
259 
260  cv::Size image_size = cv::Size(width, height);
261 
262  for (unsigned int i=0; i<channels; i++)
263  images[i] = cv::Mat_<cv::Vec2f>(image_size);
264 }
265 
266 cv::Mat_<cv::Vec2f> JointImager::getJointImage(unsigned int index) const
267 {
268  return images[index];
269 }
bool computeVelocity(const ros::Time &start, const ros::Time &end, const settlerlib::SortedDeque< joint_states_settler::DeflatedJointStates > &cache, std::vector< double > &result)
#define ROS_WARN(...)
static bool interp(const Deflated &before, const Deflated &after, const ros::Time &target, std::vector< double > &result)
void allocateImages(unsigned int height, unsigned int width, unsigned int channels)
bool getElemAfterTime(const ros::Time &time, M &out) const
std::vector< double > channels_
bool getElemBeforeTime(const ros::Time &time, M &out) const
void writeImage(unsigned int i, const std::string &filename)
bool update(const calibration_msgs::DenseLaserSnapshot &snapshot, const settlerlib::SortedDeque< joint_states_settler::DeflatedJointStates > &cache, const ros::Duration &max_interp=ros::Duration(.25))
bool interpPosition(const ros::Time &target, const settlerlib::SortedDeque< joint_states_settler::DeflatedJointStates > &cache, std::vector< double > &result)
cv::Mat_< cv::Vec2f > getJointImage(unsigned int index) const
#define ROS_ERROR(...)


laser_joint_processor
Author(s): Vijay Pradeep
autogenerated on Tue Jun 1 2021 02:50:55