DepthImageToLaserScanTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Willow Garage, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Willow Garage, Inc. nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * Author: Chad Rockey
32  */
33 
34 // Bring in my package's API, which is what I'm testing
36 // Bring in gtest
37 #include <gtest/gtest.h>
38 
39 #include <limits.h>
40 #include <math.h>
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <time.h>
45 
46 // Library object
48 
49 // Inputs
50 sensor_msgs::ImagePtr depth_msg_;
51 sensor_msgs::CameraInfoPtr info_msg_;
52 
53 // Check if the setters work properly and initialize member variables
54 TEST(ConvertTest, setupLibrary)
55 {
56  // Set up library
57  const float scan_time = 1.0/30.0;
58  dtl_.set_scan_time(scan_time);
59  const float range_min = 0.45;
60  const float range_max = 10.0;
61  dtl_.set_range_limits(range_min, range_max);
62  const int scan_height = 1;
63  dtl_.set_scan_height(scan_height);
64  const std::string output_frame = "camera_depth_frame";
65  dtl_.set_output_frame(output_frame);
66 
67  depth_msg_.reset(new sensor_msgs::Image);
68  depth_msg_->header.seq = 42;
69  depth_msg_->header.stamp.fromNSec(1234567890);
70  depth_msg_->header.frame_id = "frame";
71  depth_msg_->height = 480;
72  depth_msg_->width = 640;
74  depth_msg_->is_bigendian = false;
75  depth_msg_->step = depth_msg_->width*2; // 2 bytes per pixel
76  uint16_t value = 0x0F;
77  depth_msg_->data.assign(depth_msg_->height*depth_msg_->step, value); // Sets all values to 3.855m
78 
79  info_msg_.reset(new sensor_msgs::CameraInfo);
80  info_msg_->header = depth_msg_->header;
81  info_msg_->height = depth_msg_->height;
82  info_msg_->width = depth_msg_->width;
83  info_msg_->distortion_model = "plumb_bob";
84  info_msg_->D.resize(5); // All 0, no distortion
85  info_msg_->K[0] = 570.3422241210938;
86  info_msg_->K[2] = 314.5;
87  info_msg_->K[4] = 570.3422241210938;
88  info_msg_->K[5] = 235.5;
89  info_msg_->K[8] = 1.0;
90  info_msg_->R[0] = 1.0;
91  info_msg_->R[4] = 1.0;
92  info_msg_->R[8] = 1.0;
93  info_msg_->P[0] = 570.3422241210938;
94  info_msg_->P[2] = 314.5;
95  info_msg_->P[5] = 570.3422241210938;
96  info_msg_->P[6] = 235.5;
97  info_msg_->P[10] = 1.0;
98 
99  sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(depth_msg_, info_msg_);
100 
101  // Test set variables
102  EXPECT_EQ(scan_msg->scan_time, scan_time);
103  EXPECT_EQ(scan_msg->range_min, range_min);
104  EXPECT_EQ(scan_msg->range_max, range_max);
105  EXPECT_EQ(scan_msg->header.frame_id, output_frame);
106  EXPECT_EQ(scan_msg->ranges.size(), depth_msg_->width);
107 }
108 
109 // Test for the exception based on encoding
110 TEST(ConvertTest, testExceptions)
111 {
112  // Test supported image encodings for exceptions
113  // Does not segfault as long as scan_height = 1
115  EXPECT_THROW(dtl_.convert_msg(depth_msg_, info_msg_), std::runtime_error);
117  EXPECT_NO_THROW(dtl_.convert_msg(depth_msg_, info_msg_));
119  EXPECT_NO_THROW(dtl_.convert_msg(depth_msg_, info_msg_));
120 }
121 
122 // Check to make sure the mininum is output for each pixel column for various scan heights
123 TEST(ConvertTest, testScanHeight)
124 {
125  for(int scan_height = 1; scan_height <= 100; scan_height++){
126  uint16_t low_value = 500;
127  uint16_t high_value = 3000;
128 
129  int data_len = depth_msg_->width;
130  uint16_t* data = reinterpret_cast<uint16_t*>(&depth_msg_->data[0]);
131  int row_step = depth_msg_->step / sizeof(uint16_t);
132 
133  dtl_.set_scan_height(scan_height);
134 
135  int offset = (int)(info_msg_->K[5]-scan_height/2);
136  data += offset*row_step; // Offset to center of image
137 
138  for(int v = 0; v < scan_height; v++, data += row_step){
139  for (int u = 0; u < data_len; u++) // Loop over each pixel in row
140  {
141  if(v % scan_height == u % scan_height){
142  data[u] = low_value;
143  } else {
144  data[u] = high_value;
145  }
146  }
147  }
148 
149  // Convert
150  sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(depth_msg_, info_msg_);
151 
152  // Test for minimum
153  float high_float_thresh = (float)high_value * 1.0f/1000.0f * 0.9f; // 0.9f represents 10 percent margin on range
154  for(size_t i = 0; i < scan_msg->ranges.size(); i++){
155  // If this is a valid point
156  if(scan_msg->range_min <= scan_msg->ranges[i] && scan_msg->ranges[i] <= scan_msg->range_max){
157  // Make sure it's not set to the high_value
158  ASSERT_LT(scan_msg->ranges[i], high_float_thresh);
159  }
160  }
161  }
162 
163  // Revert to 1 scan height
164  dtl_.set_scan_height(1);
165 
166 }
167 
168 // Test a randomly filled image and ensure all values are < range_min
169 // (range_max is currently violated to fill the messages)
170 TEST(ConvertTest, testRandom)
171 {
172  srand ( 8675309 ); // Set seed for repeatable tests
173 
174  uint16_t* data = reinterpret_cast<uint16_t*>(&depth_msg_->data[0]);
175  for(size_t i = 0; i < depth_msg_->width*depth_msg_->height; i++){
176  data[i] = rand() % 500; // Distance between 0 and 0.5m
177  }
178 
179  // Convert
180  sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(depth_msg_, info_msg_);
181 
182  // Make sure all values are greater than or equal to range_min and less than or equal to range_max
183  for(size_t i = 0; i < scan_msg->ranges.size(); i++){
184  if(std::isfinite(scan_msg->ranges[i])){
185  ASSERT_GE(scan_msg->ranges[i], scan_msg->range_min);
186  ASSERT_LE(scan_msg->ranges[i], scan_msg->range_max);
187  }
188  }
189 }
190 
191 // Test to preserve NaN
192 TEST(ConvertTest, testNaN)
193 {
194  // Use a floating point image
195  sensor_msgs::ImagePtr float_msg(new sensor_msgs::Image(*depth_msg_));
196  float_msg->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
197  float_msg->step = float_msg->width*4; // 4 bytes per pixel
198  float_msg->data.resize(float_msg->step * float_msg->height);
199 
200  float* data = reinterpret_cast<float*>(&float_msg->data[0]);
201  for(size_t i = 0; i < float_msg->width*float_msg->height; i++){
202  data[i] = std::numeric_limits<float>::quiet_NaN();
203  }
204 
205  // Convert
206  sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(float_msg, info_msg_);
207 
208  // Make sure all values are NaN
209  for(size_t i = 0; i < scan_msg->ranges.size(); i++){
210  if(std::isfinite(scan_msg->ranges[i])){
211  ADD_FAILURE() << "Non-NaN value produced from NaN test.";
212  }
213  }
214 }
215 
216 // Test to preserve +Inf
217 TEST(ConvertTest, testPositiveInf)
218 {
219  // Use a floating point image
220  sensor_msgs::ImagePtr float_msg(new sensor_msgs::Image(*depth_msg_));
221  float_msg->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
222  float_msg->step = float_msg->width*4; // 4 bytes per pixel
223  float_msg->data.resize(float_msg->step * float_msg->height);
224 
225  float* data = reinterpret_cast<float*>(&float_msg->data[0]);
226  for(size_t i = 0; i < float_msg->width*float_msg->height; i++){
227  data[i] = std::numeric_limits<float>::infinity();
228  }
229 
230  // Convert
231  sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(float_msg, info_msg_);
232 
233  // Make sure most (> 80%) values are Inf
234  size_t nan_count = 0;
235  for(size_t i = 0; i < scan_msg->ranges.size(); i++){
236  if(std::isfinite(scan_msg->ranges[i])){ // NaNs are acceptable.
237  ADD_FAILURE() << "Non-finite value produced from postive infniity test.";
238  } else if(std::isnan(scan_msg->ranges[i])){
239  nan_count++;
240  } else if(scan_msg->ranges[i] < 0){
241  ADD_FAILURE() << "Negative value produced from postive infinity test.";
242  }
243  }
244 
245  ASSERT_LE(nan_count, scan_msg->ranges.size() * 0.80);
246 }
247 
248 // Test to preserve -Inf
249 TEST(ConvertTest, testNegativeInf)
250 {
251  // Use a floating point image
252  sensor_msgs::ImagePtr float_msg(new sensor_msgs::Image(*depth_msg_));
253  float_msg->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
254  float_msg->step = float_msg->width*4; // 4 bytes per pixel
255  float_msg->data.resize(float_msg->step * float_msg->height);
256 
257  float* data = reinterpret_cast<float*>(&float_msg->data[0]);
258  for(size_t i = 0; i < float_msg->width*float_msg->height; i++){
259  data[i] = -std::numeric_limits<float>::infinity();
260  }
261 
262  // Convert
263  sensor_msgs::LaserScanPtr scan_msg = dtl_.convert_msg(float_msg, info_msg_);
264 
265  // Make sure most (> 80%) values are Inf
266  size_t nan_count = 0;
267  for(size_t i = 0; i < scan_msg->ranges.size(); i++){
268  if(std::isfinite(scan_msg->ranges[i])){ // NaNs are acceptable.
269  ADD_FAILURE() << "Non-finite value produced from postive infniity test.";
270  } else if(std::isnan(scan_msg->ranges[i])){
271  nan_count++;
272  } else if(scan_msg->ranges[i] > 0){
273  ADD_FAILURE() << "Postive value produced from negative infinity test.";
274  }
275  }
276 
277  ASSERT_LE(nan_count, scan_msg->ranges.size() * 0.80);
278 }
279 
280 
281 // Run all the tests that were declared with TEST()
282 int main(int argc, char **argv){
283 testing::InitGoogleTest(&argc, argv);
284 return RUN_ALL_TESTS();
285 }
int main(int argc, char **argv)
sensor_msgs::LaserScanPtr convert_msg(const sensor_msgs::ImageConstPtr &depth_msg, const sensor_msgs::CameraInfoConstPtr &info_msg)
f
void set_output_frame(const std::string output_frame_id)
const std::string TYPE_32FC1
const std::string TYPE_16UC1
TEST(ConvertTest, setupLibrary)
sensor_msgs::CameraInfoPtr info_msg_
depthimage_to_laserscan::DepthImageToLaserScan dtl_
void set_range_limits(const float range_min, const float range_max)
sensor_msgs::ImagePtr depth_msg_


depthimage_to_laserscan
Author(s): Chad Rockey
autogenerated on Sun Jan 5 2020 03:45:46