Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <rve_common/eigen_conversions.h>
00031 #include <rve_render_client/camera.h>
00032 #include <rve_msgs/make_vector3.h>
00033 #include "rve_geometry/screen_to_world.h"
00034
00035 namespace rve_geometry
00036 {
00037
00040 class Ray
00041 {
00042 public:
00045 rve_msgs::Vector3 getPoint( float distance );
00046
00050 std::pair<bool, float> intersect( const Plane& plane );
00051
00053 static Ray createFromCameraPixel( const rve_render_client::CameraPtr& camera,
00054 float screen_x, float screen_y );
00055
00056 private:
00057 Eigen::Vector3f origin_;
00058 Eigen::Vector3f direction_;
00059 };
00060
00061 rve_msgs::Vector3 Ray::getPoint( float distance )
00062 {
00063 return rve_common::eigenToMsg( origin_ + distance * direction_ );
00064 }
00065
00066 std::pair<bool, float> Ray::intersect( const Plane& plane )
00067 {
00068 float denominator = rve_common::msgToEigen(plane.normal_).dot( direction_ );
00069 if( fabsf( denominator ) < std::numeric_limits<float>::epsilon() )
00070 {
00071 return std::pair<bool, float>(false, 0);
00072 }
00073 else
00074 {
00075 float numerator = rve_common::msgToEigen(plane.normal_).dot( origin_ ) + plane.distance_from_origin_;
00076 float distance = -(numerator / denominator);
00077 return std::pair<bool,float>(distance >= 0, distance);
00078 }
00079 }
00080
00081
00082
00083
00084 static Eigen::Matrix3f compute_view_to_robot()
00085 {
00086 Eigen::Matrix3f view_to_robot;
00087 view_to_robot =
00088 Eigen::AngleAxisf(-M_PI/2, Eigen::Vector3f::UnitY()) *
00089 Eigen::AngleAxisf(-M_PI/2, Eigen::Vector3f::UnitZ());
00090 return view_to_robot;
00091 }
00092
00093
00094
00095 static Eigen::Matrix3f view_to_robot = compute_view_to_robot();
00096 static Eigen::Matrix3f robot_to_view = view_to_robot.inverse();
00097
00098
00099
00100 static Eigen::Matrix4f getViewMatrix( const rve_render_client::CameraPtr& camera )
00101 {
00102 Eigen::Matrix3f rot_t = Eigen::Matrix3f( rve_common::msgToEigen( camera->getOrientation() )).transpose();
00103 Eigen::Vector3f trans = -rot_t * rve_common::msgToEigen( camera->getPosition() );
00104
00105 Eigen::Matrix4f cam_to_view;
00106 cam_to_view <<
00107 robot_to_view, Eigen::MatrixXf::Zero(3,1),
00108 0, 0, 0, 1;
00109 Eigen::Matrix4f world_to_cam;
00110 world_to_cam <<
00111 rot_t , trans,
00112 0, 0, 0, 1;
00113
00114 return cam_to_view * world_to_cam;
00115 }
00116
00117 Ray Ray::createFromCameraPixel( const rve_render_client::CameraPtr& camera,
00118 float screen_x, float screen_y )
00119 {
00120 Eigen::Matrix4f inverse_projection = (rve_common::msgToEigen(camera->getProjectionMatrix()) * getViewMatrix(camera)).inverse();
00121
00122 float nx = (2.0f * screen_x) - 1.0f;
00123 float ny = 1.0f - (2.0f * screen_y);
00124
00125 Eigen::Vector4f near_point(nx, ny, -1.f, 1.f);
00126 Eigen::Vector4f mid_point (nx, ny, 0.0f, 1.f);
00127
00128
00129 Eigen::Vector4f ray_origin, ray_target;
00130
00131 ray_origin = inverse_projection * near_point;
00132 ray_target = inverse_projection * mid_point;
00133
00134 ray_origin /= ray_origin(3);
00135 ray_target /= ray_target(3);
00136
00137 Eigen::Vector3f ray_origin3 = ray_origin.start<3>();
00138 Eigen::Vector3f ray_target3 = ray_target.start<3>();
00139
00140 Eigen::Vector3f ray_direction = ray_target3 - ray_origin3;
00141
00142 ray_direction.normalize();
00143
00144 Ray out_ray;
00145 out_ray.origin_= ray_origin3;
00146 out_ray.direction_ = ray_direction;
00147
00148 return out_ray;
00149 }
00150
00151 bool screenToWorld( const Plane& world_plane,
00152 const rve_render_client::CameraPtr &camera,
00153 int screen_x, int screen_y,
00154 int screen_width, int screen_height,
00155 rve_msgs::Vector3* position_output )
00156 {
00157 Ray pixel_ray = Ray::createFromCameraPixel( camera,
00158 float(screen_x)/float(screen_width),
00159 float(screen_y)/float(screen_height) );
00160 std::pair<bool, float> intersection = pixel_ray.intersect( world_plane );
00161 if( intersection.first )
00162 {
00163 if( position_output )
00164 {
00165 *position_output = pixel_ray.getPoint( intersection.second );
00166 }
00167 return true;
00168 }
00169 else
00170 {
00171 return false;
00172 }
00173 }
00174
00175 }