data.h
Go to the documentation of this file.
00001 
00041 #include <endian.h>
00042 
00043 #if __BYTE_ORDER == __BIG_ENDIAN
00044 uint64_t swapLong(uint64_t x) {
00045         x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
00046         x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
00047         x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;
00048         return x;
00049 }
00050 
00051 #define __Swap2Bytes(val)   ( (((val) >> 8) & 0x00FF) | (((val) << 8) & 0xFF00) )
00052 #define __Swap2BytesD(val)  (val>7490?0:( (((val) >> 8) & 0x00FF) | (((val) << 8) & 0xFF00) ))
00053 #define __Swap4Bytes(dword) ( ((dword>>24)&0x000000FF) | ((dword>>8)&0x0000FF00) | ((dword<<8)&0x00FF0000) | ((dword<<24)&0xFF000000) )
00054 #define __Swap8Bytes(val) (swapLong(val))
00055 #else
00056 #define __Swap2Bytes(val) (val)
00057 #define __Swap2BytesD(val) (val>7490?0:val)
00058 #define __Swap4Bytes(dword) (dword)
00059 #define __Swap8Bytes(dword) (dword)
00060 #endif
00061 
00062 
00063 /* This class gathers the main camera parameters. */
00064 struct CameraParameters {
00065         uint32_t width, height;
00066         double cam2worldMatrix[4*4];
00067         double fx, fy, cx, cy, k1, k2, f2rc;
00068         
00069     CameraParameters(uint32_t width=176, uint32_t height=144,
00070                  double *cam2worldMatrix=NULL,
00071                  double fx=146.5, double fy=146.5,double cx=84.4,double cy=71.2,
00072                  double k1=0.326442, double k2=0.219623,
00073                  double f2rc=0.0):
00074         width(width), height(height),
00075         fx(fx), fy(fy),
00076         cx(cx), cy(cy),
00077         k1(k1), k2(k2),
00078         f2rc(f2rc)
00079                   {
00080                 if(cam2worldMatrix)
00081                         memcpy(this->cam2worldMatrix, cam2worldMatrix, sizeof(this->cam2worldMatrix));
00082         }
00083 };
00084 
00085 
00086 /* Gathers methods to handle the raw data. */
00087 class Data {
00088     CameraParameters cameraParams_;
00089     cv::Mat distance_, intensity_, confidence_;
00090     int numBytesPerDistanceValue_, numBytesPerIntensityValue_, numBytesPerConfidenceValue_;
00091     uint32_t framenumber_;
00092 public:
00093 
00094     Data() : framenumber_(0) {
00095     }
00096 
00097     const cv::Mat &get_distance() const {return distance_;}
00098     const cv::Mat &get_intensity() const {return intensity_;}
00099     const cv::Mat &get_confidence() const {return confidence_;}
00100     uint32_t get_framenumber() const { return framenumber_; }
00101     
00102     const CameraParameters &getCameraParameters() const {return cameraParams_;}
00103 
00104     /* Get size of complete package. */
00105     static size_t actual_size(const char *data, const size_t size) {
00106         if(size<8) return 0;
00107         // first 11 bytes contain some internal definitions   
00108         const uint32_t pkglength = ntohl( *(uint32_t*)(data+4) );
00109 
00110         return pkglength+9;
00111     }
00112 
00113     /* Check if there are enough data to be parsed. */
00114     static bool check_header(const char *data, const size_t size) {
00115         if(size<11) return false;
00116 
00117         const uint32_t magicword = ntohl( *(uint32_t*)(data+0) );
00118 
00119         //if magic word in invalid we'll read the content anyway to skip data
00120         return magicword != 0x02020202 || size>=actual_size(data, size);
00121     }
00122 
00123     /* Extracts necessary data segments and triggers parsing of segments. */
00124     bool read(const char *data, const size_t size) {
00125         // first 11 bytes contain some internal definitions   
00126                 const uint32_t magicword = ntohl( *(uint32_t*)(data+0) );
00127                 const uint32_t pkglength = ntohl( *(uint32_t*)(data+4) );
00128                 const uint16_t protocolVersion = ntohs( *(uint16_t*)(data+8) );
00129                 const uint8_t packetType = *(uint8_t*)(data+10);
00130                 
00131         ROS_ASSERT( magicword == 0x02020202 );
00132         ROS_ASSERT( protocolVersion == 1 );
00133         ROS_ASSERT( packetType == 98 );
00134         
00135         if( magicword != 0x02020202 || protocolVersion != 1 || packetType != 98 )
00136                         return false;
00137         
00138         // next four bytes an id (should equal 1) and
00139         // the number of segments (should be 3)       
00140                 const uint16_t id = ntohs( *(uint16_t*)(data+11) );
00141                 const uint16_t numSegments = ntohs( *(uint16_t*)(data+13) );
00142         ROS_ASSERT( id == 1 );
00143         ROS_ASSERT( numSegments == 3 );
00144         
00145         // offset and changedCounter, 4 bytes each per segment
00146         uint32_t offset[numSegments];
00147         uint32_t changedCounter[numSegments];
00148         for(size_t i=0; i<(size_t)numSegments; i++) {
00149                         offset[i] = 11 + ntohl( *(uint32_t*)(data+(i*8+15)) );
00150                         changedCounter[i] = ntohl( *(uint32_t*)(data+(i*8+19)) );
00151                 }
00152         
00153         // XML segment describes the data format
00154         std::string xmlSegment(data+offset[0], offset[1]-offset[0]);
00155         
00156         // parsing the XML in order to extract necessary image information
00157         parseXML(xmlSegment);
00158                 
00159         /*self.cameraParams = \
00160                 CameraParameters(width=myXMLParser.imageWidth,
00161                                  height=myXMLParser.imageHeight,
00162                                  cam2worldMatrix=myXMLParser.cam2worldMatrix,
00163                                  fx=myXMLParser.fx,fy=myXMLParser.fy,
00164                                  cx=myXMLParser.cx,cy=myXMLParser.cy,
00165                                  k1=myXMLParser.k1,k2=myXMLParser.k2,
00166                                  f2rc=myXMLParser.f2rc)*/
00167 
00168         // extracting data from the binary segment (distance, intensity
00169         // and confidence).
00170         ROS_ASSERT(numBytesPerDistanceValue_==2);
00171         ROS_ASSERT(numBytesPerIntensityValue_==2);
00172         ROS_ASSERT(numBytesPerConfidenceValue_==2);
00173         
00174         distance_   = cv::Mat(cameraParams_.height, cameraParams_.width, CV_16UC1);
00175         intensity_  = cv::Mat(cameraParams_.height, cameraParams_.width, CV_16UC1);
00176         confidence_ = cv::Mat(cameraParams_.height, cameraParams_.width, CV_16UC1);
00177         
00178         getData(data+offset[1], size-offset[1]);
00179         
00180         return true;
00181         }
00182         
00183 private:
00184     /* Parse method needs the XML segment as string input. */
00185     bool parseXML(const std::string &xmlString) {
00186                 numBytesPerConfidenceValue_ = numBytesPerIntensityValue_ = numBytesPerConfidenceValue_ = -1;
00187                 
00188                 boost::property_tree::ptree pt;
00189                 std::istringstream ss(xmlString);
00190                 try {
00191                         boost::property_tree::xml_parser::read_xml(ss, pt);
00192                 } catch(...) {
00193                         ROS_ERROR("failed to parse response (XML malformed)\ncontent: %s", xmlString.c_str());
00194                         return false;
00195                 }
00196                 
00197                 boost::property_tree::ptree ds = pt.get_child("SickRecord.DataSets.DataSetDepthMap.FormatDescriptionDepthMap.DataStream");
00198                 cameraParams_.width = ds.get<uint32_t>("Width");
00199                 cameraParams_.height = ds.get<uint32_t>("Height");
00200                 
00201                 int i=0;
00202                 BOOST_FOREACH(const boost::property_tree::ptree::value_type &item, ds.get_child("CameraToWorldTransform")) {
00203                         if(i<16)
00204                                 cameraParams_.cam2worldMatrix[i] = item.second.get_value<double>();
00205                         ++i;
00206                 }
00207                 ROS_ASSERT(i==16);
00208                 
00209                 cameraParams_.fx = ds.get<double>("CameraMatrix.FX");
00210                 cameraParams_.fy = ds.get<double>("CameraMatrix.FY");
00211                 cameraParams_.cx = ds.get<double>("CameraMatrix.CX");
00212                 cameraParams_.cy = ds.get<double>("CameraMatrix.CY");
00213                 
00214                 cameraParams_.k1 = ds.get<double>("CameraDistortionParams.K1");
00215                 cameraParams_.k2 = ds.get<double>("CameraDistortionParams.K2");
00216                 
00217                 cameraParams_.f2rc = ds.get<double>("FocalToRayCross");
00218         
00219         // extract data format from XML (although it does not change)
00220         std::string data_type;
00221         
00222         data_type=ds.get<std::string>("Distance", "");
00223         boost::algorithm::to_lower(data_type);
00224         if(data_type != "") {
00225             ROS_ASSERT(data_type == "uint16");
00226             numBytesPerDistanceValue_ = 2;
00227         }
00228         
00229         data_type=ds.get<std::string>("Intensity", "");
00230         boost::algorithm::to_lower(data_type);
00231         if(data_type != "") {
00232             ROS_ASSERT(data_type == "uint16");
00233             numBytesPerIntensityValue_ = 2;
00234         }
00235         
00236         data_type=ds.get<std::string>("Confidence", "");
00237         boost::algorithm::to_lower(data_type);
00238         if(data_type != "") {
00239             ROS_ASSERT(data_type == "uint16");
00240             numBytesPerConfidenceValue_ = 2;
00241         }
00242             
00243         return true;
00244         }
00245     
00246     void getData(const char *data, const size_t size) {
00247         ROS_ASSERT(size>=14);
00248         if(size<14) {
00249             ROS_WARN("malformed data (1): %d<14", (int)size);
00250             return;
00251         }
00252         const size_t numBytesDistance   = (numBytesPerDistanceValue_ > 0) ? distance_.total()*numBytesPerDistanceValue_ : 0;
00253         const size_t numBytesIntensity  = (numBytesPerIntensityValue_ > 0) ? intensity_.total()*numBytesPerIntensityValue_ : 0;
00254         const size_t numBytesConfidence = (numBytesPerConfidenceValue_ > 0) ? confidence_.total()*numBytesPerConfidenceValue_ : 0;
00255 
00256         // the binary part starts with entries for length, a timestamp
00257         // and a version identifier
00258         size_t offset = 0;
00259         const uint32_t length = __Swap4Bytes( *(uint32_t*)(data+offset) );
00260         const uint64_t timeStamp = __Swap8Bytes( *(uint64_t*)(data+offset+4) );
00261         const uint16_t version = __Swap2Bytes( *(uint16_t*)(data+offset+12) );
00262 
00263         offset += 14; //calcsize('>IQH')
00264 
00265         if(length>size) {
00266             ROS_WARN("malformed data (2): %d>%d", (int)length, (int)size);
00267             return;
00268         }
00269 
00270         if (version > 1) {
00271             // more frame information follows in this case: frame number, data quality, device status ('<IBB')
00272             framenumber_ = ntohl( *(uint32_t*)(data+offset) );
00273             const uint8_t dataQuality = *(uint8_t*)(data+offset+4);
00274             const uint8_t deviceStatus = *(uint8_t*)(data+offset+5);
00275             offset += 6;
00276         } else {
00277             ++framenumber_;
00278         }
00279 
00280         size_t end = offset + numBytesDistance + numBytesIntensity + numBytesConfidence; // calculating the end index
00281         //wholeBinary = binarySegment[start:end] // whole data block
00282         //distance = wholeBinary[0:numBytesDistance] // only the distance
00283                                                    // data (as string)
00284 
00285         ROS_ASSERT(end<=size);
00286 
00287         if (numBytesDistance > 0) {
00288             for(size_t i=0; i<distance_.total(); i++)
00289                 distance_.at<uint16_t>(i) = __Swap2BytesD( *(uint16_t*)(data+offset+i*2) );
00290             offset += numBytesDistance;
00291         }
00292         else {
00293             distance_.setTo(0);
00294         }
00295         if (numBytesIntensity > 0) {
00296             for(size_t i=0; i<intensity_.total(); i++)
00297                 intensity_.at<uint16_t>(i) = __Swap2Bytes( *(uint16_t*)(data+offset+i*2) );
00298             offset += numBytesIntensity;
00299         }
00300         else {
00301             intensity_.setTo(std::numeric_limits<uint16_t>::max()/2);
00302         }
00303         if (numBytesConfidence > 0) {
00304             for(size_t i=0; i<confidence_.total(); i++)
00305                 confidence_.at<uint16_t>(i) = __Swap2Bytes( *(uint16_t*)(data+offset+i*2) );
00306             offset += numBytesConfidence;
00307         }
00308         else {
00309             confidence_.setTo(std::numeric_limits<uint16_t>::max());
00310         }
00311 
00312         // data end with a 32byte (unused) CRC field and a copy of the length byte
00313         const uint32_t unusedCrc = __Swap4Bytes( *(uint32_t*)(data+offset) );
00314         const uint32_t lengthCopy = __Swap4Bytes( *(uint32_t*)(data+offset + 4) );
00315 
00316         if(length != lengthCopy)
00317             ROS_WARN("check failed %d!=%d", (int)length, (int)lengthCopy);
00318         ROS_ASSERT(length == lengthCopy);
00319     }
00320 
00321 };
00322 
00323 #undef __Swap2Bytes


sick_visionary_t_driver
Author(s): Joshua Hampp
autogenerated on Sat Jun 8 2019 19:04:06