Go to the documentation of this file.00001 #include "RealMonoCamera.hpp"
00002
00003 namespace virtual_camera {
00004
00005
00006
00007 RealMonoCamera::RealMonoCamera(std::string name,
00008 const boost::shared_ptr<tf::TransformListener> & listener):
00009 transformListener(listener) {
00010 this->name = name;
00011 this->positionCache = TableP2Ptr(new TableP2());
00012 }
00013
00014
00015 bool RealMonoCamera::isReady() {
00016 if (this->camInfo) {
00017 if (this->image) {
00018 return true;
00019 }
00020 }
00021 return false;
00022 }
00023
00024
00025 sensor_msgs::CameraInfoConstPtr RealMonoCamera::getCameraInfo() {
00026 return this->camInfo;
00027 }
00028
00029
00030 void RealMonoCamera::setCameraInfo(const sensor_msgs::CameraInfoConstPtr & camInfo) {
00031 this->camInfo = camInfo;
00032 kMat[0][0] = camInfo->K[0];kMat[0][1] = camInfo->K[1];kMat[0][2] = camInfo->K[2];
00033 kMat[1][0] = camInfo->K[3];kMat[1][1] = camInfo->K[4];kMat[1][2] = camInfo->K[5];
00034 kMat[2][0] = camInfo->K[6];kMat[2][1] = camInfo->K[7];kMat[2][2] = camInfo->K[8];
00035 }
00036
00037
00038 void RealMonoCamera::updateImage(const sensor_msgs::ImageConstPtr & image) {
00039 this->image = image;
00040 }
00041
00042
00043 void RealMonoCamera::setPointsCache(std::string frame, const TableV3Ptr & points) {
00044 this->requestFrame = frame;
00045 this->requestPoints = points;
00046 this->buildInnerCache();
00047 }
00048
00049
00050 bool RealMonoCamera::validateCache() {
00051
00052 tf::StampedTransform transform;
00053 try {
00054 this->transformListener->lookupTransform(this->name, this->requestFrame,
00055 ros::Time(0), transform);
00056 } catch (tf::TransformException & ex){
00057 ROS_ERROR("%s",ex.what());
00058 }
00059 if (areTransformsEqual(transform, this->usedTransform)){
00060 return true;
00061 }else {
00062 this->buildInnerCache();
00063 return false;
00064 }
00065 }
00066
00067
00068 std::string RealMonoCamera::getName() {
00069 return this->name;
00070 }
00071
00072
00073 TableP2ConstPtr RealMonoCamera::getCachedPositions() {
00074 return this->positionCache;
00075 }
00076
00077
00078 sensor_msgs::ImageConstPtr RealMonoCamera::getImage() {
00079 return this->image;
00080 }
00081
00082
00083 float RealMonoCamera::getWeight(int row, int col) {
00084 const Point2D & position = (*(this->positionCache))[row][col];
00085 if(position.x == NOT_VISIBLE) {
00086 return 0;
00087 }
00088 float xW = 1 - std::fabs((2.0*position.x/camInfo->width)-1);
00089 float yW = 1 - std::fabs((2.0*position.y/camInfo->height)-1);
00090 return std::min(xW, yW);
00091 }
00092
00093
00094
00095
00096
00097 void RealMonoCamera::buildInnerCache() {
00098 tf::StampedTransform & transform = this->usedTransform;
00099 try {
00100 this->transformListener->lookupTransform(this->name, this->requestFrame,
00101 ros::Time(0), transform);
00102 } catch (tf::TransformException & ex){
00103 ROS_ERROR("%s",ex.what());
00104 }
00105 int rows = this->requestPoints->shape()[0];
00106 int cols = this->requestPoints->shape()[1];
00107 this->positionCache->resize(boost::extents[rows][cols]);
00108 for (int y=0; y < rows; y++) {
00109 for (int x=0; x < cols; x++) {
00110 this->mapPointToInnerCache(y, x, transform);
00111 }
00112 }
00113 }
00114
00115
00116 void RealMonoCamera::mapPointToInnerCache(
00117 int row, int col, tf::StampedTransform & transform) {
00118 tf::Vector3 localPt = transform*(*(this->requestPoints))[row][col];
00119 Point2D & res = (*(this->positionCache))[row][col];
00120 if (localPt[2] > 0) {
00121 this->applyPlumbBobDistortion(localPt);
00122 tf::Vector3 imPt = (this->kMat)*localPt;
00123 if (imPt[0] >= 0 && imPt[0] < this->camInfo->width &&
00124 imPt[1] >= 0 && imPt[1] < this->camInfo->height) {
00125 res.x = static_cast<int>(std::floor(imPt[0]));
00126 res.y = static_cast<int>(std::floor(imPt[1]));
00127 return;
00128 }
00129 }
00130
00131 res.x = NOT_VISIBLE;
00132 res.y = NOT_VISIBLE;
00133 }
00134
00135
00136 void RealMonoCamera::applyPlumbBobDistortion(tf::Vector3 & p) {
00137 float x = p[0]/p[2];
00138 float y = p[1]/p[2];
00139 float r2 = x*x + y*y;
00140 float dx1 = 2*camInfo->D[2]*x*y + camInfo->D[3]*(r2+2*x*x);
00141 float dx2 = camInfo->D[2]*(r2 + 2*y*y) + 2*camInfo->D[3]*x*y;
00142
00143
00144 float rad = 1 + camInfo->D[0]*r2 + camInfo->D[1]*r2*r2;
00145 if (camInfo->D.size() >= 5) {
00146 rad += camInfo->D[4]*r2*r2*r2;
00147 }
00148 if (camInfo->D.size() >= 8) {
00149 rad /= 1 + camInfo->D[5]*r2 + camInfo->D[6]*r2*r2 + camInfo->D[7]*r2*r2*r2;
00150 }
00151 p[0] = rad*x + dx1;
00152 p[1] = rad*y + dx2;
00153 p[2] = 1;
00154 }
00155
00156
00157 bool RealMonoCamera::areTransformsEqual(
00158 const tf::StampedTransform & t1, const tf::StampedTransform & t2) {
00159 const tf::Vector3 & o1 = t1.getOrigin();
00160 const tf::Vector3 & o2 = t2.getOrigin();
00161 if (fabs(o1.getX() - o2.getX()) > 0.000001 ||
00162 fabs(o1.getY() - o2.getY()) > 0.000001 ||
00163 fabs(o1.getZ() - o2.getZ()) > 0.000001) {
00164 return false;
00165 }
00166 const tf::Quaternion & r1 = t1.getRotation();
00167 const tf::Quaternion & r2 = t2.getRotation();
00168
00169 if (fabs(r1.dot(r2)) < 0.999) {
00170 return false;
00171 }
00172 return true;
00173 }
00174
00175
00176 }