Skip to content

Commit 3ce6468

Browse files
committed
switched to async_read for bad performance with multiple vesc
1 parent 153998d commit 3ce6468

File tree

1 file changed

+59
-65
lines changed

1 file changed

+59
-65
lines changed

vesc_driver/src/vesc_interface.cpp

Lines changed: 59 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class VescInterface::Impl
5454
: owned_ctx{new IoContext(2)},
5555
serial_driver_{new drivers::serial_driver::SerialDriver(*owned_ctx)}
5656
{}
57-
void packet_creation_thread();
57+
void receive_callback(const std::vector<uint8_t> & buffer, const size_t & bytes_transferred);
5858
void on_configure();
5959
void connect(const std::string & port);
6060

@@ -78,69 +78,66 @@ class VescInterface::Impl
7878
std::vector<uint8_t> buffer_;
7979
};
8080

81-
void VescInterface::Impl::packet_creation_thread()
81+
void VescInterface::Impl::receive_callback(
82+
const std::vector<uint8_t> & temp_buffer,
83+
const size_t & bytes_transferred
84+
)
8285
{
83-
static auto temp_buffer = Buffer(2048, 0);
84-
while (packet_thread_run_) {
85-
const auto bytes_read = serial_driver_->port()->receive(temp_buffer);
86-
buffer_.reserve(buffer_.size() + temp_buffer.size());
87-
buffer_.insert(buffer_.end(), temp_buffer.begin(), temp_buffer.begin() + bytes_read);
88-
int bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
89-
if (!buffer_.empty()) {
90-
// search buffer for valid packet(s)
91-
auto iter = buffer_.begin();
92-
auto iter_begin = buffer_.begin();
93-
while (iter != buffer_.end()) {
94-
// check if valid start-of-frame character
95-
if (VescFrame::VESC_SOF_VAL_SMALL_FRAME == *iter ||
96-
VescFrame::VESC_SOF_VAL_LARGE_FRAME == *iter)
97-
{
98-
// good start, now attempt to create packet
99-
std::string error;
100-
VescPacketConstPtr packet =
101-
VescPacketFactory::createPacket(iter, buffer_.end(), &bytes_needed, &error);
102-
if (packet) {
103-
// good packet, check if we skipped any data
104-
if (std::distance(iter_begin, iter) > 0) {
105-
std::ostringstream ss;
106-
ss << "Out-of-sync with VESC, unknown data leading valid frame. Discarding " <<
107-
std::distance(iter_begin, iter) << " bytes.";
108-
error_handler_(ss.str());
109-
}
110-
// call packet handler
111-
packet_handler_(packet);
112-
// update state
113-
iter = iter + packet->frame().size();
114-
iter_begin = iter;
115-
// continue to look for another frame in buffer
116-
continue;
117-
} else if (bytes_needed > 0) {
118-
// need more data, break out of while loop
119-
break; // for (iter_sof...
120-
} else {
121-
// else, this was not a packet, move on to next byte
122-
error_handler_(error);
86+
buffer_.reserve(buffer_.size() + bytes_transferred);
87+
buffer_.insert(buffer_.end(), temp_buffer.begin(), temp_buffer.begin() + bytes_transferred);
88+
int bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
89+
if (!buffer_.empty()) {
90+
// search buffer for valid packet(s)
91+
auto iter = buffer_.begin();
92+
auto iter_begin = buffer_.begin();
93+
while (iter != buffer_.end()) {
94+
// check if valid start-of-frame character
95+
if (VescFrame::VESC_SOF_VAL_SMALL_FRAME == *iter ||
96+
VescFrame::VESC_SOF_VAL_LARGE_FRAME == *iter)
97+
{
98+
// good start, now attempt to create packet
99+
std::string error;
100+
VescPacketConstPtr packet =
101+
VescPacketFactory::createPacket(iter, buffer_.end(), &bytes_needed, &error);
102+
if (packet) {
103+
// good packet, check if we skipped any data
104+
if (std::distance(iter_begin, iter) > 0) {
105+
std::ostringstream ss;
106+
ss << "Out-of-sync with VESC, unknown data leading valid frame. Discarding " <<
107+
std::distance(iter_begin, iter) << " bytes.";
108+
error_handler_(ss.str());
123109
}
110+
// call packet handler
111+
packet_handler_(packet);
112+
// update state
113+
iter = iter + packet->frame().size();
114+
iter_begin = iter;
115+
// continue to look for another frame in buffer
116+
continue;
117+
} else if (bytes_needed > 0) {
118+
// need more data, break out of while loop
119+
break; // for (iter_sof...
120+
} else {
121+
// else, this was not a packet, move on to next byte
122+
error_handler_(error);
124123
}
125-
126-
iter++;
127124
}
128125

129-
// if iter is at the end of the buffer, more bytes are needed
130-
if (iter == buffer_.end()) {
131-
bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
132-
}
126+
iter++;
127+
}
133128

134-
// erase "used" buffer
135-
if (std::distance(iter_begin, iter) > 0) {
136-
std::ostringstream ss;
137-
ss << "Out-of-sync with VESC, discarding " << std::distance(iter_begin, iter) << " bytes.";
138-
error_handler_(ss.str());
139-
}
140-
buffer_.erase(buffer_.begin(), iter);
129+
// if iter is at the end of the buffer, more bytes are needed
130+
if (iter == buffer_.end()) {
131+
bytes_needed = VescFrame::VESC_MIN_FRAME_SIZE;
141132
}
142-
// Only attempt to read every 5 ms
143-
std::this_thread::sleep_for(std::chrono::milliseconds(5));
133+
134+
// erase "used" buffer
135+
if (std::distance(iter_begin, iter) > 0) {
136+
std::ostringstream ss;
137+
ss << "Out-of-sync with VESC, discarding " << std::distance(iter_begin, iter) << " bytes.";
138+
error_handler_(ss.str());
139+
}
140+
buffer_.erase(buffer_.begin(), iter);
144141
}
145142
}
146143

@@ -155,9 +152,14 @@ void VescInterface::Impl::connect(const std::string & port)
155152
serial_driver_->init_port(port, *device_config_);
156153
if (!serial_driver_->port()->is_open()) {
157154
serial_driver_->port()->open();
155+
serial_driver_->port()->async_receive(
156+
std::bind(
157+
&VescInterface::Impl::receive_callback, this, std::placeholders::_1,
158+
std::placeholders::_2));
158159
}
159160
}
160161

162+
161163
VescInterface::VescInterface(
162164
const std::string & port,
163165
const PacketHandlerFunction & packet_handler,
@@ -205,12 +207,6 @@ void VescInterface::connect(const std::string & port)
205207
ss << "Failed to open the serial port " << port << " to the VESC. " << e.what();
206208
throw SerialException(ss.str().c_str());
207209
}
208-
209-
// start up a monitoring thread
210-
impl_->packet_thread_run_ = true;
211-
impl_->packet_thread_ = std::unique_ptr<std::thread>(
212-
new std::thread(
213-
&VescInterface::Impl::packet_creation_thread, impl_.get()));
214210
}
215211

216212
void VescInterface::disconnect()
@@ -219,9 +215,7 @@ void VescInterface::disconnect()
219215

220216
if (isConnected()) {
221217
// bring down read thread
222-
impl_->packet_thread_run_ = false;
223218
requestFWVersion();
224-
impl_->packet_thread_->join();
225219
impl_->serial_driver_->port()->close();
226220
}
227221
}

0 commit comments

Comments
 (0)