00001
00002
00003
00004
00005
00006
00007
00008
00016 #include <math.h>
00017 #include <net/ethernet.h>
00018 #include <netinet/ip.h>
00019 #include <netinet/tcp.h>
00020 #include <netinet/udp.h>
00021
00022 #include "applanix.h"
00023
00024 #define DEVICE "Applanix POS-LV"
00025
00026 void DevApplanix::unpack_grp1(applanix_data_t *adata, GRP1_MSG *msg)
00027 {
00028 ROS_DEBUG(DEVICE " Group1: Speed %.3f Lat %.8f Lon %.8f Alt "
00029 "%.2f Heading %.2f, Alignment %d",
00030 msg->data.speed, msg->data.lat, msg->data.lon,
00031 msg->data.alt, msg->data.heading, msg->data.alignment);
00032 ROS_DEBUG(DEVICE " Group1: roll %.3f pitch %.3f",
00033 msg->data.roll, msg->data.pitch);
00034
00035 adata->grp1 = msg->data;
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 if (have_DGPS)
00047 {
00048 if (msg->data.alignment > ApplStatusFull
00049 && msg->data.alignment < ApplStatusInitial)
00050 {
00051 ROS_WARN("Differential GPS lost! Alignment status %d",
00052 msg->data.alignment);
00053 have_DGPS = false;
00054 }
00055 }
00056 else
00057 {
00058 if (msg->data.alignment == ApplStatusFull)
00059 {
00060 ROS_WARN("Differential GPS regained!");
00061 have_DGPS = true;
00062 }
00063 }
00064 }
00065
00066 void DevApplanix::unpack_grp4(applanix_data_t *adata, GRP4_MSG *msg)
00067 {
00068
00069 ROS_DEBUG(" Status Data 0x%x IMU 0x%x IMU type 0x%x",
00070 msg->data.datastatus, msg->data.imustatus, msg->data.imutype);
00071 #if 0 // need to figure out how to interpret these fields
00072 ROS_DEBUG(" X, Y, Z velocities: (%d, %d, %d)",
00073 msg->data.vel_x, msg->data.vel_y, msg->data.vel_z);
00074 ROS_DEBUG(" roll, pitch and yaw angular velocities (raw): (%d, %d, %d)",
00075 msg->data.ang_x, msg->data.ang_y, msg->data.ang_z);
00076 ROS_DEBUG(" roll, pitch and yaw angular velocities (deg): (%.3f, %.3f, %.3f)",
00077 APPLANIX_NMEA_DEG_PER_BIT * msg->data.ang_x,
00078 APPLANIX_NMEA_DEG_PER_BIT * msg->data.ang_y,
00079 APPLANIX_NMEA_DEG_PER_BIT * msg->data.ang_z);
00080 #endif
00081 adata->grp4 = msg->data;
00082 }
00083
00084 int DevApplanix::connect_socket(void)
00085 {
00086 int rc;
00087
00088 ROS_DEBUG(DEVICE " creating socket");
00089 sockfd = socket(AF_INET, SOCK_STREAM, 0);
00090 if (sockfd < 0)
00091 {
00092 ROS_ERROR("Unable to create socket for " DEVICE " (%s)",
00093 strerror(errno));
00094 return errno;
00095 }
00096
00097 memset(&serveraddr, 0, sizeof(struct sockaddr_in));
00098 serveraddr.sin_family = AF_INET;
00099
00100 serverhostp = gethostbyname(serverhost);
00101 if (serverhostp == NULL)
00102 {
00103 ROS_ERROR("gethostbyname() failed for " DEVICE " (%s)",
00104 strerror(errno));
00105 return errno;
00106 }
00107
00108 bcopy(serverhostp->h_addr,
00109 (char *)&(serveraddr.sin_addr.s_addr),
00110 serverhostp->h_length);
00111
00112 serveraddr.sin_port = htons(APPLANIX_RTDATA_PORT);
00113
00114
00115 ROS_DEBUG(DEVICE " connecting to socket");
00116 rc = connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
00117 if (rc < 0)
00118 {
00119 ROS_ERROR("Unable to connect to " DEVICE " socket (%s)",
00120 strerror(errno));
00121 return errno;
00122 }
00123
00124 rc = fcntl(sockfd, F_SETFL, O_NONBLOCK);
00125 if (rc < 0)
00126 {
00127 ROS_ERROR("Unable to set O_NONBLOCK for " DEVICE " socket (%s)",
00128 strerror(errno));
00129 return errno;
00130 }
00131
00132 return 0;
00133 }
00134
00135
00136
00137
00138
00139
00140 int DevApplanix::read_packet(ros::Time *time)
00141 {
00142 int nbytes;
00143
00144
00145 do
00146 {
00147 ROS_DEBUG(DEVICE " reading socket");
00148 nbytes = recv(sockfd, packet_buffer+buffer_length,
00149 sizeof(packet_buffer)-buffer_length, 0);
00150 }
00151 while ((nbytes < 0) && (errno == EINTR));
00152
00153 if (nbytes == 0)
00154 {
00155 ROS_DEBUG(DEVICE " nothing received");
00156 return EAGAIN;
00157 }
00158 else if (nbytes < 0)
00159 {
00160 if (errno != EAGAIN)
00161 ROS_WARN(DEVICE " socket recv() error (%s)", strerror(errno));
00162 return errno;
00163 }
00164
00165 *time = ros::Time::now();
00166 buffer_length += nbytes;
00167
00168 ROS_DEBUG("Got packet with %d bytes, time %.6f", nbytes, time->toSec());
00169
00170 return 0;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 int DevApplanix::get_packet(applanix_data_t *adata)
00182 {
00183 GRPHDR_MSG *hdr = (GRPHDR_MSG *) packet_buffer;
00184 ros::Time packet_time = adata->time;
00185
00186
00187 while ((buffer_length < sizeof(GRPHDR_MSG))
00188 || (buffer_length < hdr->bytecount + sizeof(GRPHDR_MSG)))
00189 {
00190 int rc = read_packet(&packet_time);
00191 if (rc != 0)
00192 {
00193 ROS_DEBUG_STREAM(DEVICE " partial packet received ("
00194 << buffer_length << " bytes)");
00195 return rc;
00196 }
00197 }
00198
00199
00200
00201 ROS_DEBUG(DEVICE " %*.*s %d packet, size %d",
00202 (int) sizeof(hdr->grpstart), (int) sizeof(hdr->grpstart),
00203 hdr->grpstart, hdr->groupnum, hdr->bytecount);
00204
00205
00206 switch(hdr->groupnum)
00207 {
00208 case 1:
00209 unpack_grp1(adata, (GRP1_MSG *) packet_buffer);
00210 adata->time = packet_time;
00211 break;
00212 case 4:
00213 unpack_grp4(adata, (GRP4_MSG *) packet_buffer);
00214 break;
00215 default:
00216 break;
00217 }
00218
00219
00220 size_t packet_length = hdr->bytecount + sizeof(GRPHDR_MSG);
00221 buffer_length -= packet_length;
00222 if (buffer_length > 0)
00223 memmove(packet_buffer, packet_buffer+packet_length, buffer_length);
00224
00225 return 0;
00226 }
00227
00228
00229 int DevApplanixPCAP::connect_socket(void)
00230 {
00231 ROS_INFO("Opening input file \"%s\"", filename_.c_str());
00232
00233
00234 if ((pcap_ = pcap_open_offline(filename_.c_str(), errbuf_) ) == NULL)
00235 {
00237 ROS_FATAL("Error opening Applanix socket dump file.");
00238 return -1;
00239 }
00240 return 0;
00241 }
00242
00249 int DevApplanixPCAP::read_packet(ros::Time *time)
00250 {
00251 struct pcap_pkthdr *header;
00252 const u_char *pkt_data;
00253 int res;
00254
00255
00256
00257 if (got_data_)
00258 {
00259 got_data_ = false;
00260 return EAGAIN;
00261 }
00262
00263
00264 if ((res = pcap_next_ex(pcap_, &header, &pkt_data)) >= 0)
00265 {
00266 if (header->len > sizeof(packet_buffer)-buffer_length)
00267 {
00268
00269 ROS_WARN_STREAM("PCAP packet (size " << header->len
00270 << ") overflows buffer (" <<
00271 sizeof(packet_buffer)-buffer_length <<" left)");
00272 return EAGAIN;
00273 }
00274
00275 size_t pkt_offset = ETH_HLEN;
00276 struct iphdr *ip = (struct iphdr *) (pkt_data + pkt_offset);
00277 size_t size_ip = ip->ihl * 4;
00278 if (size_ip < 20)
00279 {
00280 ROS_WARN("invalid IP header size: %d", ip->ihl);
00281 return EAGAIN;
00282 }
00283 pkt_offset += size_ip;
00284
00285 if (ip->protocol == IPPROTO_TCP)
00286 {
00287 struct tcphdr *tcp = (struct tcphdr *) (pkt_data + pkt_offset);
00288 size_t size_tcp = tcp->doff * 4;
00289 if (size_tcp < 20)
00290 {
00291 ROS_WARN("invalid TCP header offset: %d", tcp->doff);
00292 return EAGAIN;
00293 }
00294 uint16_t dport = ntohs(tcp->dest);
00295 if (dport != APPLANIX_RTDATA_PORT)
00296 {
00297 ROS_INFO("wrong TCP data port: %u", dport);
00298 return EAGAIN;
00299 }
00300 ROS_DEBUG_STREAM("have TCP packet, port " << dport);
00301 pkt_offset += size_tcp;
00302 }
00303 else if (ip->protocol == IPPROTO_UDP)
00304 {
00305
00306
00307
00308 struct udphdr *udp = (struct udphdr *) (pkt_data + pkt_offset);
00309 uint16_t dport = ntohs(udp->dest);
00310 if (dport != APPLANIX_DISPLAY_PORT)
00311 {
00312 ROS_DEBUG("other UDP data port: %u", dport);
00313 return EAGAIN;
00314 }
00315 ROS_DEBUG_STREAM("have UDP packet, port " << dport);
00316 pkt_offset += sizeof(struct udphdr);
00317 }
00318 else
00319 {
00320 ROS_DEBUG_STREAM("non-Applanix packet, protocol " << ip->protocol);
00321 return EAGAIN;
00322 }
00323
00324
00325
00326 size_t pkt_length = header->len - pkt_offset;
00327 memcpy(packet_buffer + buffer_length, pkt_data + pkt_offset, pkt_length);
00328 buffer_length += pkt_length;
00329 *time = ros::Time::now();
00330 got_data_ = true;
00331 empty_ = false;
00332 }
00333 else
00334 {
00335 if (empty_)
00336 {
00337 if (res == -1)
00338 {
00339 ROS_WARN("Error reading Applanix packet: %s",
00340 pcap_geterr(pcap_));
00341 return EIO;
00342 }
00343 ROS_FATAL("No useable Applanix packets in PCAP file");
00344 ros::shutdown();
00345 return EIO;
00346 }
00347
00348 if (read_once_)
00349 {
00350
00351
00352 return EAGAIN;
00353 }
00354
00355 if (repeat_delay_ > 0.0)
00356 {
00357 ROS_INFO("end of file reached -- delaying %.3f seconds.",
00358 repeat_delay_);
00359 usleep(rint(repeat_delay_ * 1000000.0));
00360 }
00361
00362 ROS_DEBUG("replaying Applanix dump file");
00363
00364
00365
00366
00367 pcap_close(pcap_);
00368 pcap_ = pcap_open_offline(filename_.c_str(), errbuf_);
00369 empty_ = true;
00370
00371 return EAGAIN;
00372 }
00373
00374 return 0;
00375 }
00376
00377 int DevApplanixTest::connect_socket(void)
00378 {
00379 fp_ = fopen(testfile_.c_str(), "r");
00380 if (fp_ == NULL)
00381 {
00382 int rc = errno;
00383 ROS_ERROR("failed to open \"%s\" (%s)",
00384 testfile_.c_str(), strerror(rc));
00385 return rc;
00386 }
00387
00388 ROS_INFO("unit test connection: running with fake data");
00389 return 0;
00390 }
00391
00393 int DevApplanixTest::get_packet(applanix_data_t *adata)
00394 {
00395 applanix_data_t test_data;
00396 memset(&test_data, 0, sizeof(test_data));
00397
00398 int rc = fscanf(fp_, " %d %lf %lf %lf %f %f %f %lf %lf %lf %f",
00399 (int *) &test_data.grp1.alignment,
00400 &test_data.grp1.lat,
00401 &test_data.grp1.lon,
00402 &test_data.grp1.alt,
00403 &test_data.grp1.vel_north,
00404 &test_data.grp1.vel_east,
00405 &test_data.grp1.vel_down,
00406 &test_data.grp1.roll,
00407 &test_data.grp1.pitch,
00408 &test_data.grp1.heading,
00409 &test_data.grp1.speed);
00410
00411 if (feof(fp_))
00412 {
00413 clearerr(fp_);
00414 rewind(fp_);
00415 return EAGAIN;
00416 }
00417 if (ferror(fp_))
00418 {
00419 clearerr(fp_);
00420 return EIO;
00421 }
00422 else if (rc < 11 || test_data.grp1.alignment == ApplStatusInvalid)
00423 return EAGAIN;
00424
00425 test_data.time = ros::Time::now();
00426 *adata = test_data;
00427
00428 return 0;
00429 }