00001
00025 #include "puma_motor_driver/serial_gateway.h"
00026 #include "ros/ros.h"
00027
00028 namespace puma_motor_driver
00029 {
00030
00031 SerialGateway::SerialGateway(serial::Serial& serial) : serial_(serial),
00032 write_buffer_index_(0), read_buffer_index_(0), read_buffer_len_(0)
00033 {
00034 serial::Timeout to(serial::Timeout::simpleTimeout(50));
00035 serial_.setTimeout(to);
00036 serial_.setBaudrate(115200);
00037 }
00038
00039 bool SerialGateway::connect()
00040 {
00041 if (!serial_.isOpen())
00042 {
00043 try
00044 {
00045 serial_.open();
00046 }
00047 catch (std::exception& e)
00048 {
00049 ROS_ERROR("Exception thrown trying to open %s: %s", serial_.getPort().c_str(), e.what());
00050 return false;
00051 }
00052 return true;
00053 }
00054 return false;
00055 }
00056
00057 bool SerialGateway::isConnected()
00058 {
00059 return serial_.isOpen();
00060 }
00061
00062 void SerialGateway::queue(const Message& msg)
00063 {
00064 ROS_DEBUG_NAMED("serial", "Queuing ID 0x%08x, data (%d)", msg.id, msg.len);
00065
00066 queue('\xff');
00067 queue(4 + msg.len);
00068
00069 encodeAndQueue(reinterpret_cast<uint8_t*>(msg.id), 4);
00070 encodeAndQueue(msg.data, msg.len);
00071 }
00072
00073 bool SerialGateway::recv(Message* msg)
00074 {
00075 int bytes_dropped = 0;
00076
00077
00078 while (1)
00079 {
00080 uint8_t header_byte;
00081 if (!read(&header_byte))
00082 {
00083 ROS_DEBUG_NAMED("serial", "Header byte read timed out. No more messages for now.");
00084 return false;
00085 }
00086
00087 if (header_byte != 0xff)
00088 {
00089 bytes_dropped++;
00090 continue;
00091 }
00092
00093 ROS_WARN_COND_NAMED(bytes_dropped > 0, "serial", "Discarded %d bytes between messages.", bytes_dropped);
00094 break;
00095 }
00096
00097 uint8_t len_byte;
00098 if (!read(&len_byte))
00099 {
00100 ROS_WARN_NAMED("serial", "Len byte read timed out.");
00101 return false;
00102 }
00103 if (len_byte < 4 || len_byte > 12)
00104 {
00105 ROS_WARN_NAMED("serial", "Illegal length byte value, dropping message.");
00106 return false;
00107 }
00108
00109
00110 if (!readAndDecode(reinterpret_cast<uint8_t*>(msg->id), 4))
00111 {
00112 ROS_WARN_NAMED("serial", "Problem reading ID, dropping message.");
00113 return false;
00114 }
00115
00116
00117 msg->len = len_byte - 4;
00118 if (!readAndDecode(msg->data, msg->len))
00119 {
00120 ROS_WARN_NAMED("serial", "Problem reading %d data bytes for ID 0x%08x, dropping message.", msg->len, msg->id);
00121 return false;
00122 }
00123
00124 ROS_DEBUG_NAMED("serial", "Received ID 0x%08x, data (%d)", msg->id, msg->len);
00125 return true;
00126 }
00127
00128 void SerialGateway::queue(uint8_t ch)
00129 {
00130 if (write_buffer_index_ < sizeof(write_buffer_))
00131 {
00132 write_buffer_[write_buffer_index_] = ch;
00133 write_buffer_index_++;
00134 }
00135 }
00136
00137 bool SerialGateway::read(uint8_t* ch)
00138 {
00139
00140 if (read_buffer_index_ >= read_buffer_len_)
00141 {
00142 read_buffer_index_ = 0;
00143 read_buffer_len_ = serial_.read(read_buffer_, sizeof(read_buffer_));
00144 ROS_DEBUG_NAMED("serial", "Filled read buffer with %d bytes.", read_buffer_len_);
00145
00146 if (read_buffer_len_ < 1)
00147 {
00148
00149
00150 return false;
00151 }
00152 }
00153
00154 *ch = read_buffer_[read_buffer_index_];
00155 read_buffer_index_++;
00156 return true;
00157 }
00158
00159 bool SerialGateway::sendAllQueued()
00160 {
00161 try
00162 {
00163 uint8_t written = serial_.write(write_buffer_, write_buffer_index_);
00164
00165 if (written < write_buffer_index_)
00166 {
00167 ROS_WARN_STREAM("Write to serial port timed out. Tried to write " <<
00168 write_buffer_index_ << " bytes, instead wrote only " << written << ". Remainder dropped.");
00169 write_buffer_index_ = 0;
00170 return false;
00171 }
00172 ROS_DEBUG_NAMED("serial", "Wrote %d bytes to serial port.", written);
00173 }
00174 catch (std::exception& e)
00175 {
00176 ROS_ERROR("Exception thrown trying to write to %s: %s", serial_.getPort().c_str(), e.what());
00177 serial_.close();
00178 }
00179
00180 write_buffer_index_ = 0;
00181 return true;
00182 }
00183
00184 void SerialGateway::encodeAndQueue(const uint8_t* data, uint8_t len)
00185 {
00186 for (uint8_t index = 0; index < len; index++)
00187 {
00188 switch (data[index])
00189 {
00190 case 0xff:
00191 queue('\xfe');
00192 queue('\xfe');
00193 break;
00194 case 0xfe:
00195 queue('\xfe');
00196 queue('\xfd');
00197 break;
00198 default:
00199 queue(data[index]);
00200 }
00201 }
00202 }
00203
00204 bool SerialGateway::readAndDecode(uint8_t* data, uint8_t len)
00205 {
00206 for (uint8_t index = 0; index < len; index++)
00207 {
00208 uint8_t undecoded_byte;
00209 if (!read(&undecoded_byte))
00210 {
00211 ROS_WARN_NAMED("serial", "Read of undecoded byte timed out.");
00212 return false;
00213 }
00214
00215 switch (undecoded_byte)
00216 {
00217 case 0xff:
00218 ROS_WARN_NAMED("serial", "Unexpected start-of-message character.");
00219 return false;
00220 case 0xfe:
00221 uint8_t second_byte;
00222 if (!read(&second_byte))
00223 {
00224 ROS_WARN_NAMED("serial", "Read of second byte in decoded pair timed out.");
00225 return false;
00226 }
00227 switch (second_byte)
00228 {
00229 case 0xfe:
00230 data[index] = '\xff';
00231 break;
00232 case 0xfd:
00233 data[index] = '\xfe';
00234 break;
00235 default:
00236 ROS_WARN_NAMED("serial", "Unexpected second byte in encoded sequence.");
00237 return false;
00238 }
00239 break;
00240 default:
00241 data[index] = undecoded_byte;
00242 }
00243 }
00244 return true;
00245 }
00246
00247 }