24 #include <sensor_msgs/PointCloud2.h> 
   25 #include <sensor_msgs/PointField.h> 
   27 bool equals(
const sensor_msgs::PointCloud2& lhs, 
const sensor_msgs::PointCloud2& rhs)
 
   30   bool are_header_equals = (lhs.header.seq        == rhs.header.seq) &&
 
   31                            (lhs.header.stamp.sec  == rhs.header.stamp.sec) &&
 
   32                            (lhs.header.stamp.nsec == rhs.header.stamp.nsec) &&
 
   33                            (lhs.header.frame_id   == rhs.header.frame_id);
 
   34   if (!are_header_equals)
 
   40   bool are_parameters_equals = (lhs.height       == rhs.height) &&
 
   41                                (lhs.width        == rhs.width) &&
 
   42                                (lhs.is_bigendian == rhs.is_bigendian) &&
 
   43                                (lhs.point_step   == rhs.point_step) &&
 
   44                                (lhs.row_step     == rhs.row_step) &&
 
   45                                (lhs.is_dense     == rhs.is_dense);
 
   46   if (!are_parameters_equals)
 
   52   bool are_all_fields_equals = 
true;
 
   53   if (lhs.fields.size() == rhs.fields.size()){
 
   54     for (uint i=0; i < lhs.fields.size(); i++)
 
   56       if (!((lhs.fields[i].name     == rhs.fields[i].name) &&
 
   57             (lhs.fields[i].offset   == rhs.fields[i].offset) &&
 
   58             (lhs.fields[i].datatype == rhs.fields[i].datatype) &&
 
   59             (lhs.fields[i].count    == rhs.fields[i].count)))
 
   61         are_all_fields_equals = 
false;
 
   68     are_all_fields_equals = 
false;
 
   70   if (!are_all_fields_equals)
 
   76   bool is_data_equal = (lhs.data.size() == rhs.data.size()) &&
 
   77                        (memcmp(lhs.data.data(),rhs.data.data(),lhs.data.size())) == 0;
 
   86 std::string 
decode_chunk(
const sensor_msgs::PointCloud2& sensor_msg, uint index)
 
   88   std::stringstream output_buffer;
 
   90   size_t point_size = sensor_msg.row_step/sensor_msg.width;  
 
   92   const uint8_t* chunk_start_ptr = 
reinterpret_cast<const uint8_t*
>(sensor_msg.data.data()) + (index*point_size);
 
   94   output_buffer << 
"chunk#" << index << 
" : ";
 
   96   for (uint i = 0; i < sensor_msg.fields.size(); i++)
 
   98     uint offset = sensor_msg.fields[i].offset;  
 
   99     for (uint current_count = 0; current_count < sensor_msg.fields[i].count ; current_count++)
 
  102         switch(sensor_msg.fields[i].datatype)
 
  104             case sensor_msgs::PointField::INT8 :
 
  107             memcpy(&val8, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  108             output_buffer << sensor_msg.fields[i].name << 
" : " << val8 << 
"; ";
 
  110             case sensor_msgs::PointField::UINT8 :
 
  113             memcpy(&valu8, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  114             output_buffer << sensor_msg.fields[i].name << 
" : " << valu8 << 
"; ";
 
  116             case sensor_msgs::PointField::INT16 :
 
  119             memcpy(&val16, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  120             output_buffer << sensor_msg.fields[i].name << 
" : " << val16 << 
"; ";
 
  122             case sensor_msgs::PointField::UINT16 :
 
  125             memcpy(&valu16, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  126             output_buffer << sensor_msg.fields[i].name << 
" : " << valu16 << 
"; ";
 
  128             case sensor_msgs::PointField::INT32 :
 
  131             memcpy(&val32, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  132             output_buffer << sensor_msg.fields[i].name << 
" : " << val32 << 
"; ";
 
  134             case sensor_msgs::PointField::UINT32 :
 
  137             memcpy(&valu32, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  138             output_buffer << sensor_msg.fields[i].name << 
" : " << valu32 << 
"; ";
 
  140             case sensor_msgs::PointField::FLOAT32 :
 
  143             memcpy(&valf32, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  144             output_buffer << sensor_msg.fields[i].name << 
" : " << valf32 << 
"; ";
 
  146             case sensor_msgs::PointField::FLOAT64 :
 
  149             memcpy(&valf64, chunk_start_ptr+offset+(current_count*read_size), read_size);
 
  150             output_buffer << sensor_msg.fields[i].name << 
" : " << valf64 << 
"; ";
 
  155   return output_buffer.str();
 
  160                                 const std::vector<uint8_t>& tested,
 
  161                                 uint chunk_size, uint* out_index = 
nullptr)
 
  163   uint min_size = std::min(expected.size(),tested.size());
 
  164   for (uint i = 0; i < min_size; i++)
 
  166     if (expected[i]!=tested[i])
 
  169       uint chunk_id = i / chunk_size;  
 
  170       uint chunk_start_index = chunk_id * chunk_size;
 
  171       std::stringstream output_buffer;
 
  172       output_buffer << 
"first mismatch at index " << i << 
" (chunk #" << chunk_id << 
") : ";
 
  173       for (uint j = chunk_start_index; j < std::min(chunk_start_index+chunk_size, min_size); j++)
 
  175         output_buffer << std::hex << static_cast<int>(expected[j]);
 
  177       output_buffer << 
" | ";
 
  178       for (uint j = chunk_start_index; j < std::min(chunk_start_index+chunk_size, min_size); j++)
 
  180         output_buffer << std::hex << static_cast<int>(tested[j]);
 
  182       if (out_index != 
nullptr)
 
  184         *out_index = chunk_id;
 
  186       return output_buffer.str();
 
  189   if (out_index != 
nullptr)
 
  197                             const sensor_msgs::PointCloud2& tested,
 
  198                             bool locate_first_data_disparity = 
false)
 
  200   std::stringstream output_buffer;
 
  203   if (expected.header.seq != tested.header.seq)
 
  205     output_buffer << 
"header.seq are differents : expected : " << expected.header.seq
 
  206       << 
"; got : " << tested.header.seq << std::endl;
 
  208   if (expected.header.stamp.sec != tested.header.stamp.sec)
 
  210     output_buffer << 
"header.stamp.sec are differents : expected : " << expected.header.stamp.sec
 
  211       << 
"; got : " << tested.header.stamp.sec << std::endl;
 
  213   if (expected.header.stamp.nsec != tested.header.stamp.nsec)
 
  215     output_buffer << 
"header.stamp.nsec are differents : expected : " << expected.header.stamp.nsec
 
  216       << 
"; got : " << tested.header.stamp.nsec << std::endl;
 
  218   if (expected.header.frame_id != tested.header.frame_id)
 
  220     output_buffer << 
"header.frame_id are differents : expected : " << expected.header.frame_id
 
  221       << 
"; got : " << tested.header.frame_id << std::endl;
 
  225   if (expected.height != tested.height)
 
  227     output_buffer << 
"height are differents : expected : " << expected.height
 
  228       << 
"; got : " << tested.height << std::endl;
 
  230   if (expected.width != tested.width)
 
  232     output_buffer << 
"width are differents : expected : " << expected.width <<
 
  233       "; got : " << tested.width << std::endl;
 
  235   if (expected.is_bigendian != tested.is_bigendian)
 
  237     output_buffer << 
"is_bigendian are differents : expected : " << expected.is_bigendian
 
  238       << 
"; got : " << tested.is_bigendian << std::endl;
 
  240   if (expected.point_step != tested.point_step)
 
  242     output_buffer << 
"point_step are differents : expected : " << expected.point_step
 
  243       << 
"; got : " << tested.point_step << std::endl;
 
  245   if (expected.row_step != tested.row_step)
 
  247     output_buffer << 
"row_step are differents : expected : " << expected.row_step
 
  248       << 
"; got : " << tested.row_step << std::endl;
 
  250   if (expected.is_dense != tested.is_dense)
 
  252     output_buffer << 
"is_dense are differents : expected : " << expected.is_dense
 
  253       << 
"; got : " << tested.is_dense << std::endl;
 
  257   if (expected.fields.size() != tested.fields.size())
 
  259     output_buffer << 
"field sizes are differents : expected : " << expected.fields.size()
 
  260       << 
"; got : " << tested.fields.size() << std::endl;
 
  263   uint min_field_size = std::min(expected.fields.size(),tested.fields.size());
 
  264   for (uint i=0; i < min_field_size; i++)
 
  266     if (expected.fields[i].name != tested.fields[i].name)
 
  268       output_buffer << 
"fields[" << i << 
"].name are differents : expected : " 
  269         << expected.fields[i].name << 
"; got : " << tested.fields[i].name << std::endl;
 
  271     if (expected.fields[i].offset != tested.fields[i].offset)
 
  273       output_buffer << 
"fields[" << i << 
"].offset are differents : expected : " 
  274         << expected.fields[i].offset << 
"; got : " << tested.fields[i].offset << std::endl;
 
  276     if (expected.fields[i].datatype != tested.fields[i].datatype)
 
  278       output_buffer << 
"fields[" << i << 
"].datatype are differents : expected : " 
  279         << expected.fields[i].datatype << 
"; got : " << tested.fields[i].datatype << std::endl;
 
  281     if (expected.fields[i].count != tested.fields[i].count)
 
  283       output_buffer << 
"fields[" << i << 
"].count are differents : expected : " 
  284         << expected.fields[i].count << 
"; got : " << tested.fields[i].count << std::endl;
 
  289   if(expected.data.size() != tested.data.size())
 
  291     output_buffer << 
"data sizes are differents : expected : " << expected.data.size()
 
  292       << 
"; got : " << tested.data.size() << std::endl;
 
  294   if (memcmp(expected.data.data(),tested.data.data(),expected.data.size()) != 0)
 
  296     output_buffer << 
"data are differents";
 
  297     if (locate_first_data_disparity)
 
  299       uint point_size = expected.row_step/expected.width;  
 
  300       uint mismatch_index = 0;
 
  301       output_buffer << 
" : " << 
get_first_mismatch(expected.data, tested.data, point_size, &mismatch_index);
 
  302       output_buffer << std::endl << 
"expected : " << 
decode_chunk(expected, mismatch_index);
 
  303       output_buffer << std::endl << 
"     got : " << 
decode_chunk(tested, mismatch_index);
 
  305     output_buffer << std::endl;
 
  308   return output_buffer.str();
 
  314                           const sensor_msgs::PointCloud2& expected_no_ground,
 
  315                           const sensor_msgs::PointCloud2& tested_ground,
 
  316                           const sensor_msgs::PointCloud2& tested_no_ground,
 
  317                           uint* out_false_ground_count,
 
  318                           uint* out_false_no_ground_count)
 
  320   uint point_size = expected_no_ground.row_step/expected_no_ground.width;  
 
  321   if (((expected_ground.data.size()%point_size) != 0) ||
 
  322       ((expected_no_ground.data.size()%point_size) != 0) ||
 
  323       ((tested_ground.data.size()%point_size) != 0) ||
 
  324       ((tested_no_ground.data.size()%point_size) != 0))
 
  329   uint expected_ground_point_count = expected_ground.data.size()/point_size;
 
  330   uint expected_no_ground_point_count = expected_no_ground.data.size()/point_size;
 
  331   uint tested_ground_point_count = tested_ground.data.size()/point_size;
 
  332   uint tested_no_ground_point_count = tested_no_ground.data.size()/point_size;
 
  334   uint tested_no_ground_index = 0;
 
  335   uint expected_no_ground_index = 0;
 
  337   *out_false_ground_count = 0;
 
  338   *out_false_no_ground_count = 0;
 
  340   bool all_mismatches_are_legit = 
true;
 
  342   while ((tested_no_ground_index < tested_no_ground_point_count) &&
 
  343          (expected_no_ground_index < expected_no_ground_point_count))
 
  348       is_equal = memcmp(tested_no_ground.data.data() + tested_no_ground_index*point_size,
 
  349                         expected_no_ground.data.data() + (expected_no_ground_index)*point_size,
 
  351       tested_no_ground_index++;
 
  352       expected_no_ground_index++;
 
  353     }
while (is_equal && (tested_no_ground_index < tested_no_ground_point_count) &&
 
  354          (expected_no_ground_index < expected_no_ground_point_count));
 
  359       bool is_false_no_ground = 
false;
 
  360       for (uint i=0; i<expected_ground_point_count; i++)
 
  362         if (0 == memcmp(tested_no_ground.data.data() + (tested_no_ground_index-1)*point_size,
 
  363                         expected_ground.data.data() + i*point_size,point_size))
 
  365           is_false_no_ground = 
true;
 
  370       bool is_false_ground = 
false;
 
  371       for (uint i=0; i<tested_ground_point_count; i++)
 
  373         if (0 == memcmp(expected_no_ground.data.data() + (expected_no_ground_index-1)*point_size,
 
  374                         tested_ground.data.data() + i*point_size,point_size))
 
  376           is_false_ground = 
true;
 
  382       if (is_false_no_ground)
 
  387           *out_false_ground_count += 1;
 
  388           *out_false_no_ground_count += 1;
 
  393           expected_no_ground_index--;
 
  394           *out_false_no_ground_count += 1;
 
  402           tested_no_ground_index--;
 
  403           *out_false_ground_count += 1;
 
  408           all_mismatches_are_legit = 
false;
 
  413   return all_mismatches_are_legit;