Regilo
A simple C++ library for controlling the Neato XV robot and the Hokuyo scanner.
hokuyocontroller.hpp
1 /*
2  * Regilo
3  * Copyright (C) 2015-2016 Branislav HolĂ˝ <branoholy@gmail.com>
4  *
5  * This file is part of Regilo.
6  *
7  * Regilo is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Regilo is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Regilo. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef REGILO_HOKUYOCONTROLLER_HPP
23 #define REGILO_HOKUYOCONTROLLER_HPP
24 
25 #include <cmath>
26 #include <map>
27 
28 #include <boost/algorithm/string/trim.hpp>
29 
30 #include "scancontroller.hpp"
31 #include "serialcontroller.hpp"
32 #include "socketcontroller.hpp"
33 
34 namespace regilo {
35 
39 class IHokuyoController : public virtual IScanController
40 {
41 public:
45  virtual ~IHokuyoController() = default;
46 
51  virtual std::map<std::string, std::string> getVersionInfo() = 0;
52 };
53 
57 template<typename ProtocolController>
58 class HokuyoController : public IHokuyoController, public ScanController<ProtocolController>
59 {
60 private:
61  std::size_t validFromStep = 44;
62  std::size_t validToStep = 725;
63  std::size_t maxStep = 768;
64  std::size_t fromStep = 0;
65  std::size_t toStep = maxStep;
66  std::size_t clusterCount = 1;
67  double startAngle = -135 * M_PI / 180;
68 
69 protected:
70  virtual inline std::string getScanCommand() const override { return this->createFormattedCommand(CMD_GET_SCAN, fromStep, toStep, clusterCount); }
71  virtual bool parseScanData(std::istream& in, ScanData& data) override;
72 
73 public:
74  static std::string CMD_GET_VERSION;
75  static std::string CMD_GET_SCAN;
76 
81 
86  HokuyoController(const std::string& logPath);
87 
92  HokuyoController(std::iostream& logStream);
93 
97  virtual ~HokuyoController() = default;
98 
99  virtual std::map<std::string, std::string> getVersionInfo() override;
100 
107  void setScanParameters(std::size_t fromStep, std::size_t toStep, std::size_t clusterCount);
108 };
109 
110 extern template class HokuyoController<SerialController>;
111 extern template class HokuyoController<SocketController>;
112 
115 
116 template<typename ProtocolController>
118 
119 template<typename ProtocolController>
120 std::string HokuyoController<ProtocolController>::CMD_GET_SCAN = "G%03d%03d%02d";
121 
122 template<typename ProtocolController>
124 {
125  this->RESPONSE_END = "\n\n";
126 }
127 
128 template<typename ProtocolController>
129 HokuyoController<ProtocolController>::HokuyoController(const std::string& logPath) : ScanController<ProtocolController>(logPath)
130 {
131  this->RESPONSE_END = "\n\n";
132 }
133 
134 template<typename ProtocolController>
135 HokuyoController<ProtocolController>::HokuyoController(std::iostream& logStream) : ScanController<ProtocolController>(logStream)
136 {
137  this->RESPONSE_END = "\n\n";
138 }
139 
140 template<typename ProtocolController>
141 std::map<std::string, std::string> HokuyoController<ProtocolController>::getVersionInfo()
142 {
143  std::map<std::string, std::string> versionInfo;
144 
145  if(ProtocolController::template sendCommand<char>(CMD_GET_VERSION) == '0')
146  {
147  std::string line;
148  while(std::getline(this->deviceOutput, line))
149  {
150  if(line.empty()) continue;
151 
152  std::size_t colonPos = line.find(':');
153  std::string name = line.substr(0, colonPos);
154  std::string value = line.substr(colonPos + 1);
155 
156  boost::algorithm::trim(name);
157  boost::algorithm::trim(value);
158 
159  versionInfo[name] = value;
160  }
161  }
162 
163  return versionInfo;
164 }
165 
166 template<typename ProtocolController>
167 void HokuyoController<ProtocolController>::setScanParameters(std::size_t fromStep, std::size_t toStep, std::size_t clusterCount)
168 {
169  if(fromStep > maxStep) throw std::invalid_argument("Invalid fromStep argument.");
170  if(toStep > maxStep) throw std::invalid_argument("Invalid fromStep argument.");
171  if(clusterCount > 99) throw std::invalid_argument("Invalid clusterCount argument.");
172  if(fromStep > toStep) throw std::invalid_argument("fromStep has to be lower than toStep.");
173 
174  this->fromStep = fromStep;
175  this->toStep = toStep;
176  this->clusterCount = clusterCount;
177 }
178 
179 template<typename ProtocolController>
181 {
182  char status;
183  in >> status;
184  if(status != '0') return false;
185 
186  double resolution = M_PI / 512;
187 
188  int lastId = 0;
189  std::size_t step = fromStep - 1;
190  while(in)
191  {
192  step++;
193 
194  char high, low;
195  in >> high >> low;
196 
197  if(step < validFromStep || step > validToStep) continue;
198 
199  int id = lastId++;
200  double angle = step * resolution + startAngle;
201  int distance = ((high - '0') << 6) | (low - '0');
202  int errorCode = 0;
203  bool error = false;
204 
205  if(distance < 20)
206  {
207  errorCode = distance;
208  distance = -1;
209  error = true;
210  }
211 
212  data.emplace_back(id, angle, distance, -1, errorCode, error);
213  }
214 
215  return true;
216 }
217 
218 }
219 
220 #endif // REGILO_HOKUYOCONTROLLER_HPP
Definition: controller.hpp:35
The IScanController interface is used for all controller classes that implement scanning functionalit...
Definition: scancontroller.hpp:34
static std::string CMD_GET_SCAN
A command for getting a scan.
Definition: hokuyocontroller.hpp:75
static std::string CMD_GET_VERSION
A command for getting the scanner version.
Definition: hokuyocontroller.hpp:74
The IHokuyoController interface is used for the HokuyoController class.
Definition: hokuyocontroller.hpp:39
virtual std::map< std::string, std::string > getVersionInfo() override
Return information about the scanner version.
Definition: hokuyocontroller.hpp:141
virtual bool parseScanData(std::istream &in, ScanData &data) override
Parse the raw scan data.
Definition: hokuyocontroller.hpp:180
The HokuyoController class is used to communicate with the Hokuyo scanner.
Definition: hokuyocontroller.hpp:58
The ScanController class implements parsing of scanned laser data.
Definition: scancontroller.hpp:54
HokuyoController()
Default constructor.
Definition: hokuyocontroller.hpp:123
virtual std::string getScanCommand() const override
Get a string that can be used for getting a scan.
Definition: hokuyocontroller.hpp:70
The ScanData class is used to store laser data.
Definition: scandata.hpp:34
virtual std::map< std::string, std::string > getVersionInfo()=0
Return information about the scanner version.
virtual ~IHokuyoController()=default
Default destructor.
void setScanParameters(std::size_t fromStep, std::size_t toStep, std::size_t clusterCount)
Set parameters for the scan command.
Definition: hokuyocontroller.hpp:167