rating.cpp
Go to the documentation of this file.
00001 
00018 #include "rating.h"
00019 #include <Eigen/Dense>
00020 #include <ros/console.h>
00021 
00022 #include <pcl/point_cloud.h>
00023 #include <pcl/filters/frustum_culling.h>
00024 #include <pcl/impl/point_types.hpp>
00025 
00026 #include <pcl/filters/impl/frustum_culling.hpp>
00027 
00028 namespace fake_object_recognition {
00029 
00030 Rating::Rating(double fovx, double fovy, double ncp, double fcp) :
00031     fovx_(fovx),
00032     fovy_(fovy),
00033     ncp_(ncp),
00034     fcp_(fcp),
00035     camera_orientation_(Eigen::Vector3d(0.0, 0.0, 1.0)) { }
00036 
00037 bool Rating::ratePose(const geometry_msgs::Pose &pose, double threshold_d, double threshold_x, double threshold_y) {
00038     //Use distance and agle ratings to rate pose.
00039     double rating_d = getDistanceRating(pose);
00040     ROS_DEBUG_STREAM("Distance Rating: " << rating_d);
00041     double rating_x = getAngleRating(pose, true);
00042     ROS_DEBUG_STREAM("Angle rating in xz-plane: " << rating_x);
00043     double rating_y = getAngleRating(pose, false);
00044     ROS_DEBUG_STREAM("Angle rating in yz-plane: " << rating_y);
00045 
00046     return rating_d > threshold_d && rating_x > threshold_x && rating_y > threshold_y;
00047 }
00048 
00049 double Rating::getDistanceRating(const geometry_msgs::Pose &object_pose) {
00050     double rating = 0.0;
00051     Eigen::Vector3d object_position(object_pose.position.x, object_pose.position.y, object_pose.position.z);
00052     double dot_cam_obj = camera_orientation_.dot(object_position);
00053 
00054     double dist_to_mid = std::abs(dot_cam_obj - ((fcp_ + ncp_) / 2.0));
00055     double dist_threshold = (fcp_ - ncp_) / 2.0;
00056 
00057     if (dist_to_mid < dist_threshold) {
00058         rating = 0.5 + 0.5 * cos((dist_to_mid * M_PI) / dist_threshold);
00059     }
00060 
00061     return rating;
00062 }
00063 
00064   double Rating::getAngleRating(const geometry_msgs::Pose &object_pose, bool direction) {
00065     double rating = 0.0;
00066 
00067     Eigen::Vector3d object_position(object_pose.position.x, object_pose.position.y, object_pose.position.z);
00068 
00069     double angle_max;
00070 
00071     //Azimut
00072     if(direction){
00073       //Project object position on xz-plane of camera frame.
00074       object_position.y() = 0.0;
00075       angle_max = (fovx_ * M_PI) / 180.0;
00076     }
00077     //Elevation
00078     else {
00079       //Project object position on xz-plane of camera frame.
00080       object_position.x() = 0.0;
00081       angle_max = (fovy_ * M_PI) / 180.0;
00082     }
00083 
00084     object_position.normalize();
00085 
00086     double angle = std::acos(camera_orientation_.dot(object_position));
00087 
00088     if (angle < angle_max) {
00089         rating = 0.5 + 0.5 * std::cos((angle * M_PI) / angle_max);
00090     }
00091 
00092     return rating;
00093 }
00094 
00095 bool Rating::getBBRating(const std::array<geometry_msgs::Point, 8> &bounding_box) {
00096     pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud = boost::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
00097     unsigned int bb_size = bounding_box.size(); // always 8
00098     for (unsigned int i = 0; i < bb_size; i++) {
00099         pcl::PointXYZ pt = pcl::PointXYZ(bounding_box.at(i).x, bounding_box.at(i).y, bounding_box.at(i).z);
00100         point_cloud->push_back(pt);
00101     }
00102 
00103     pcl::FrustumCulling<pcl::PointXYZ> fc;
00104     fc.setHorizontalFOV(fovx_);
00105     fc.setVerticalFOV(fovy_);
00106     fc.setNearPlaneDistance(ncp_);
00107     fc.setFarPlaneDistance(fcp_);
00108 
00109     /* Camera pose: since visual axis is always set to (0,0,1) in ctor, a fixed matrix is used here; it is a homogenous matrix rotating around the y-axis by 90 degrees
00110      * because of the assumption that the camera is pointing in the x direction in the beginning. */
00111     Eigen::Matrix4f cam;
00112     cam <<  0.0, 0.0, -1.0, 0.0,
00113             0.0, 1.0,  0.0, 0.0,
00114             1.0, 0.0,  0.0, 0.0,
00115             0.0, 0.0,  0.0, 1.0;
00116     fc.setCameraPose(cam);
00117 
00118     fc.setInputCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr(point_cloud));
00119 
00120     pcl::PointCloud<pcl::PointXYZ>::Ptr culled_cloud = boost::make_shared<pcl::PointCloud<pcl::PointXYZ>>();
00121     fc.filter(*culled_cloud);
00122 
00123     return (culled_cloud->size() == bb_size);
00124 }
00125 
00126 double Rating::getNormalRating(const geometry_msgs::Pose &object_pose, const std::vector<geometry_msgs::Point> &normals) {
00127     //similar to NBV - DefaulRatingModule
00128     // (never called with empty normals because of check in rateBBandNormal)
00129     Eigen::Vector3d v1, v2;
00130     double angleThreshold = M_PI * 0.5;
00131     v1 << object_pose.position.x, object_pose.position.y, object_pose.position.z; // Vector describing the position of the object.
00132     v1 = (-1) * v1;
00133     v1.normalize(); // Vector from camera to object
00134 
00135     float xNorm = v1.lpNorm<2>();
00136     if (xNorm == 0) {
00137         ROS_DEBUG_STREAM("Object appears to be inside camera.");
00138         return 0.0;
00139     }
00140     // find maximum rating:
00141     float best_rated = 0.0;
00142     for (unsigned int i = 0; i < normals.size(); i++) {
00143         v2 << normals.at(i).x, normals.at(i).y, normals.at(i).z;
00144         v2.normalize();
00145         float yNorm = v2.lpNorm<2>();
00146         if (yNorm != 0) { // Otherwise normal does not actually exist
00147             float cosine = v1.dot(v2) / xNorm / yNorm;
00148             float angle = std::acos(cosine);
00149             if (angle < angleThreshold) {
00150                 float rating = 0.5 + 0.5 * std::cos(angle * M_PI / angleThreshold);
00151                 if (rating > best_rated) { best_rated = rating; }
00152             }           
00153         }
00154     }
00155     ROS_DEBUG_STREAM("getNormalRating: best_rated = " << best_rated);
00156     return best_rated;
00157 }
00158 
00159 bool Rating::rateBBandNormal(const geometry_msgs::Pose &object_pose, const std::array<geometry_msgs::Point, 8> &bounding_box, const std::vector<geometry_msgs::Point> &normals, double threshold) {
00160     if (!getBBRating(bounding_box)) {       // if not all 8 corner points of bounding box are inside the frustum:
00161         return false;                       // Return immediately.
00162     }
00163     else if (normals.empty()) {             // if there are no normals, e.g. because an object has no clear ones:
00164         return true;                        // since all bounding box corner points are inside frustum: return true.
00165     }
00166     else {
00167         return (getNormalRating(object_pose, normals) > threshold); // Otherwise rate normals.
00168     }
00169 }
00170 
00171 
00172 
00173 
00174 }


asr_fake_object_recognition
Author(s): Allgeyer Tobias, Aumann Florian, Borella Jocelyn, Meißner Pascal, Qattan Mohamad
autogenerated on Sat Jun 8 2019 19:15:45