urgManualCapture.cpp

00001 /*
00002   URG の基本制御
00003   Satofumi KAMIMURA
00004   $Id$
00005 */
00006 
00007 #include "urgManualCapture.h"
00008 #include "serialDevice.h"
00009 #include "tcpipDevice.h"
00010 #include <stdio.h>
00011 
00012 enum {
00013   LineLength = 64 + 16,
00014 };
00015 
00016 
00017 URGManualCapture::URGManualCapture(void)
00018   : con(NULL), error_message("Connection device is not specified"),
00019     capture_times(0), oneData_byte(OneDataByte), Timeout(DefaultTimeout),
00020     laser_on(false), remain_byte(0), enableTimestamp(false) {
00021 }
00022 
00023 
00024 URGManualCapture::~URGManualCapture(void) {
00025   disconnect();
00026 }
00027 
00028 
00029 const char* URGManualCapture::what(void) {
00030   return error_message.c_str();
00031 }
00032 
00033 
00034 int URGManualCapture::connect(const char* device, long baudrate) {
00035   disconnect();
00036   con = new SerialDevice();
00037 
00038   int ret_value = -1;
00039   long expected_baudrate[] = { 115200, 19200, 57600 };
00040   int n = sizeof(expected_baudrate) / sizeof(expected_baudrate[0]);
00041   char s_message[16];
00042 
00043   sprintf(s_message, "SS%06ld\r", baudrate);
00044   for (int try_times = 0; try_times < 2; ++try_times) {
00045     for (int i = 0; i < n; ++i) {
00046 
00047       ret_value = con->connect(device, expected_baudrate[i]);
00048       if (ret_value >= 0) {
00049         // Linux kernel 2.4 系での受信時に最初の 64[byte]が読めない問題に対処
00050         con->disconnect();
00051         ret_value = con->connect(device, expected_baudrate[i]);
00052       }
00053       error_message = con->what();
00054       if (ret_value < 0) {
00055         return ret_value;
00056       }
00057       con->flush();
00058       con->send(s_message, 9);
00059 
00060       char ch, pre_ch = '\0';
00061       while (con->recv(&ch, 1, Timeout) > 0) {
00062         if (isLF(ch) && isLF(pre_ch)) {
00063           error_message = "Success";
00064           con->setBaudrate(baudrate);
00065           return 0;
00066         }
00067         pre_ch = ch;
00068       }
00069     }
00070   }
00071   error_message = "Baudrate adjust fail";
00072   return ConnectionDevice::BaudrateAdjustFail;
00073 }
00074 
00075 
00076 int URGManualCapture::connectSocket(const char* host, short port) {
00077 
00078   disconnect();
00079   con = new TcpipDevice();
00080   int ret_value = con->connect(host, port);
00081   error_message = con->what();
00082 
00083   return ret_value;
00084 }
00085 
00086 
00087 void URGManualCapture::disconnect(void) {
00088   if (con) {
00089     delete con;
00090     con = NULL;
00091   }
00092 }
00093 
00094 
00095 bool URGManualCapture::isConnected(void) {
00096   if (!con) {
00097     return false;
00098   } else {
00099     if (con->isConnected()) {
00100       return true;
00101     } else {
00102       throw URGCapture_Exception("Connection is disconnected");
00103     }
00104   }
00105 }
00106 
00107 
00108 void URGManualCapture::setTimestampMode(bool withTimestamp) {
00109   enableTimestamp = withTimestamp;
00110 }
00111 
00112 
00113 bool URGManualCapture::isLF(char ch) {
00114   return (ch == '\r' || ch == '\n') ? true : false;
00115 }
00116 
00117 
00118 int URGManualCapture::adjustIndex(int index, int add) {
00119 
00120   int a = (index - (index / 65) + ((index >= 65) ? 1 : 0)) % 65;
00121   int b =
00122     (index - ((index + add) / 65) + ((index + add>= 65) ? 1 : 0) + add) % 65;
00123   if (a > b) {
00124       return index + add + 1;
00125   }
00126   return index + add;
00127 }
00128 
00129 
00130 unsigned char URGManualCapture::encode6bit(char ch) {
00131   return 0x3f & (ch - 0x30);
00132 }
00133 
00134 
00135 // !!! URGCtrl からのコピー
00136 long URGManualCapture::decode(const char* data, int data_byte) {
00137   long value = 0;
00138   for (int i = 0; i < data_byte; ++i) {
00139     value <<= 6;
00140     value &= ~0x3f;
00141     value |= data[i] - 0x30;
00142   }
00143   return value;
00144 }
00145 
00146 
00147 int URGManualCapture::recvCaptureData(long* data, size_t max_size,
00148                                       unsigned long* timestamp,
00149                                       URGInterface::urgParams_t& params) {
00150 #if 0
00151   if (data == NULL) {
00152     return 0;
00153   }
00154 #endif
00155 
00156   recv_data.clear();
00157 
00158   // min までの領域を 19(計測有効範囲外)で埋める
00159   for (int i = params.first_step; i >= 0; --i) {
00160     recv_data.push_back(19);
00161   }
00162 
00163   char message_type = 'M';
00164   char buffer[LineLength];
00165   int line_length;
00166   unsigned long local_timestamp = 0;
00167   for (int i = 0; (line_length = readLine(buffer, Timeout)) >= 0; ++i) {
00168 
00169     //fprintf(stderr, "%02d: %s\n", i, buffer);
00170 
00171     // チェックサムの確認
00172     // !!!
00173     // !!! return false;
00174 
00175     if ((i >= 6) && (line_length == 0)) {
00176       // データ受信の完了
00177       int data_size = recv_data.size();
00178       size_t min_length =
00179         (static_cast<int>(max_size) < data_size) ? max_size : data_size;
00180       for (size_t i = 0; i < min_length; ++i) {
00181         data[i] = recv_data[i];
00182       }
00183       if (timestamp) {
00184         *timestamp = local_timestamp;
00185       }
00186       //fprintf(stderr, "ticks: %u\n", *timestamp);
00187       return min_length;
00188 
00189     } else if (i == 0) {
00190       // 送信メッセージの最初の文字のみでメッセージの判定を行う
00191       if ((buffer[0] != 'M') && (buffer[0] != 'G')) {
00192         error_message = "YY 01";
00193         //fprintf(stderr, "err 1\n");
00194         return -1;
00195       }
00196       message_type = buffer[0];
00197 
00198     } else if (! strncmp(buffer, "99b", 3)) {
00199       // "99b" を検出し、以降を「タイムスタンプ」「データ」とみなす
00200       i = 4;
00201 
00202     } else if ((i == 1) && (message_type == 'G')) {
00203       i = 4;
00204 
00205       // !!! 'G' コマンド時の残り回数は、ここで取り出せる
00206       if (0) {
00207         laser_on = false;
00208       }
00209 
00210     } else if (i == 2) {
00211       // 送信パケットに対する応答
00212       // !!!
00213       // 受信が終了したら、レーザーは停止する
00214       if (0) {
00215         laser_on = false;
00216       }
00217 
00218     } else if (i == 4) {
00219       // "99b" 固定
00220       if (strncmp(buffer, "99b", 3)) {
00221         error_message = "YY 02";
00222         return -1;
00223       }
00224 
00225     } else if (i == 5) {
00226       // タイムスタンプ
00227       local_timestamp = decode(buffer, 4);
00228       //fprintf(stderr, "ticks: %s, %d\n", buffer, local_timestamp);
00229 
00230     } else if (i >= 6) {
00231       // 取得データ
00232       if (line_length > (64 + 1)) {
00233         // !!! Top-URG のバグで 65 byte 以上のデータがくる問題に対処
00234         line_length = (64 + 1);
00235       }
00236       buffer[line_length -1] = '\0';
00237       int ret = addRecvData(buffer);
00238       if (ret < 0) {
00239         error_message = "YY 03";
00240         // !!! エラーメッセージの更新
00241         return ret;
00242       }
00243     }
00244   }
00245   return -1;
00246 }
00247 
00248 
00249 int URGManualCapture::readLine(char *buffer, int timeout) {
00250   if (con == NULL) {
00251     return 0;
00252   }
00253 
00254   int i;
00255   for (i = 0; i < LineLength -1; ++i) {
00256     char recv_ch;
00257     int n = con->recv(&recv_ch, 1, timeout);
00258     if (n <= 0) {
00259       if (i == 0) {
00260         return -1;              // タイムアウト
00261       }
00262       break;
00263     }
00264     if (isLF(recv_ch)) {
00265       break;
00266     }
00267     buffer[i] = recv_ch;
00268   }
00269 
00270   buffer[i] = '\0';
00271   return i;
00272 }
00273 
00274 
00275 int URGManualCapture::addRecvData(const char buffer[]) {
00276 
00277     const char* pre_p = buffer;
00278     const char* p = pre_p;
00279 
00280     if (remain_byte > 0) {
00281       memmove(&remain_data[remain_byte], buffer, oneData_byte - remain_byte);
00282       recv_data.push_back(decode(remain_data, oneData_byte));
00283       pre_p = &buffer[oneData_byte - remain_byte];
00284       p = pre_p;
00285 
00286       remain_byte = 0;
00287     }
00288 
00289     do {
00290       ++p;
00291       if ((p - pre_p) >= static_cast<int>(oneData_byte)) {
00292         recv_data.push_back(decode(pre_p, oneData_byte));
00293         pre_p = p;
00294       }
00295     } while (*p != '\0');
00296     remain_byte = p - pre_p;
00297     memmove(remain_data, pre_p, remain_byte);
00298 
00299     return 0;
00300   }
00301 
00302 
00303 int URGManualCapture::recvScanData(long data[],
00304                                    int first, int last, int group,
00305                                    const char* send_str,
00306                                    URGInterface::urgParams_t& params,
00307                                    unsigned long* raw_ticks) {
00308 
00309 
00310   size_t max_size = last - first +1;
00311   ++capture_times;
00312   return recvCaptureData(data, max_size, raw_ticks, params);
00313 
00314 #if 0
00315   char reply[13];
00316   char lf;
00317 
00318   if ((con->recv(reply, 13, DefaultTimeout) <= 0) ||
00319       strncmp(send_str, reply, 13)) {
00320     return -1;
00321   }
00322   if ((con->recv(reply, 4, Timeout) <= 0) || (reply[0] != '0')) {
00323     return -3;
00324   }
00325 
00326   //if (raw_ticks) {
00327   if (con->recv(reply, 6, Timeout) <= 0) {
00328     return HeaderError;
00329   }
00330 
00331   if (raw_ticks) {
00332     *raw_ticks = decode(reply, 4);
00333   }
00334 
00335   int num_data = last - first +1;
00336   num_data = (num_data / group) + ((num_data % group == 0) ? 0 : 1);
00337   int data_byte = oneData_byte * num_data;
00338   //int total = data_byte + ((data_byte >> 6) * 2 + 1);
00339   int total = data_byte;
00340   //fprintf(stderr, "total: %d\n", total);
00341   int filled = 0;
00342 
00343   while (total > filled) {
00344     int max = total - filled;
00345     if (max > 65) {
00346       max = 65;
00347     }
00348     int n = con->recv(&recv_buffer[filled], max, Timeout);
00349     if (n <= 0) {
00350       return RecvSizeError;
00351     }
00352     filled += n;
00353     if (n == 65) {
00354       filled -= 1;
00355     }
00356   }
00357 
00358   int lf_count = 0;
00359   while (true) {
00360     if (con->recv(&lf, 1, Timeout) <= 0) {
00361       return RecvSizeError;
00362     }
00363     if (!isLF(lf)) {
00364       lf_count = 0;
00365     }
00366     ++lf_count;
00367     if (lf_count >= 2) {
00368       break;
00369     }
00370   }
00371 
00372   //fprintf(stderr, "\n%s\n", recv_buffer);
00373 
00374   // 距離データを配列に格納
00375   for (int i = 0; i < first; ++i) {
00376     data[i] = -1;
00377   }
00378   int index = first;
00379   for (int i = 0; (index <= last) && (i < num_data); ++i) {
00380     int num = i * oneData_byte;
00381 #if 0
00382     int actual_index = num + (int)(num / 65);
00383     if ((i > 0) && ((i % 65) == 0) &&
00384         !isLF(recv_buffer[actual_index -1])) {
00385       return MissmatchLF;
00386     }
00387 #endif
00388     int actual_index = num;
00389     for (int j = 0; (index <= last) && (j < group); ++j) {
00390       data[index] =
00391         (encode6bit(recv_buffer[adjustIndex(actual_index, 0)]) << 6)
00392         | encode6bit(recv_buffer[adjustIndex(actual_index, 1)]);
00393       if (oneData_byte == 3) {
00394         data[index] = (data[index] << 6)
00395           | encode6bit(recv_buffer[adjustIndex(actual_index, 2)]);
00396       }
00397       ++index;
00398       //fprintf(stderr, "%d: %c%c%c, ", actual_index, recv_buffer[adjustIndex(actual_index, 0)], recv_buffer[adjustIndex(actual_index, 1)], recv_buffer[adjustIndex(actual_index, 2)]);
00399     }
00400   }
00401   for (int i = last +1; i < params.sense_steps; ++i) {
00402     data[i] = -1;
00403   }
00404   ++capture_times;
00405 
00406 #if 0
00407   for (int i = 0; i < params.sense_steps; ++i) {
00408     fprintf(stderr, "%d:%d\n", i, data[i]);
00409   }
00410   fprintf(stderr,"\n");
00411 #endif
00412 
00413   return params.sense_steps;
00414 #endif
00415 }
00416 
00417 
00418 int URGManualCapture::capture(long length[],
00419                               int first_index, int last_index, int group,
00420                               URGInterface::urgParams_t& params,
00421                               unsigned long* raw_timestamp) {
00422   // 渡された値を修正
00423   if (first_index > last_index) {
00424     int tmp = first_index; first_index = last_index; last_index = tmp;
00425   }
00426   if (first_index < 0) {
00427     first_index = 0;
00428   }
00429   if (last_index > params.sense_steps -1) {
00430     last_index = params.sense_steps -1;
00431   }
00432   if (group <= 0) {
00433     group = 1;
00434   } else if (group > 99) {
00435     group = 99;
00436   }
00437 
00438   // 取得コマンドの送信
00439   char send_str[13];
00440   sprintf(send_str, "GD%04d%04d%02d\n", first_index, last_index, group);
00441 #if 0
00442   if (raw_timestamp) {
00443     send_str[0] = 'g';
00444   }
00445 #endif
00446   con->flush();
00447   con->send(send_str, 13);
00448 
00449   // 受信データの解析
00450   int ret = recvScanData(length, first_index, last_index, group,
00451                          send_str, params, raw_timestamp);
00452   if (ret < 0) {
00453     error_message = "capture fail.";
00454   }
00455   return ret;
00456 }
00457 
00458 
00459 int URGManualCapture::getCaptureTimes(void) {
00460   return capture_times;
00461 }
00462 
00463 
00464 int URGManualCapture::send(const char* data, int size) {
00465   if (!con) {
00466     return ConnectionDevice::NotConnected;
00467   }
00468   return con->send(data, size);
00469 }
00470 
00471 
00472 int URGManualCapture::recv(char* data, int maxsize, long timeout) {
00473   if (!con) {
00474     return ConnectionDevice::NotConnected;
00475   }
00476   return con->recv(data, maxsize, timeout);
00477 }
00478 
00479 
00480 int URGManualCapture::recv_line(char* data, int maxsize, long timeout) {
00481   if (!con) {
00482     return ConnectionDevice::NotConnected;
00483   }
00484 
00485   // 改行までを読み出して data に格納する
00486   int filled = 0;
00487   while (con->recv(&data[filled], ((maxsize - filled > 0) ? 1 : 0),
00488                    timeout) > 0) {
00489     if (isLF(data[filled++])) {
00490       --filled;
00491       data[filled] = '\0';
00492       //fprintf(stderr, "%s\n", data);
00493       return filled;
00494     }
00495   }
00496   return filled;
00497 }
00498 
00499 
00500 void URGManualCapture::set_recvTimeout(int timeout) {
00501   Timeout = (timeout < 0) ? DefaultTimeout : timeout;
00502 }
00503 
00504 
00505 int URGManualCapture::laser(bool on) {
00506   //char l_message[7] = "L0\r";
00507   char l_message[9] = "BM\r";
00508   //l_message[1] = (on) ? '1' : '0';
00509   con->flush();
00510   con->send(l_message, 3);
00511 
00512   char ch, pre_ch = '\0';
00513   while (con->recv(&ch, 1, Timeout + 200) > 0) {
00514     //fprintf(stderr, "%c", ch);
00515     if (isLF(ch) && isLF(pre_ch)) {
00516       return 0;
00517     }
00518     pre_ch = ch;
00519   }
00520 
00521   //con->recv(l_message, 8, DefaultTimeout);
00522   //con->recv(l_message, 8, Timeout);
00523 
00524   // !!! とりあえず、適当で
00525   return 0; //(l_message[3] == '0') ? 0 : -1;
00526   return -1;
00527 }
00528 

Generated on Mon Apr 13 22:52:05 2009 by  doxygen 1.5.7.1