TelegramS300.h
Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2010
00004  *
00005  * Fraunhofer Institute for Manufacturing Engineering   
00006  * and Automation (IPA)
00007  *
00008  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00009  *
00010  * Project name: care-o-bot
00011  * ROS stack name: cob_driver
00012  * ROS package name: cob_sick_s300
00013  * Description:
00014  *                                                              
00015  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00016  *                      
00017  * Author: Christian Connette, email:christian.connette@ipa.fhg.de
00018  * Supervised by: Christian Connette, email:christian.connette@ipa.fhg.de
00019  *
00020  * Date of creation: Jan 2009
00021  * ToDo:
00022  *
00023  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  *     * Redistributions of source code must retain the above copyright
00029  *       notice, this list of conditions and the following disclaimer.
00030  *     * Redistributions in binary form must reproduce the above copyright
00031  *       notice, this list of conditions and the following disclaimer in the
00032  *       documentation and/or other materials provided with the distribution.
00033  *     * Neither the name of the Fraunhofer Institute for Manufacturing 
00034  *       Engineering and Automation (IPA) nor the names of its
00035  *       contributors may be used to endorse or promote products derived from
00036  *       this software without specific prior written permission.
00037  *
00038  * This program is free software: you can redistribute it and/or modify
00039  * it under the terms of the GNU Lesser General Public License LGPL as 
00040  * published by the Free Software Foundation, either version 3 of the 
00041  * License, or (at your option) any later version.
00042  * 
00043  * This program is distributed in the hope that it will be useful,
00044  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00045  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00046  * GNU Lesser General Public License LGPL for more details.
00047  * 
00048  * You should have received a copy of the GNU Lesser General Public 
00049  * License LGPL along with this program. 
00050  * If not, see <http://www.gnu.org/licenses/>.
00051  *
00052  ****************************************************************/
00053 
00054 #pragma once
00055 
00056 #include <arpa/inet.h>
00057 
00058 class TelegramParser {
00059 
00060         #pragma pack(push,1)
00061         union TELEGRAM_COMMON1 {
00062                 struct {
00063                         uint32_t reply_telegram;
00064                         uint16_t trigger_result;
00065                         uint16_t size;
00066                         uint8_t  coordination_flag;
00067                         uint8_t  device_addresss;
00068                 };
00069                 uint8_t bytes[10];
00070         };
00071         union TELEGRAM_COMMON2 {
00072                 struct {
00073                         uint16_t protocol_version;
00074                         uint16_t status;
00075                         uint32_t scan_number;
00076                         uint16_t telegram_number;
00077                 };
00078                 uint8_t bytes[10];
00079         };
00080         union TELEGRAM_COMMON3 {
00081                 struct {
00082                         uint16_t type;
00083                 };
00084                 uint8_t bytes[2];
00085         };
00086 
00087         union TELEGRAM_DISTANCE {
00088                 struct {
00089                         uint16_t type;
00090                 };
00091                 uint8_t bytes[2];
00092         };
00093 
00094         union TELEGRAM_TAIL {
00095                 struct {
00096                         uint16_t crc;
00097                 };
00098                 uint8_t bytes[2];
00099         };
00100 
00101         union TELEGRAM_S300_DIST_2B {
00102                 struct {
00103                         unsigned distance : 13; //cm
00104                         unsigned bit13 : 1;  //reflector or scanner distorted
00105                         unsigned protective : 1;
00106                         unsigned warn_field : 1;
00107                 };
00108                 uint16_t val16;
00109                 uint8_t bytes[2];
00110         };
00111 
00112         #pragma pack(pop)
00113 
00114         enum TELEGRAM_COMMON_HS {JUNK_SIZE=4};
00115         enum TELEGRAM_COMMON_TYPES {IO=0xAAAA, DISTANCE=0xBBBB, REFLEXION=0xCCCC};
00116         enum TELEGRAM_DIST_SECTOR {_1=0x1111, _2=0x2222, _3=0x3333, _4=0x4444, _5=0x5555};
00117 
00118 
00119         static void ntoh(TELEGRAM_COMMON1 &tc) {
00120                 tc.reply_telegram = ntohl(tc.reply_telegram);
00121                 tc.trigger_result = ntohs(tc.trigger_result);
00122                 tc.size = ntohs(tc.size);
00123         }
00124 
00125         static void ntoh(TELEGRAM_COMMON2 &tc) {
00126                 tc.protocol_version = ntohs(tc.protocol_version);
00127                 tc.status = ntohs(tc.status);
00128                 tc.scan_number = ntohl(tc.scan_number);
00129                 tc.telegram_number = ntohs(tc.telegram_number);
00130         }
00131 
00132         static void ntoh(TELEGRAM_COMMON3 &tc) {
00133                 tc.type = ntohs(tc.type);
00134         }
00135 
00136         static void ntoh(TELEGRAM_DISTANCE &tc) {
00137                 tc.type = ntohs(tc.type);
00138         }
00139 
00140         static void ntoh(TELEGRAM_TAIL &tc) {
00141             //crc calc. is also in network order
00142                 //tc.crc = ntohs(tc.crc);
00143         }
00144 
00145         static void print(const TELEGRAM_COMMON1 &tc) {
00146                 std::cout<<"HEADER"<<std::dec<<std::endl;
00147                 std::cout<<"reply_telegram"<<":"<<tc.reply_telegram<<std::endl;
00148                 std::cout<<"trigger_result"<<":"<<tc.trigger_result<<std::endl;
00149                 std::cout<<"size"<<":"<<2*tc.size<<std::endl;
00150                 std::cout<<"coordination_flag"<<":"<< std::hex<<tc.coordination_flag<<std::endl;
00151                 std::cout<<"device_addresss"<<":"<< std::hex<<(int)tc.device_addresss<<std::endl;
00152         }
00153 
00154         static void print(const TELEGRAM_COMMON2 &tc) {
00155                 std::cout<<"protocol_version"<<":"<< std::hex<<tc.protocol_version<<std::endl;
00156                 std::cout<<"status"<<":"<<tc.status<<std::endl;
00157                 std::cout<<"scan_number"<<":"<< std::hex<<tc.scan_number<<std::endl;
00158                 std::cout<<"telegram_number"<<":"<< std::hex<<tc.telegram_number<<std::endl;
00159         }
00160 
00161         static void print(const TELEGRAM_COMMON3 &tc) {
00162                 std::cout<<"type"<<":"<< std::hex<<tc.type<<std::endl;
00163                 switch(tc.type) {
00164                         case IO: std::cout<<"type"<<": "<<"IO"<<std::endl; break;
00165                         case DISTANCE: std::cout<<"type"<<": "<<"DISTANCE"<<std::endl; break;
00166                         case REFLEXION: std::cout<<"type"<<": "<<"REFLEXION"<<std::endl; break;
00167                         default: std::cout<<"type"<<": "<<"unknown "<<tc.type<<std::endl; break;
00168                 }
00169                 std::cout<<std::dec<<std::endl;
00170         }
00171 
00172         static void print(const TELEGRAM_DISTANCE &tc) {
00173                 std::cout<<"DISTANCE"<<std::endl;
00174                 std::cout<<"type"<<":"<< std::hex<<tc.type<<std::endl;
00175                 switch(tc.type) {
00176                         case _1: std::cout<<"field 1"<<std::endl; break;
00177                         case _2: std::cout<<"field 2"<<std::endl; break;
00178                         case _3: std::cout<<"field 3"<<std::endl; break;
00179                         case _4: std::cout<<"field 4"<<std::endl; break;
00180                         case _5: std::cout<<"field 5"<<std::endl; break;
00181                         default: std::cout<<"unknown "<<tc.type<<std::endl; break;
00182                 }
00183                 std::cout<<std::dec<<std::endl;
00184         }
00185 
00186         static void print(const TELEGRAM_TAIL &tc) {
00187                 std::cout<<"TAIL"<<std::endl;
00188                 std::cout<<"crc"<<":"<< std::hex<<tc.crc<<std::endl;
00189                 std::cout<<std::dec<<std::endl;
00190         }
00191 
00192         //-------------------------------------------
00193         static unsigned int createCRC(uint8_t *ptrData, int Size);
00194 
00195         //supports versions: 0301, 0201
00196         static bool check(const TELEGRAM_COMMON1 &tc, const uint8_t DEVICE_ADDR) {
00197                 uint8_t TELEGRAM_COMMON_PATTERN_EQ[] = {0,0,0,0, 0,0, 0,0, 0xFF, 0&DEVICE_ADDR/*version, 2, 1*/};
00198                 uint8_t TELEGRAM_COMMON_PATTERN_OR[] = {0,0,0,0, 0,0, 0xff,0xff, 0,0xff/*version, 1, 0*/};
00199 
00200                 for(size_t i=0; i<sizeof(TELEGRAM_COMMON_PATTERN_EQ); i++) {
00201                         if(TELEGRAM_COMMON_PATTERN_EQ[i] != (tc.bytes[i]&(~TELEGRAM_COMMON_PATTERN_OR[i])) ) {
00202                                 //std::cout<<"invalid at byte "<<i<<std::endl;
00203                                 return false;
00204                         }
00205                 }
00206 
00207                 return true;
00208         }
00209 
00210         TELEGRAM_COMMON1 tc1_;
00211         TELEGRAM_COMMON2 tc2_;
00212         TELEGRAM_COMMON3 tc3_;
00213         TELEGRAM_DISTANCE td_;
00214         int last_offset_;
00215 public:
00216 
00217         TelegramParser() : last_offset_(0) {}
00218 
00219         bool parseHeader(const unsigned char *buffer, const size_t max_size, const uint8_t DEVICE_ADDR, const bool debug)
00220         {
00221                 if(sizeof(tc1_)>max_size) return false;
00222                 tc1_ = *((TELEGRAM_COMMON1*)buffer);
00223 
00224                 if(!check(tc1_, DEVICE_ADDR)) {
00225                         //if(debug) std::cout<<"basic check failed"<<std::endl;
00226                         return false;
00227                 }
00228 
00229                 ntoh(tc1_);
00230                 if(debug) print(tc1_);
00231 
00232                 if(tc1_.size*2+JUNK_SIZE>(int)max_size) {
00233                         if(debug) std::cout<<"invalid header size"<<std::endl;
00234                         return false;
00235                 }
00236 
00237                 tc2_ = *((TELEGRAM_COMMON2*)(buffer+sizeof(TELEGRAM_COMMON1)));
00238                 tc3_ = *((TELEGRAM_COMMON3*)(buffer+(sizeof(TELEGRAM_COMMON1)+sizeof(TELEGRAM_COMMON2))));
00239 
00240                 TELEGRAM_TAIL tt;
00241                 uint16_t crc;
00242 
00243                 if(tc2_.protocol_version==0x102)
00244                         last_offset_ = -10;
00245                 tt = *((TELEGRAM_TAIL*) (buffer+(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)) );
00246                 ntoh(tt);
00247                 crc = createCRC((uint8_t*)buffer+JUNK_SIZE, 2*tc1_.size-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_);
00248                 
00249                 if(tc2_.protocol_version!=0x102) {
00250                         if(tt.crc!=crc) {
00251                                 last_offset_ = 0;
00252                                 if(debug) std::cout<<"CRC failed!\ntrying offset of "<<std::dec<<last_offset_<<std::endl;
00253                                 tt = *((TELEGRAM_TAIL*) (buffer+(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)) );
00254                                 ntoh(tt);
00255                                 crc = createCRC((uint8_t*)buffer+JUNK_SIZE, 2*tc1_.size-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_);
00256                         }
00257 
00258                         if(tt.crc!=crc) {
00259                                 last_offset_ = -6;
00260                                 if(debug) std::cout<<"CRC failed!\ntrying offset of "<<std::dec<<last_offset_<<std::endl;
00261                                 tt = *((TELEGRAM_TAIL*) (buffer+(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)) );
00262                                 ntoh(tt);
00263                                 crc = createCRC((uint8_t*)buffer+JUNK_SIZE, 2*tc1_.size-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_);
00264                         }
00265                 }
00266 
00267                 if(tt.crc!=crc) {
00268                         if(debug) {
00269                                 print(tc2_);
00270                                 print(tc3_);
00271                                 print(tt);
00272                                 std::cout<<"at "<<std::hex<<(2*tc1_.size+JUNK_SIZE-sizeof(TELEGRAM_TAIL)+sizeof(TELEGRAM_COMMON2)+last_offset_)<<std::endl;
00273                                 std::cout<<"invalid CRC: "<<crc<<" ("<<tt.crc<<")"<<std::endl;
00274                         }
00275                         return false;
00276                 }
00277 
00278                 memset(&td_, 0, sizeof(td_));
00279                 switch(tc3_.type) {
00280                         case IO: break;
00281 
00282                         case DISTANCE:
00283                                 if(debug) std::cout<<"got distance"<<std::endl;
00284 
00285                                 td_ = *((TELEGRAM_DISTANCE*)(buffer+sizeof(tc1_)+sizeof(tc2_)+sizeof(tc3_)));
00286                                 ntoh(td_);
00287                                 //print(td_);
00288                                 break;
00289 
00290                         case REFLEXION: break;
00291                         default: return false;
00292                 }
00293 
00294                 return true;
00295         }
00296 
00297         bool isDist() const {return tc3_.type==DISTANCE;}
00298         int getField() const {
00299                 switch(td_.type) {
00300                         case _1: return 1;
00301                         case _2: return 2;
00302                         case _3: return 3;
00303                         case _4: return 4;
00304                         case _5: return 5;
00305                         default: return -1;
00306                 }
00307         }
00308 
00309         int getCompletePacketSize() const {
00310                 return 2*tc1_.size + sizeof(tc1_) + JUNK_SIZE + last_offset_;
00311         }
00312 
00313         void readDistRaw(const unsigned char *buffer, std::vector<int> &res) const
00314         {
00315                 res.clear();
00316                 if(!isDist()) return;
00317 
00318                 size_t num_points = (2*tc1_.size - (sizeof(tc1_)+sizeof(tc2_)+sizeof(tc3_)+sizeof(td_)+sizeof(TELEGRAM_TAIL)-JUNK_SIZE-last_offset_));
00319                 //std::cout<<"num_points: "<<std::dec<<num_points/sizeof(TELEGRAM_S300_DIST_2B)<<"  "<<num_points<<" "<<tc1_.size<<std::endl;
00320                 size_t i=0;
00321                 for(; i<num_points; ) {
00322                         TELEGRAM_S300_DIST_2B dist = *((TELEGRAM_S300_DIST_2B*) (buffer+(sizeof(tc1_)+sizeof(tc2_)+sizeof(tc3_)+sizeof(td_)+i)) );
00323                         //for distance only: res.push_back((int)dist.distance);
00324                         res.push_back((int)dist.val16);
00325                         i += sizeof(TELEGRAM_S300_DIST_2B);
00326                 }
00327         }
00328 
00329 };


cob_sick_s300
Author(s): Florian Weisshardt
autogenerated on Thu Aug 27 2015 12:45:42