Regilo
A simple C++ library for controlling the Neato XV robot and the Hokuyo scanner.
neatocontroller.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_NEATOCONTROLLER_HPP
23 #define REGILO_NEATOCONTROLLER_HPP
24 
25 #include <cmath>
26 
27 #include <boost/algorithm/string.hpp>
28 
29 #include "scancontroller.hpp"
30 #include "serialcontroller.hpp"
31 #include "socketcontroller.hpp"
32 
33 namespace regilo {
34 
38 class INeatoController : public virtual IScanController
39 {
40 public:
44  virtual ~INeatoController() = default;
45 
50  virtual bool getTestMode() const = 0;
51 
56  virtual void setTestMode(bool testMode) = 0;
57 
62  virtual bool getLdsRotation() const = 0;
63 
68  virtual void setLdsRotation(bool ldsRotation) = 0;
69 
76  virtual void setMotor(int left, int right, int speed) = 0;
77 
82  virtual std::string getTime() = 0;
83 };
84 
88 template<typename ProtocolController>
89 class NeatoController : public INeatoController, public ScanController<ProtocolController>
90 {
91 private:
92  bool testMode = false;
93  bool ldsRotation = false;
94 
95 protected:
96  virtual inline std::string getScanCommand() const override { return CMD_GET_LDS_SCAN; }
97  virtual bool parseScanData(std::istream& in, ScanData& data) override;
98 
99 public:
100  static std::string ON;
101  static std::string OFF;
102  static std::string LDS_SCAN_HEADER;
103  static std::string LDS_SCAN_FOOTER;
104 
105  static std::string CMD_TEST_MODE;
106  static std::string CMD_SET_LDS_ROTATION;
107  static std::string CMD_SET_MOTOR;
108  static std::string CMD_GET_TIME;
109  static std::string CMD_GET_LDS_SCAN;
110 
114  NeatoController();
115 
120  NeatoController(const std::string& logPath);
121 
126  NeatoController(std::iostream& logStream);
127 
131  virtual ~NeatoController() = default;
132 
133  virtual inline bool getTestMode() const override { return testMode; }
134 
135  virtual void setTestMode(bool testMode) override;
136 
137  virtual inline bool getLdsRotation() const override { return ldsRotation; }
138 
139  virtual void setLdsRotation(bool ldsRotation) override;
140 
141  virtual void setMotor(int left, int right, int speed) override;
142 
143  virtual std::string getTime() override;
144 };
145 
146 extern template class NeatoController<SerialController>;
147 extern template class NeatoController<SocketController>;
148 
151 
152 template<typename ProtocolController>
153 std::string NeatoController<ProtocolController>::ON = "on";
154 
155 template<typename ProtocolController>
156 std::string NeatoController<ProtocolController>::OFF = "off";
157 
158 template<typename ProtocolController>
159 std::string NeatoController<ProtocolController>::LDS_SCAN_HEADER = "AngleInDegrees,DistInMM,Intensity,ErrorCodeHEX";
160 
161 template<typename ProtocolController>
162 std::string NeatoController<ProtocolController>::LDS_SCAN_FOOTER = "ROTATION_SPEED,";
163 
164 template<typename ProtocolController>
165 std::string NeatoController<ProtocolController>::CMD_TEST_MODE = "testmode %s";
166 
167 template<typename ProtocolController>
168 std::string NeatoController<ProtocolController>::CMD_SET_LDS_ROTATION = "setldsrotation %s";
169 
170 template<typename ProtocolController>
171 std::string NeatoController<ProtocolController>::CMD_SET_MOTOR = "setmotor %d %d %d";
172 
173 template<typename ProtocolController>
175 
176 template<typename ProtocolController>
178 
179 template<typename ProtocolController>
181 {
182  this->RESPONSE_END = std::string(1, 0x1a);
183 }
184 
185 template<typename ProtocolController>
186 NeatoController<ProtocolController>::NeatoController(const std::string& logPath) : ScanController<ProtocolController>(logPath)
187 {
188  this->RESPONSE_END = std::string(1, 0x1a);
189 }
190 
191 template<typename ProtocolController>
192 NeatoController<ProtocolController>::NeatoController(std::iostream& logStream) : ScanController<ProtocolController>(logStream)
193 {
194  this->RESPONSE_END = std::string(1, 0x1a);
195 }
196 
197 template<typename ProtocolController>
199 {
200  this->sendFormattedCommand(CMD_TEST_MODE, (testMode ? ON : OFF).c_str());
201  this->testMode = testMode;
202 }
203 
204 template<typename ProtocolController>
206 {
207  this->sendFormattedCommand(CMD_SET_LDS_ROTATION, (ldsRotation ? ON : OFF).c_str());
208  this->ldsRotation = ldsRotation;
209 }
210 
211 template<typename ProtocolController>
212 void NeatoController<ProtocolController>::setMotor(int left, int right, int speed)
213 {
214  this->sendFormattedCommand(CMD_SET_MOTOR, left, right, speed);
215 }
216 
217 template<typename ProtocolController>
219 {
220  int lastId = 0;
221  double M_PI_180 = M_PI / 180.0;
222 
223  std::string line;
224  std::getline(in, line);
225  boost::algorithm::trim(line);
226 
227  if(line == NeatoController<ProtocolController>::LDS_SCAN_HEADER)
228  {
229  while(true)
230  {
231  std::getline(in, line);
232  boost::algorithm::trim(line);
233 
234  if(boost::algorithm::starts_with(line, NeatoController<ProtocolController>::LDS_SCAN_FOOTER))
235  {
236  std::vector<std::string> values;
237  boost::algorithm::split(values, line, boost::algorithm::is_any_of(","));
238  data.rotationSpeed = std::stod(values.at(1));
239 
240  break;
241  }
242  else
243  {
244  std::vector<std::string> values;
245  boost::algorithm::split(values, line, boost::algorithm::is_any_of(","));
246 
247  int id = lastId++;
248  double angle = std::stod(values.at(0)) * M_PI_180;
249  double distance = std::stod(values.at(1));
250  int intensity = std::stoi(values.at(2));
251  int errorCode = std::stoi(values.at(3));
252  bool error = (errorCode != 0);
253 
254  if(error) distance = -1;
255 
256  data.emplace_back(id, angle, distance, intensity, errorCode, error);
257  }
258  }
259 
260  return true;
261  }
262 
263  return false;
264 }
265 
266 template<typename ProtocolController>
268 {
269  return this->sendCommand(CMD_GET_TIME);
270 }
271 
272 }
273 
274 #endif // REGILO_NEATOCONTROLLER_HPP
static std::string CMD_SET_LDS_ROTATION
A template for the setldsrotation command.
Definition: neatocontroller.hpp:106
virtual ~INeatoController()=default
Default destructor.
static std::string LDS_SCAN_HEADER
A header of the LDS scan output.
Definition: neatocontroller.hpp:102
static std::string CMD_TEST_MODE
A template for the testmode command.
Definition: neatocontroller.hpp:105
Definition: controller.hpp:35
The IScanController interface is used for all controller classes that implement scanning functionalit...
Definition: scancontroller.hpp:34
virtual std::string getScanCommand() const override
Get a string that can be used for getting a scan.
Definition: neatocontroller.hpp:96
The INeatoController interface is used for the NeatoController class.
Definition: neatocontroller.hpp:38
static std::string CMD_GET_TIME
A template for the gettime command.
Definition: neatocontroller.hpp:108
virtual void setMotor(int left, int right, int speed)=0
Set the specified motor to run in a direction at a requested speed.
static std::string CMD_GET_LDS_SCAN
A template for the getldsscan command.
Definition: neatocontroller.hpp:109
static std::string CMD_SET_MOTOR
A template for the setmotor command.
Definition: neatocontroller.hpp:107
The NeatoController class is used to communicate with the Neato robot.
Definition: neatocontroller.hpp:89
The ScanController class implements parsing of scanned laser data.
Definition: scancontroller.hpp:54
virtual bool parseScanData(std::istream &in, ScanData &data) override
Parse the raw scan data.
Definition: neatocontroller.hpp:218
virtual std::string sendCommand(const std::string &command)=0
Send a command to the device.
virtual std::string getTime()=0
Get the current scheduler time.
static std::string LDS_SCAN_FOOTER
A footer of the LDS scan output.
Definition: neatocontroller.hpp:103
The ScanData class is used to store laser data.
Definition: scandata.hpp:34
virtual void setLdsRotation(bool ldsRotation) override
Set LDS rotation on or off.
Definition: neatocontroller.hpp:205
virtual bool getTestMode() const =0
Get whether the Neato is in the test mode.
double rotationSpeed
The rotation speed (in Hz).
Definition: scandata.hpp:38
virtual void setTestMode(bool testMode) override
Set or unset the test mode.
Definition: neatocontroller.hpp:198
NeatoController()
Default constructor.
Definition: neatocontroller.hpp:180
static std::string OFF
A string that represents the OFF value.
Definition: neatocontroller.hpp:101
virtual std::string getTime() override
Get the current scheduler time.
Definition: neatocontroller.hpp:267
virtual void setTestMode(bool testMode)=0
Set or unset the test mode.
virtual bool getLdsRotation() const =0
Get whether the Neato has LDS rotation on or off.
virtual void setMotor(int left, int right, int speed) override
Set the specified motor to run in a direction at a requested speed.
Definition: neatocontroller.hpp:212
static std::string ON
A string that represents the ON value.
Definition: neatocontroller.hpp:100
virtual void setLdsRotation(bool ldsRotation)=0
Set LDS rotation on or off.
virtual bool getLdsRotation() const override
Get whether the Neato has LDS rotation on or off.
Definition: neatocontroller.hpp:137
virtual bool getTestMode() const override
Get whether the Neato is in the test mode.
Definition: neatocontroller.hpp:133