serial.cpp
Go to the documentation of this file.
1 #include <iostream>
2 
3 #include "create/serial.h"
4 #include "create/types.h"
5 
6 namespace create {
7 
8  Serial::Serial(boost::shared_ptr<Data> d) :
9  data(d),
10  port(io),
11  isReading(false),
12  dataReady(false),
13  corruptPackets(0),
14  totalPackets(0) {
15  }
16 
18  disconnect();
19  }
20 
21  bool Serial::connect(const std::string& portName, const int& baud, boost::function<void()> cb) {
22  using namespace boost::asio;
23  port.open(portName);
24  port.set_option(serial_port::baud_rate(baud));
25  port.set_option(serial_port::flow_control(serial_port::flow_control::none));
26 
27  usleep(1000000);
28 
29  if (port.is_open()) {
30  callback = cb;
31  bool startReadSuccess = startReading();
32  if (!startReadSuccess) {
33  port.close();
34  }
35  return startReadSuccess;
36  }
37  return false;
38  }
39 
41  if (isReading) {
42  stopReading();
43  }
44 
45  if (connected()) {
46  // Ensure not in Safe/Full modes
48  // Stop OI
50  port.close();
51  }
52  }
53 
55  if (!connected()) return false;
56 
57  if (!data) {
58  CERR("[create::Serial] ", "data pointer not initialized.");
59  return false;
60  }
61 
62  // Only allow once
63  if (isReading) return true;
64 
65  // Start OI
67 
68  if (!startSensorStream()) return false;
69 
70  io.reset();
71 
72  // Start continuously reading one byte at a time
73  boost::asio::async_read(port,
74  boost::asio::buffer(&byteRead, 1),
75  boost::bind(&Serial::onData, this, _1, _2));
76 
77  ioThread = boost::thread(boost::bind(&boost::asio::io_service::run, &io));
78 
79  // Wait for first complete read to finish
80  boost::unique_lock<boost::mutex> lock(dataReadyMut);
81 
82  int attempts = 1;
83  int maxAttempts = 10;
84  while (!dataReady) {
85  if (!dataReadyCond.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(500))) {
86  if (attempts >= maxAttempts) {
87  CERR("[create::Serial] ", "failed to receive data from Create. Check if robot is powered!");
88  io.stop();
89  ioThread.join();
90  return false;
91  }
92  attempts++;
93 
94  // Request data again
97  }
98  }
99 
100  isReading = true;
101  return true;
102  }
103 
105  if (isReading) {
106  io.stop();
107  ioThread.join();
108  isReading = false;
109  {
110  boost::lock_guard<boost::mutex> lock(dataReadyMut);
111  dataReady = false;
112  }
113  }
114  }
115 
116 
118  // Validate all packets
119  data->validateAll();
120 
121  // Notify first data packets ready
122  {
123  boost::lock_guard<boost::mutex> lock(dataReadyMut);
124  if (!dataReady) {
125  dataReady = true;
126  dataReadyCond.notify_one();
127  }
128  }
129  // Callback to notify data is ready
130  if (callback)
131  callback();
132  }
133 
134  void Serial::onData(const boost::system::error_code& e, const std::size_t& size) {
135  if (e) {
136  CERR("[create::Serial] ", "serial error - " << e.message());
137  return;
138  }
139 
140  // Should have read exactly one byte
141  if (size == 1) {
143  } // end if (size == 1)
144 
145  // Read the next byte
146  boost::asio::async_read(port,
147  boost::asio::buffer(&byteRead, 1),
148  boost::bind(&Serial::onData, this, _1, _2));
149  }
150 
151  bool Serial::send(const uint8_t* bytes, unsigned int numBytes) {
152  if (!connected()) {
153  CERR("[create::Serial] ", "send failed, not connected.");
154  return false;
155  }
156  // TODO: catch boost exceptions
157  boost::asio::write(port, boost::asio::buffer(bytes, numBytes));
158  return true;
159  }
160 
161  bool Serial::sendOpcode(const Opcode& code) {
162  uint8_t oc = (uint8_t) code;
163  return send(&oc, 1);
164  }
165 
166  uint64_t Serial::getNumCorruptPackets() const {
167  return corruptPackets;
168  }
169 
170  uint64_t Serial::getTotalPackets() const {
171  return totalPackets;
172  }
173 } // namespace create
uint8_t byteRead
Definition: serial.h:62
boost::mutex dataReadyMut
Definition: serial.h:58
uint64_t getTotalPackets() const
Definition: serial.cpp:170
boost::asio::serial_port port
Definition: serial.h:53
bool connected() const
Definition: serial.h:90
virtual void processByte(uint8_t byteRead)=0
bool sendOpcode(const Opcode &code)
Definition: serial.cpp:161
void notifyDataReady()
Definition: serial.cpp:117
boost::shared_ptr< Data > data
Definition: serial.h:74
Opcode
Definition: types.h:154
Definition: create.h:46
Serial(boost::shared_ptr< Data > data)
Definition: serial.cpp:8
uint64_t totalPackets
Definition: serial.h:77
#define CERR(prefix, msg)
Definition: util.h:38
bool startReading()
Definition: serial.cpp:54
void stopReading()
Definition: serial.cpp:104
boost::thread ioThread
Definition: serial.h:56
void disconnect()
Definition: serial.cpp:40
bool connect(const std::string &port, const int &baud=115200, boost::function< void()> cb=0)
Definition: serial.cpp:21
bool send(const uint8_t *bytes, const uint32_t numBytes)
Definition: serial.cpp:151
virtual bool startSensorStream()=0
boost::function< void()> callback
Definition: serial.h:68
bool dataReady
Definition: serial.h:59
boost::condition_variable dataReadyCond
Definition: serial.h:57
void onData(const boost::system::error_code &e, const std::size_t &size)
Definition: serial.cpp:134
boost::asio::io_service io
Definition: serial.h:52
bool isReading
Definition: serial.h:60
uint64_t getNumCorruptPackets() const
Definition: serial.cpp:166
uint64_t corruptPackets
Definition: serial.h:76


libcreate
Author(s): Jacob Perron
autogenerated on Sat Jun 8 2019 17:58:17