stream.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2018 The urg_stamped Authors
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef SCIP2_RESPONSE_STREAM_H
00018 #define SCIP2_RESPONSE_STREAM_H
00019 
00020 #include <boost/asio.hpp>
00021 
00022 #include <map>
00023 #include <string>
00024 #include <vector>
00025 
00026 #include <scip2/decode.h>
00027 #include <scip2/response/abstract.h>
00028 
00029 namespace scip2
00030 {
00031 class ScanData
00032 {
00033 public:
00034   uint32_t timestamp_;
00035   std::vector<int32_t> ranges_;
00036   std::vector<int32_t> intensities_;
00037 };
00038 
00039 class ResponseStream : public Response
00040 {
00041 public:
00042   using Callback = boost::function<void(
00043       const boost::posix_time::ptime &,
00044       const std::string &,
00045       const std::string &,
00046       const ScanData &)>;
00047 
00048 protected:
00049   Callback cb_;
00050 
00051 public:
00052   virtual std::string getCommandCode() const = 0;
00053   virtual void operator()(
00054       const boost::posix_time::ptime &,
00055       const std::string &,
00056       const std::string &,
00057       std::istream &) = 0;
00058 
00059   bool readTimestamp(
00060       const boost::posix_time::ptime &time_read,
00061       const std::string &echo_back,
00062       const std::string &status,
00063       std::istream &stream,
00064       ScanData &scan)
00065   {
00066     if (status == "00")
00067     {
00068       return false;
00069     }
00070     if (status != "99")
00071     {
00072       if (cb_)
00073         cb_(time_read, echo_back, status, scan);
00074       std::cout << echo_back << " errored with " << status << std::endl;
00075       return false;
00076     }
00077     std::string stamp;
00078     if (!std::getline(stream, stamp))
00079     {
00080       std::cerr << "Failed to get timestamp" << std::endl;
00081       return false;
00082     }
00083     const uint8_t checksum = stamp.back();
00084     stamp.pop_back();  // remove checksum
00085     if (stamp.size() < 4)
00086     {
00087       std::cerr << "Wrong timestamp format" << std::endl;
00088       return false;
00089     }
00090 
00091     auto dec = Decoder<4>(stamp);
00092     auto it = dec.begin();
00093     scan.timestamp_ = *it;
00094     if ((dec.getChecksum() & 0x3F) + 0x30 != checksum)
00095     {
00096       std::cerr << "Checksum mismatch" << std::endl;
00097       return false;
00098     }
00099     return true;
00100   }
00101   void registerCallback(Callback cb)
00102   {
00103     cb_ = cb;
00104   }
00105 };
00106 
00107 class ResponseMD : public ResponseStream
00108 {
00109 public:
00110   std::string getCommandCode() const
00111   {
00112     return std::string("MD");
00113   }
00114   void operator()(
00115       const boost::posix_time::ptime &time_read,
00116       const std::string &echo_back,
00117       const std::string &status,
00118       std::istream &stream) override
00119   {
00120     ScanData scan;
00121     if (!readTimestamp(time_read, echo_back, status, stream, scan))
00122       return;
00123     scan.ranges_.reserve(512);
00124 
00125     std::string line;
00126     scip2::DecoderRemain remain;
00127     while (std::getline(stream, line))
00128     {
00129       if (line.size() == 0)
00130         break;
00131 
00132       const uint8_t checksum = line.back();
00133       line.pop_back();  // remove checksum
00134       if (line.size() < 3)
00135       {
00136         std::cerr << "Wrong stream format" << std::endl;
00137         return;
00138       }
00139       auto dec = Decoder<3>(line, remain);
00140       auto it = dec.begin();
00141       for (; it != dec.end(); ++it)
00142       {
00143         scan.ranges_.push_back(*it);
00144       }
00145       remain = it.getRemain();
00146       if ((dec.getChecksum() & 0x3F) + 0x30 != checksum)
00147       {
00148         std::cerr << "Checksum mismatch; scan dropped" << std::endl
00149                   << line << std::endl;
00150         return;
00151       }
00152     }
00153     if (cb_)
00154       cb_(time_read, echo_back, status, scan);
00155   }
00156 };
00157 
00158 class ResponseME : public ResponseStream
00159 {
00160 public:
00161   std::string getCommandCode() const
00162   {
00163     return std::string("ME");
00164   }
00165   void operator()(
00166       const boost::posix_time::ptime &time_read,
00167       const std::string &echo_back,
00168       const std::string &status,
00169       std::istream &stream) override
00170   {
00171     ScanData scan;
00172     if (!readTimestamp(time_read, echo_back, status, stream, scan))
00173       return;
00174     scan.ranges_.reserve(512);
00175     scan.intensities_.reserve(512);
00176 
00177     std::string line;
00178     scip2::DecoderRemain remain;
00179     while (std::getline(stream, line))
00180     {
00181       if (line.size() == 0)
00182         break;
00183 
00184       const uint8_t checksum = line.back();
00185       line.pop_back();  // remove checksum
00186       if (line.size() < 3)
00187       {
00188         std::cerr << "Wrong stream format" << std::endl;
00189         return;
00190       }
00191       auto dec = Decoder<6>(line, remain);
00192       auto it = dec.begin();
00193       for (; it != dec.end(); ++it)
00194       {
00195         scan.ranges_.push_back((*it) >> 18);
00196         scan.intensities_.push_back((*it) & 0x3FFFF);
00197       }
00198       remain = it.getRemain();
00199       if ((dec.getChecksum() & 0x3F) + 0x30 != checksum)
00200       {
00201         std::cerr << "Checksum mismatch; scan dropped" << std::endl
00202                   << line << std::endl;
00203         return;
00204       }
00205     }
00206     if (cb_)
00207       cb_(time_read, echo_back, status, scan);
00208   }
00209 };
00210 
00211 }  // namespace scip2
00212 
00213 #endif  // SCIP2_RESPONSE_STREAM_H


urg_stamped
Author(s): Atsushi Watanabe
autogenerated on Thu Jun 6 2019 18:59:51