00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <sys/termios.h>
00027 #include <sys/ioctl.h>
00028 #include <cstring>
00029 #include <cstdlib>
00030 #include <time.h>
00031 #include <errno.h>
00032 #include <bitset>
00033
00034 #include <ros/ros.h>
00035
00036 #include "asctec_autopilot/crc16.h"
00037 #include "asctec_autopilot/autopilot.h"
00038 #include "asctec_autopilot/telemetry.h"
00039 #include "asctec_autopilot/serialinterface.h"
00040
00041
00042 extern "C" {
00043 #include <unistd.h>
00044 #include <fcntl.h>
00045 }
00046
00047 namespace asctec
00048 {
00049 SerialInterface::SerialInterface (std::string port, uint32_t speed):serialport_name_ (port), serialport_speed_ (speed)
00050 {
00051 struct termios tio;
00052 status = false;
00053 serialport_baud_ = bitrate (serialport_speed_);
00054 ROS_INFO ("Initializing serial port...");
00055
00056 dev_ = open(serialport_name_.c_str (),O_RDWR | O_NOCTTY | O_NDELAY);
00057 ROS_DEBUG ("dev: %d", dev_);
00058 ROS_ASSERT_MSG (dev_ != -1, "Failed to open serial port: %s %s", serialport_name_.c_str (), strerror (errno));
00059
00060 ROS_ASSERT_MSG (tcgetattr (dev_, &tio) == 0, "Unknown Error: %s", strerror (errno));
00061
00062 cfsetispeed (&tio, serialport_baud_);
00063 cfsetospeed (&tio, serialport_baud_);
00064
00065 tio.c_iflag = 0;
00066 tio.c_iflag &= ~(BRKINT | ICRNL | IMAXBEL);
00067 tio.c_iflag |= IGNBRK;
00068
00069 tio.c_oflag = 0;
00070 tio.c_oflag &= ~(OPOST | ONLCR);
00071
00072 tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;
00073 tio.c_cflag &= ~(PARENB | CRTSCTS | CSTOPB);
00074
00075 tio.c_lflag = 0;
00076 tio.c_lflag |= NOFLSH;
00077 tio.c_lflag &= ~(ISIG | IEXTEN | ICANON | ECHO | ECHOE);
00078
00079 ROS_ASSERT_MSG (tcsetattr (dev_, TCSADRAIN, &tio) == 0, "Unknown Error: %s", strerror (errno));
00080
00081 tio.c_cc[VMIN] = 0;
00082 tio.c_cc[VTIME] = 0;
00083
00084 tcflush (dev_, TCIOFLUSH);
00085
00086 ROS_ASSERT_MSG (dev_ != NULL, "Could not open serial port %s", serialport_name_.c_str ());
00087 ROS_INFO ("Successfully connected to %s, Baudrate %d\n", serialport_name_.c_str (), serialport_speed_);
00088 }
00089
00090 SerialInterface::~SerialInterface ()
00091 {
00092 ROS_DEBUG ("Destroying Serial Interface");
00093 flush ();
00094 close (dev_);
00095 }
00096
00097 void SerialInterface::flush ()
00098 {
00099 tcflush (dev_, TCIOFLUSH);
00100 }
00101
00102 void SerialInterface::drain ()
00103 {
00104 ROS_ASSERT_MSG (tcdrain (dev_) == 0, "Drain Error: %s", strerror (errno));
00105 }
00106
00107 int SerialInterface::wait (int bytes_requested)
00108 {
00109 int bytes_available=0;
00110 unsigned int i=0;
00111
00112 while (bytes_available < bytes_requested)
00113 {
00114 ioctl(dev_,FIONREAD,&bytes_available);
00115 usleep(1);
00116 if (i>650 && bytes_available < bytes_requested)
00117 {
00118 ROS_ERROR("Timeout: %d bytes available %d bytes requested",bytes_available,bytes_requested);
00119 return bytes_available;
00120 }
00121 i++;
00122 }
00123 return bytes_available;
00124 }
00125
00126 speed_t SerialInterface::bitrate (int Bitrate)
00127 {
00128 switch (Bitrate)
00129 {
00130 case 9600:
00131 return B9600;
00132 case 19200:
00133 return B19200;
00134 case 38400:
00135 return B38400;
00136 case 57600:
00137 return B57600;
00138 case 115200:
00139 return B115200;
00140 case 230400:
00141 return B230400;
00142 default:
00143 return B0;
00144 }
00145 }
00146
00147 bool SerialInterface::getPacket (char *spacket, unsigned char &packet_type, unsigned short &packet_crc,
00148 unsigned short &packet_size)
00149 {
00150 char stoken[4];
00151 char ssize[2];
00152 char stype[1];
00153 char scrc[2];
00154 int bytes;
00155
00156 int i;
00157
00158 ROS_DEBUG (" SerialInterface::getPacket()");
00159
00160 stoken[0] = '\0';
00161 stoken[1] = '\0';
00162 stoken[2] = '\0';
00163 stoken[3] = '\0';
00164
00165 wait(3);
00166 i = read (dev_,stoken, 3);
00167 if (i == 0 || strncmp (stoken, ">*>", 3) != 0)
00168 {
00169 ROS_DEBUG (" dev: %zd", (size_t) dev_);
00170 ROS_ERROR (" Error Reading Packet Header: %s", strerror (errno));
00171 ROS_ERROR (" Read (%d): %s", i, stoken);
00172
00173
00174 flush ();
00175 return false;
00176 }
00177 serialport_bytes_rx_ += 3;
00178 ROS_DEBUG (" Packet Header OK");
00179
00180
00181 wait(2);
00182 i = read (dev_,ssize, 2);
00183 if (i == 0)
00184 {
00185 ROS_ERROR ("Error Reading Packet Size: %s", strerror (errno));
00186 flush ();
00187 return false;
00188 }
00189 serialport_bytes_rx_ += 2;
00190 memcpy (&packet_size, ssize, sizeof (packet_size));
00191
00192
00193
00194 wait(1);
00195 i = read (dev_, stype, 1);
00196 if (i == 0)
00197 return false;
00198 serialport_bytes_rx_ += 1;
00199 memcpy (&packet_type, stype, sizeof (packet_type));
00200
00201
00202
00203 wait(packet_size);
00204 i = read (dev_, spacket, packet_size);
00205 if (i == 0)
00206 return false;
00207 serialport_bytes_rx_ += packet_size;
00208
00209
00210
00211 wait(2);
00212 i = read (dev_, scrc, 2);
00213 if (i == 0)
00214 return false;
00215 serialport_bytes_rx_ += sizeof (scrc);
00216 memcpy (&packet_crc, scrc, sizeof (packet_crc));
00217
00218
00219
00220 wait(3);
00221 i = read (dev_, stoken, 3);
00222 if (i == 0 || strncmp (stoken, "<#<", 3) != 0)
00223 {
00224 ROS_ERROR ("Error Reading Packet Footer: %s", strerror (errno));
00225 ROS_DEBUG ("Read (%d): %s", i, stoken);
00226 while (read (dev_, stoken, 1) != 0)
00227 {
00228 stoken[1] = '\0';
00229 ROS_DEBUG ("%s", stoken);
00230 }
00231 flush ();
00232 drain ();
00233 ROS_DEBUG ("Packet Footer Corrupt!!");
00234 return false;
00235 }
00236 serialport_bytes_rx_ += 3;
00237
00238
00239 return true;
00240 }
00241
00242 void SerialInterface::output (char *output, int len)
00243 {
00244 int i;
00245 ROS_DEBUG ("SerialInterface::output()");
00246 serialport_bytes_tx_ += len;
00247
00248
00249
00250 i = write (dev_, output, len);
00251 if (i != len)
00252 {
00253 ROS_ERROR ("Error wrote %d out of %d element(s): %s", i, len, strerror (errno));
00254 ROS_BREAK ();
00255 }
00256 ROS_DEBUG ("Write completed");
00257 }
00258
00259 void SerialInterface::output (unsigned char *output, int len)
00260 {
00261 int i;
00262 ROS_DEBUG ("SerialInterface::output()");
00263 serialport_bytes_tx_ += len;
00264
00265
00266
00267 i = write (dev_, output, len);
00268 if (i != len)
00269 {
00270 ROS_ERROR ("Error wrote %d out of %d element(s): %s", i, len, strerror (errno));
00271 ROS_BREAK ();
00272 }
00273 }
00274 void SerialInterface::sendControl (Telemetry * telemetry)
00275 {
00276 int i;
00277 char data[5];
00278
00279 if(!telemetry->controlEnabled_) return;
00280
00281 flush();
00282 unsigned char cmd[] = ">*>di";
00283
00284 if (telemetry->controlInterval_ != 0 && ((telemetry->controlCount_ - telemetry->controlOffset_) % telemetry->controlInterval_ == 0)) {
00285 if(telemetry->CTRL_INPUT_.chksum != telemetry->CTRL_INPUT_.pitch + telemetry->CTRL_INPUT_.roll + telemetry->CTRL_INPUT_.yaw + telemetry->CTRL_INPUT_.thrust + telemetry->CTRL_INPUT_.ctrl + (short) 0xAAAA){
00286
00287 return;
00288 }
00289 output(cmd,5);
00290 output((unsigned char*) &telemetry->CTRL_INPUT_, 12);
00291
00292 wait(5);
00293
00294 i = read (dev_,data,5);
00295 if (i != 5) {
00296 ROS_ERROR("Control Response : Insufficient Data");
00297 flush();
00298 return;
00299 }
00300 if (strncmp(data,">a",2) != 0) {
00301 ROS_ERROR("Corrupt Response Header %c%c (%0x%0x)",data[0],data[1],data[0],data[1]);
00302 flush();
00303 return;
00304 }
00305 if (strncmp(data+3,"a<",2) != 0) {
00306 ROS_ERROR("Corrupt Response Footer %c%c (%0x%0x)",data[3],data[4],data[3],data[4]);
00307 flush();
00308 return;
00309 }
00310 ROS_DEBUG("Control Response Code %0x",data[2]);
00311 }
00312
00313 }
00314
00315 void SerialInterface::sendEstop(Telemetry * telemetry)
00316 {
00317 static bool sent_estop_reported = false;
00318 if (!telemetry->controlEnabled_)
00319 return;
00320
00321 flush();
00322 unsigned char cmd[] = ">*>me";
00323 output(cmd, 5);
00324 if (!sent_estop_reported)
00325 {
00326 ROS_WARN("Sent E-Stop command!");
00327 sent_estop_reported = true;
00328 }
00329 }
00330
00331 bool SerialInterface::getPackets (Telemetry * telemetry)
00332 {
00333 flush ();
00334 ROS_DEBUG ("SerialInterface::getPackets");
00335 char cmd[16];
00336 char spacket[1024];
00337 unsigned char packet_type;
00338 unsigned short packet_crc;
00339 unsigned short packet_size;
00340 unsigned int i;
00341 bool result = false;
00342 ros::Time packetTime;
00343
00344 ROS_DEBUG (" Requesting %04x %zd packets", (short) telemetry->requestPackets_.to_ulong (),
00345 telemetry->requestPackets_.count ());
00346 sprintf (cmd, ">*>p%c", (short) telemetry->requestPackets_.to_ulong ());
00347 output (cmd, 6);
00348
00349 for (i = 0; i < telemetry->requestPackets_.count (); i++)
00350 {
00351 packetTime = ros::Time::now();
00352
00353
00354
00355 bool read_result = getPacket (spacket, packet_type, packet_crc, packet_size);
00356
00357 if (read_result)
00358 {
00359 ROS_DEBUG (" Read successful: type = %d, crc = %d", packet_type, packet_crc);
00360
00361 if (packet_type == Telemetry::PD_LLSTATUS)
00362 {
00363 ROS_DEBUG (" Packet type is LL_STATUS");
00364 memcpy (&telemetry->LL_STATUS_, spacket, packet_size);
00365 telemetry->timestamps_[RequestTypes::LL_STATUS] = packetTime;
00366 if (crc_valid (packet_crc, &telemetry->LL_STATUS_, sizeof (packet_size)))
00367 {
00368 result = true;
00369 }
00370
00371 }
00372 else if (packet_type == Telemetry::PD_IMURAWDATA)
00373 {
00374 ROS_DEBUG (" Packet type is IMU_RAWDATA");
00375 memcpy (&telemetry->IMU_RAWDATA_, spacket, packet_size);
00376 telemetry->timestamps_[RequestTypes::IMU_RAWDATA] = packetTime;
00377 if (crc_valid (packet_crc, &telemetry->IMU_RAWDATA_, packet_size))
00378 {
00379 result = true;
00380 }
00381
00382 }
00383 else if (packet_type == Telemetry::PD_IMUCALCDATA)
00384 {
00385 ROS_DEBUG (" Packet type is IMU_CALCDATA");
00386 memcpy (&telemetry->IMU_CALCDATA_, spacket, packet_size);
00387 telemetry->timestamps_[RequestTypes::IMU_CALCDATA] = packetTime;
00388 if (crc_valid (packet_crc, &telemetry->IMU_CALCDATA_, packet_size))
00389 {
00390 result = true;
00391 }
00392
00393 }
00394 else if (packet_type == Telemetry::PD_RCDATA)
00395 {
00396 ROS_DEBUG (" Packet type is RC_DATA");
00397 memcpy (&telemetry->RC_DATA_, spacket, packet_size);
00398 telemetry->timestamps_[RequestTypes::RC_DATA] = packetTime;
00399 if (crc_valid (packet_crc, &telemetry->RC_DATA_, packet_size))
00400 {
00401 result = true;
00402 }
00403
00404 }
00405 else if (packet_type == Telemetry::PD_CTRLOUT)
00406 {
00407 ROS_DEBUG (" Packet type is CONTROLLER_OUTPUT");
00408 memcpy (&telemetry->CONTROLLER_OUTPUT_, spacket, packet_size);
00409 telemetry->timestamps_[RequestTypes::CONTROLLER_OUTPUT] = packetTime;
00410 if (crc_valid (packet_crc, &telemetry->CONTROLLER_OUTPUT_, packet_size))
00411 {
00412 result = true;
00413 }
00414
00415 }
00416 else if (packet_type == Telemetry::PD_GPSDATA)
00417 {
00418 ROS_DEBUG (" Packet type is GPS_DATA");
00419 memcpy (&telemetry->GPS_DATA_, spacket, packet_size);
00420 telemetry->timestamps_[RequestTypes::GPS_DATA] = packetTime;
00421 if (crc_valid (packet_crc, &telemetry->GPS_DATA_, packet_size))
00422 {
00423 result = true;
00424 }
00425
00426 }
00427 else if (packet_type == Telemetry::PD_GPSDATAADVANCED)
00428 {
00429 ROS_DEBUG (" Packet type is GPS_DATA_ADVANCED");
00430 memcpy (&telemetry->GPS_DATA_ADVANCED_, spacket, packet_size);
00431 telemetry->timestamps_[RequestTypes::GPS_DATA_ADVANCED] = packetTime;
00432 if (crc_valid (packet_crc, &telemetry->GPS_DATA_ADVANCED_, packet_size))
00433 {
00434 result = true;
00435 }
00436
00437 }
00438 else
00439 {
00440 ROS_ERROR (" Packet type (%#2x) is UNKNOWN", packet_type);
00441 }
00442 }
00443 else
00444 {
00445
00446 ROS_ERROR (" Read failed");
00447 break;
00448 }
00449 }
00450 ioctl(dev_,FIONREAD,&i);
00451 if (i != 0)
00452 {
00453 ROS_ERROR (" Unexpected Data: Flushing receive buffer");
00454 flush();
00455 }
00456 return result;
00457 }
00458 }
00459