vesc_interface.cpp
Go to the documentation of this file.
1 // Copyright 2020 F1TENTH Foundation
2 //
3 // Redistribution and use in source and binary forms, with or without modification, are permitted
4 // provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice, this list of conditions
7 // and the following disclaimer.
8 //
9 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
10 // of conditions and the following disclaimer in the documentation and/or other materials
11 // provided with the distribution.
12 //
13 // 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 // to endorse or promote products derived from this software without specific prior
15 // written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
18 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
24 // WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 // -*- mode:c++; fill-column: 100; -*-
27 
29 
30 #include <pthread.h>
31 
32 #include <algorithm>
33 #include <cassert>
34 #include <iomanip>
35 #include <iostream>
36 #include <sstream>
37 #include <string>
38 #include <thread>
39 
40 #include <serial/serial.h>
41 
43 
44 namespace vesc_driver
45 {
46 
48 {
49 public:
50  Impl() :
51  serial_(std::string(), 115200, serial::Timeout::simpleTimeout(100),
53  {}
54 
55  void rxThread();
56 
57  std::thread rxThreadHelper()
58  {
59  return std::thread(&Impl::rxThread, this);
60  }
61 
62  std::thread rx_thread_;
67 };
68 
70 {
71  Buffer buffer;
72  buffer.reserve(4096);
73 
74  while (rx_thread_run_)
75  {
76  int bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
77  if (!buffer.empty())
78  {
79  // search buffer for valid packet(s)
80  Buffer::iterator iter(buffer.begin());
81  Buffer::iterator iter_begin(buffer.begin());
82  while (iter != buffer.end())
83  {
84  // check if valid start-of-frame character
87  {
88  // good start, now attempt to create packet
89  std::string error;
90  VescPacketConstPtr packet =
91  VescPacketFactory::createPacket(iter, buffer.end(), &bytes_needed, &error);
92  if (packet)
93  {
94  // good packet, check if we skipped any data
95  if (std::distance(iter_begin, iter) > 0)
96  {
97  std::ostringstream ss;
98  ss << "Out-of-sync with VESC, unknown data leading valid frame. Discarding "
99  << std::distance(iter_begin, iter) << " bytes.";
100  error_handler_(ss.str());
101  }
102  // call packet handler
103  packet_handler_(packet);
104  // update state
105  iter = iter + packet->frame().size();
106  iter_begin = iter;
107  // continue to look for another frame in buffer
108  continue;
109  }
110  else if (bytes_needed > 0)
111  {
112  // need more data, break out of while loop
113  break; // for (iter_sof...
114  }
115  else
116  {
117  // else, this was not a packet, move on to next byte
118  error_handler_(error);
119  }
120  }
121 
122  iter++;
123  }
124 
125  // if iter is at the end of the buffer, more bytes are needed
126  if (iter == buffer.end())
127  bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
128 
129  // erase "used" buffer
130  if (std::distance(iter_begin, iter) > 0)
131  {
132  std::ostringstream ss;
133  ss << "Out-of-sync with VESC, discarding " << std::distance(iter_begin, iter) << " bytes.";
134  error_handler_(ss.str());
135  }
136  buffer.erase(buffer.begin(), iter);
137  }
138 
139  // attempt to read at least bytes_needed bytes from the serial port
140  int bytes_to_read =
141  std::max(bytes_needed, std::min(4096, static_cast<int>(serial_.available())));
142  int bytes_read = serial_.read(buffer, bytes_to_read);
143  if (bytes_needed > 0 && 0 == bytes_read && !buffer.empty())
144  {
145  error_handler_("Possibly out-of-sync with VESC, read timout in the middle of a frame.");
146  }
147  }
148 }
149 
150 
151 VescInterface::VescInterface(const std::string& port,
152  const PacketHandlerFunction& packet_handler,
153  const ErrorHandlerFunction& error_handler) :
154  impl_(new Impl())
155 {
156  setPacketHandler(packet_handler);
157  setErrorHandler(error_handler);
158  // attempt to conect if the port is specified
159  if (!port.empty())
160  connect(port);
161 }
162 
164 {
165  disconnect();
166 }
167 
169 {
170  // todo - definately need mutex
171  impl_->packet_handler_ = handler;
172 }
173 
175 {
176  // todo - definately need mutex
177  impl_->error_handler_ = handler;
178 }
179 
180 void VescInterface::connect(const std::string& port)
181 {
182  // todo - mutex?
183 
184  if (isConnected())
185  {
186  throw SerialException("Already connected to serial port.");
187  }
188 
189  // connect to serial port
190  try
191  {
192  impl_->serial_.setPort(port);
193  impl_->serial_.open();
194  }
195  catch (const std::exception& e)
196  {
197  std::stringstream ss;
198  ss << "Failed to open the serial port to the VESC. " << e.what();
199  throw SerialException(ss.str().c_str());
200  }
201 
202  // start up a monitoring thread
203  impl_->rx_thread_run_ = true;
204  impl_->rx_thread_ = impl_->rxThreadHelper();
205 }
206 
208 {
209  // todo - mutex?
210 
211  if (isConnected())
212  {
213  // bring down read thread
214  impl_->rx_thread_run_ = false;
215  impl_->rx_thread_.join();
216  impl_->serial_.close();
217  }
218 }
219 
221 {
222  return impl_->serial_.isOpen();
223 }
224 
225 void VescInterface::send(const VescPacket& packet)
226 {
227  size_t written = impl_->serial_.write(packet.frame());
228  if (written != packet.frame().size())
229  {
230  std::stringstream ss;
231  ss << "Wrote " << written << " bytes, expected " << packet.frame().size() << ".";
232  throw SerialException(ss.str().c_str());
233  }
234 }
235 
237 {
239 }
240 
242 {
244 }
245 
246 void VescInterface::setDutyCycle(double duty_cycle)
247 {
248  send(VescPacketSetDuty(duty_cycle));
249 }
250 
251 void VescInterface::setCurrent(double current)
252 {
253  send(VescPacketSetCurrent(current));
254 }
255 
256 void VescInterface::setBrake(double brake)
257 {
259 }
260 
261 void VescInterface::setSpeed(double speed)
262 {
263  send(VescPacketSetRPM(speed));
264 }
265 
266 void VescInterface::setPosition(double position)
267 {
268  send(VescPacketSetPos(position));
269 }
270 
271 void VescInterface::setServo(double servo)
272 {
273  send(VescPacketSetServoPos(servo));
274 }
275 
276 } // namespace vesc_driver
size_t available()
VescInterface(const std::string &port=std::string(), const PacketHandlerFunction &packet_handler=PacketHandlerFunction(), const ErrorHandlerFunction &error_handler=ErrorHandlerFunction())
std::function< void(const VescPacketConstPtr &)> PacketHandlerFunction
PacketHandlerFunction packet_handler_
std::vector< uint8_t > Buffer
Definition: vesc_packet.h:43
void setPosition(double position)
std::unique_ptr< Impl > impl_
std::function< void(const std::string &)> ErrorHandlerFunction
void setDutyCycle(double duty_cycle)
virtual const Buffer & frame() const
Definition: vesc_packet.h:54
void connect(const std::string &port)
parity_none
static VescPacketPtr createPacket(const Buffer::const_iterator &begin, const Buffer::const_iterator &end, int *num_bytes_needed, std::string *what)
static const int VESC_MIN_FRAME_SIZE
Smallest VESC frame size, in bytes.
Definition: vesc_packet.h:61
stopbits_one
void setCurrent(double current)
void setBrake(double brake)
void setServo(double servo)
void send(const VescPacket &packet)
void setSpeed(double speed)
flowcontrol_none
eightbits
size_t read(uint8_t *buffer, size_t size)
std::shared_ptr< VescPacket const > VescPacketConstPtr
Definition: vesc_packet.h:107
static const unsigned int VESC_SOF_VAL_LARGE_FRAME
VESC start of "large" frame value.
Definition: vesc_packet.h:64
void setErrorHandler(const ErrorHandlerFunction &handler)
static const unsigned int VESC_SOF_VAL_SMALL_FRAME
VESC start of "small" frame value.
Definition: vesc_packet.h:63
ErrorHandlerFunction error_handler_
void setPacketHandler(const PacketHandlerFunction &handler)


vesc_driver
Author(s): Michael T. Boulet , Joshua Whitley
autogenerated on Sun Apr 18 2021 02:48:01