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
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
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
00105 static size_t actual_size(const char *data, const size_t size) {
00106 if(size<8) return 0;
00107
00108 const uint32_t pkglength = ntohl( *(uint32_t*)(data+4) );
00109
00110 return pkglength+9;
00111 }
00112
00113
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
00120 return magicword != 0x02020202 || size>=actual_size(data, size);
00121 }
00122
00123
00124 bool read(const char *data, const size_t size) {
00125
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
00139
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
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
00154 std::string xmlSegment(data+offset[0], offset[1]-offset[0]);
00155
00156
00157 parseXML(xmlSegment);
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
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
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
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
00257
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;
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
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;
00281
00282
00283
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
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