Неправильная ориентация коробки OBB - PullRequest
0 голосов
/ 04 мая 2020

Я использую библиотеку PCL для получения ориентации обнаруженных объектов. В основном мне нужно только получить OBB объекта (коробка на земле). Для этого я использовал момент инерции из этого урока PCL Tutorial . Итак, сначала я фильтрую облако с помощью фильтра «Сквозной фильтр», а затем выполняю плоскую сегментацию, чтобы удалить первый этаж. И в конце я использовал извлеченное Облако точек (без плоской поверхности), чтобы получить OBB объекта коробки. В конце я визуализирую его как OBB в Rviz (ROS). Здесь код на C ++ (PCL и ROS).

ros::Publisher pub, markers_pub_;

void cloud_cb(const sensor_msgs::PointCloud2::ConstPtr &msg){

    // Convert to pcl point cloud
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_msg (new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::fromROSMsg(*msg,*cloud_msg);
    //ROS_DEBUG("%s: new ponitcloud (%i,%i)(%zu)",_name.c_str(),cloud_msg->width,cloud_msg->height,cloud_msg->size());

    // Filter cloud
    pcl::PassThrough<pcl::PointXYZRGB> pass;
    pass.setInputCloud(cloud_msg);
    pass.setFilterFieldName ("y");
    pass.setFilterLimits(0.001,10);
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
    pass.filter (*cloud);

    // Get segmentation ready
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
    pcl::SACSegmentation<pcl::PointXYZRGB> seg;
    pcl::ExtractIndices<pcl::PointXYZRGB> extract;
    seg.setOptimizeCoefficients (true);
    seg.setModelType (pcl::SACMODEL_PLANE);
    seg.setMethodType (pcl::SAC_RANSAC);
    seg.setDistanceThreshold(0.04);

    // Create pointcloud to publish inliers
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_pub(new pcl::PointCloud<pcl::PointXYZRGB>);


        // Fit a plane
        seg.setInputCloud(cloud);
        seg.segment(*inliers, *coefficients);

        // Check result
        if (inliers->indices.size() == 0)
           {
            ROS_WARN_STREAM ("Could not estimate a planar model for the given dataset.") ;
            }


        // Extract inliers
        extract.setInputCloud(cloud);
        extract.setIndices(inliers);
        extract.setNegative(true);
        //pcl::PointCloud<pcl::PointXYZRGB> cloudF;
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_box (new pcl::PointCloud<pcl::PointXYZRGB> ());
        extract.filter(*cloud_box);

  //Moment of Inertia
  pcl::MomentOfInertiaEstimation <pcl::PointXYZRGB> feature_extractor;
  feature_extractor.setInputCloud (cloud_box);
  feature_extractor.compute ();

  std::vector <float> moment_of_inertia;
  std::vector <float> eccentricity;

  pcl::PointXYZRGB min_point_OBB;
  pcl::PointXYZRGB max_point_OBB;
  pcl::PointXYZRGB position_OBB;
  Eigen::Matrix3f rotational_matrix_OBB;
  float major_value, middle_value, minor_value;
  Eigen::Vector3f major_vector, middle_vector, minor_vector;
  Eigen::Vector3f mass_center;

  feature_extractor.getMomentOfInertia (moment_of_inertia);
  feature_extractor.getEccentricity (eccentricity);
  feature_extractor.getOBB (min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
  feature_extractor.getEigenValues (major_value, middle_value, minor_value);
  feature_extractor.getEigenVectors (major_vector, middle_vector, minor_vector);
  feature_extractor.getMassCenter (mass_center);

  Eigen::Vector3f position (position_OBB.x, position_OBB.y, position_OBB.z);
  Eigen::Quaternionf quat (rotational_matrix_OBB);

  cout << " orientation x  = " << quat.x() <<  endl;
  cout << " orientation y = "  << quat.y() <<  endl;
  cout << " orientation z = "  << quat.z() <<  endl;
  cout << " orientation w = "  << quat.w() <<  endl;
  cout << " postion x  = " << position_OBB.x <<  endl;
  cout << " postion y  = " << position_OBB.y <<  endl;
  cout << " postion z  = " << position_OBB.z <<  endl;


    // Publish points
    sensor_msgs::PointCloud2 cloud_publish;
    pcl::toROSMsg(*cloud_box,cloud_publish);
    pub.publish(cloud_publish);

  //Visualisation Marker
  std::string ns; 
  float r; 
  float g; 
  float b;
  visualization_msgs::MarkerArray msg_marker;
  visualization_msgs::Marker bbx_marker;
  bbx_marker.header.frame_id = "zed_left_camera_frame";
  bbx_marker.header.stamp = ros::Time::now();
  bbx_marker.ns = ns;
  bbx_marker.type = visualization_msgs::Marker::CUBE;
  bbx_marker.action = visualization_msgs::Marker::ADD;
  bbx_marker.pose.position.x =  position_OBB.x;
  bbx_marker.pose.position.y =  position_OBB.y;
  bbx_marker.pose.position.z =  position_OBB.z;
  bbx_marker.pose.orientation.x = quat.x();
  bbx_marker.pose.orientation.y = quat.x();
  bbx_marker.pose.orientation.z = quat.x();
  bbx_marker.pose.orientation.w = quat.x();
  bbx_marker.scale.x = (max_point_OBB.x - min_point_OBB.x);
  bbx_marker.scale.y = (max_point_OBB.y - min_point_OBB.y);
  bbx_marker.scale.z = (max_point_OBB.z - min_point_OBB.z);
  bbx_marker.color.b = b;
  bbx_marker.color.g = g;
  bbx_marker.color.r = r;
  bbx_marker.color.a = 0.4;
  bbx_marker.lifetime = ros::Duration();
  msg_marker.markers.push_back(bbx_marker);
  markers_pub_.publish(msg_marker);

}

int
main (int argc, char** argv)
{
  // Initialize ROS
  ros::init (argc, argv, "my_pcl_tutorial");
  ros::NodeHandle nh;
  // Create a ROS subscriber for the input point cloud
  ros::Subscriber sub = nh.subscribe ("/zed/zed_node/point_cloud/cloud_registered", 200, cloud_cb);
  // Create a ROS publisher for the output point cloud
  pub = nh.advertise<sensor_msgs::PointCloud2> ("cloud_publish", 100);
  markers_pub_ = nh.advertise<visualization_msgs::MarkerArray> ("msg_marker", 100);
    ros::spin();
  ros::spin ();
}

Здесь сцена облака точек.

The whole pointcloud scene

Затем извлеченный блок и визуализированный OBB.

Visualized OBB

Итак, мой вопрос, почему ориентация OBB не правильная? не совпадает с красной рамкой. Также вывод выглядит следующим образом:

orientation x  = 0.553429
 orientation y = 0.409076
 orientation z = 0.575402
 orientation w = 0.441912
 postion x  = 0.688811
 postion y  = 0.296049
 postion z  = -0.0444195
 orientation x  = 0.551899
 orientation y = 0.41675
 orientation z = 0.556839
 orientation w = 0.460061
 postion x  = 0.6858
 postion y  = 0.297214
 postion z  = -0.0479018
 orientation x  = -0.447575
 orientation y = 0.523119
 orientation z = -0.488997
 orientation w = 0.535635
 postion x  = 0.687003
 postion y  = 0.296398
 postion z  = -0.0541157
 orientation x  = -0.435059
 orientation y = 0.533038
 orientation z = -0.483508
 orientation w = 0.541123
 postion x  = 0.689015
 postion y  = 0.299274
 postion z  = -0.0532807
 orientation x  = -0.483639
 orientation y = 0.486945
 orientation z = -0.526589
 orientation w = 0.50168
 postion x  = 0.687567
 postion y  = 0.290984
 postion z  = -0.0566443
 orientation x  = -0.451907
 orientation y = 0.514618
 orientation z = -0.499482
 orientation w = 0.530533
 postion x  = 0.688489
 postion y  = 0.300407
 postion z  = -0.0544657
 orientation x  = -0.462979
 orientation y = 0.508457
 orientation z = -0.503387
 orientation w = 0.523185
 postion x  = 0.687322
 postion y  = 0.294014
 postion z  = -0.0556483
 orientation x  = 0.507688
 orientation y = 0.462501
 orientation z = 0.530055
 orientation w = 0.497381
 postion x  = 0.687552
 postion y  = 0.293263
 postion z  = -0.055368
 orientation x  = -0.413774
 orientation y = 0.554115
 orientation z = -0.456901
 orientation w = 0.559455

Как можно видеть изменение ориентации. Пожалуйста, помогите как улучшить результаты? Спасибо

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Проблема решена. Это была опечатка в

bbx_marker.pose.orientation.x = quat.x();
bbx_marker.pose.orientation.y = quat.x();
bbx_marker.pose.orientation.z = quat.x();
bbx_marker.pose.orientation.w = quat.x();

Я должен быть

bbx_marker.pose.orientation.x = quat.x();
  bbx_marker.pose.orientation.y = quat.y();
  bbx_marker.pose.orientation.z = quat.z();
  bbx_marker.pose.orientation.w = quat.w();
0 голосов
/ 06 мая 2020

Обычно, когда возникает проблема с поворотами в 3D, системы отсчета, используемые различными библиотеками, часто отличаются и нуждаются в исправлении, прежде чем переходить между ними (в данном случае ROS и PCL). Я не могу сказать, в этом ли проблема.

Однако я также вижу следующую проблему в представленном коде:

  // notice all assignments are from x() to {x,y,z,w}
  // they should be from x() to x, y() to y and so on and so forth
  bbx_marker.pose.orientation.x = quat.x();
  bbx_marker.pose.orientation.y = quat.x();
  bbx_marker.pose.orientation.z = quat.x();
  bbx_marker.pose.orientation.w = quat.x();

Похоже, что либо

  1. вы неправильно назначаете ориентацию ИЛИ
  2. вы не синхронизировали код и изображения с вашими наблюдениями
...