urgSimulator.cpp

00001 /*
00002   URG センサデバイスのシミュレートクラス
00003   Satofumi KAMIMURA
00004   $Id$
00005 */
00006 
00007 #include "urgSimulator.h"
00008 #include "urgCtrl.h"
00009 #include "deleteObjects.h"
00010 #include "monitorTask.h"
00011 #include "urgIntersection.h"
00012 
00013 
00014 URG_Simulator::URG_Simulator(void)
00015   : server(NULL), pre_registered(NULL), enable_timestamp(false) {
00016 }
00017 
00018 
00019 URG_Simulator::~URG_Simulator(void) {
00020   for_each(sim_urgs.begin(), sim_urgs.end(), DeleteObjects());
00021 }
00022 
00023 
00024 void URG_Simulator::init(void) {
00025   // サーバの起動
00026   server = new TcpipServer();
00027   server->activate(URGCtrl::SimulatorPort);
00028 }
00029 
00030 
00031 void URG_Simulator::recv(void) {
00032   // 接続
00033   TcpipDevice *con;
00034   if (pre_registered && (con = server->accept(0))) {
00035     ScanInfo* urg = new ScanInfo;
00036     urg->con = con;
00037     urg->obj = pre_registered;
00038     pre_registered = NULL;
00039     sim_urgs.push_back(urg);
00040   }
00041 
00042   // データの受信、応答
00043   for (std::list<ScanInfo*>::iterator it = sim_urgs.begin();
00044        it != sim_urgs.end(); ++it) {
00045     if (*it) {
00046       urgDeviceResponse(**it);
00047     }
00048   }
00049 }
00050 
00051 
00052 void URG_Simulator::exec1msec(unsigned long total_msec) {
00053   // 制御処理
00054   for (std::list<ScanInfo*>::iterator it = sim_urgs.begin();
00055        it != sim_urgs.end(); ++it) {
00056     if (*it) {
00057       urgDeviceSimulator(**it, total_msec);
00058     }
00059   }
00060 }
00061 
00062 
00063 URG_Simulator::ScanInfo::ScanInfo(void)
00064   : con(NULL), obj(NULL),
00065     pre_index(0), raw_timestamp(0),
00066     cmd_handled(true), now_timeAdjustMode(false) {
00067   for (int i = 0; i < 1024; ++i) {
00068     length[i] = 19;
00069   }
00070 }
00071 
00072 
00073 URG_Simulator::ScanInfo::~ScanInfo(void) {
00074   delete con;
00075   con = NULL;
00076 
00077   //sim_urgs.erase(this);
00078   // どこかでちゃんと削除すべき。切断の検出時かな?
00079 }
00080 
00081 
00082 void URG_Simulator::setURGObject(URGCtrl* urg_obj) {
00083 
00084   // !!! このあたり、同期とかしないと、複数 URG 使用時に非常にまずい
00085   pre_registered = urg_obj;
00086 }
00087 
00088 
00089 bool URG_Simulator::checkCmdLength(TcpipDevice* con, int require_size) {
00090   return (con->size() < require_size) ? true : false;
00091 }
00092 
00093 
00094 void URG_Simulator::urgDeviceResponse(URG_Simulator::ScanInfo& urg) {
00095   bool pre_cmd_handled = urg.cmd_handled;
00096   urg.cmd_handled = true;
00097   if (pre_cmd_handled || (urg.con->size() < 1)) {
00098     return;
00099   }
00100 
00101   char first_char;
00102   urg.con->copy(&first_char, 1);
00103   //fprintf(stderr, "first_char: %c\n", first_char);
00104   if (urg.now_timeAdjustMode && (first_char != 'T')) {
00105     // エラー応答
00106     char reply[5];
00107     sprintf(reply, "%c\rE\r\r", first_char);
00108     urg.con->send(reply, 5);
00109     return;
00110   }
00111 
00112   char buffer[8];
00113   switch (first_char) {
00114   case 'S':
00115     urg.con->recv(buffer, 8);
00116     break;
00117 
00118   case 'V':
00119     if (checkCmdLength(urg.con, 3)) {
00120       break;
00121     }
00122     replyVersionInfo(urg);
00123     break;
00124 
00125   case 'B':
00126     if (checkCmdLength(urg.con, 3)) {
00127       break;
00128     }
00129     urg.con->recv(buffer, 3);
00130     urg.con->send("BM\r00P\r\r", 8);
00131     break;
00132 
00133   case 'T':
00134     if (checkCmdLength(urg.con, 4)) {
00135       break;
00136     }
00137     replyAdjustTimestamp(urg);
00138     break;
00139 
00140     //case 'g':
00141   case 'G':
00142     if (checkCmdLength(urg.con, 13)) {
00143       break;
00144     }
00145     replyDataRequest(urg);
00146     break;
00147   }
00148 }
00149 
00150 
00151 void URG_Simulator::judgeSenseArea(URG_Simulator::ScanInfo& urg,
00152                                    bool isHandstand,
00153                                    int from_index, int to_index) {
00154   URGInterface::urgParams_t& params = urg.obj->getParameters();
00155 
00156   for (int i = from_index; i < to_index; ++i) {
00157     if (i > params.sense_steps) {
00158       continue;
00159     }
00160     double radian = urg.obj->index2rad(i);
00161     CoordinateCtrl::line_t line;
00162     line.position =
00163       VXV::Position(MonitorTask::getRunPosition()
00164                     + VXV::Position(0,0, VXV::Direction::rad(radian)));
00165     line.length = params.length_max;
00166 
00167     int dest_index = (!isHandstand) ? i : params.sense_steps - i;
00168     urg.length[dest_index] = getLengthToEnvironment(line, env_polygons);
00169   }
00170 }
00171 
00172 
00173 void URG_Simulator::urgDeviceSimulator(URG_Simulator::ScanInfo& urg,
00174                                        unsigned long total_msec) {
00175   URGInterface::urgParams_t& params = urg.obj->getParameters();
00176   int index =
00177     (urg.pre_index + (1000 / params.cycle_msec)) % params.cycle_step_max;
00178   int pre_index = urg.pre_index;
00179   urg.pre_index = index;
00180 
00181   // コマンド受付タイミング
00182   if (pre_index <= index) {
00183     if ((pre_index < params.sense_steps) && (params.sense_steps <= index)) {
00184       urg.cmd_handled = false;
00185     } else if (pre_index > index) {
00186       urg.cmd_handled = true;
00187     }
00188   }
00189 
00190   // タイムスタンプの確保
00191   if ((pre_index <= index) &&
00192       (pre_index < params.ticks_begin_step) &&
00193       (params.ticks_begin_step <= index)) {
00194     urg.raw_timestamp = total_msec & 0x00ffffff;
00195   }
00196 
00197   // 時刻印合わせモードの場合
00198   if (urg.now_timeAdjustMode) {
00199     urg.cmd_handled = false;
00200     urg.raw_timestamp = total_msec & 0x00ffffff;
00201   }
00202 
00203   // URG の取り付け情報を考慮
00204   if (urg.obj->isHandstand) {
00205     int tmp = index;
00206     index = params.cycle_step_max - pre_index;
00207     pre_index = params.cycle_step_max - tmp;
00208   }
00209 
00210   // 環境線分との交差判定処理
00211   if (pre_index > index) {
00212     judgeSenseArea(urg,urg.obj->isHandstand, pre_index, params.cycle_step_max);
00213     pre_index = 0;
00214   }
00215   judgeSenseArea(urg, urg.obj->isHandstand, pre_index, index);
00216 }
00217 
00218 
00219 void URG_Simulator::setURGType(const char* type) {
00220   if (!strcmp("URG-04LX", type)) {
00221     enable_timestamp = true;
00222   }
00223 }
00224 
00225 
00226 void URG_Simulator::replyVersionInfo(URG_Simulator::ScanInfo& urg) {
00227   char withTimestamp_reply[] =
00228     "VV\r"
00229     "VV\r"
00230     "00P\r"
00231     "VEND:Hokuyo Automatic Co.,Ltd.;[\r"
00232     "PROD:SOKUIKI Sensor TOP-URG UTM-X001S;E\r"
00233     "FIRM:k.1.28b(03/Sep./2007);M\r"
00234     "PROT:SCIP 2.0;N\r"
00235     "SERI:00704464;6\r"
00236     "\r";
00237 
00238   char normal_reply[] =
00239     "V\r"
00240     "0\r"
00241     "VEND:Hokuyo Automatic Co.,Ltd.\r"
00242     "PROD:SOKUIKI Sensor URG-X003\r"
00243     "FIRM:0.2.11d,05/05/18 with USB\r"
00244     "PROT:00003,(SCIP 1.0)\r"
00245     "SERI:H0500846\r"
00246     "\r";
00247 
00248   char buffer[3];
00249   urg.con->recv(buffer, 3);
00250   if (enable_timestamp) {
00251     urg.con->send(withTimestamp_reply, sizeof(withTimestamp_reply)-1);
00252   } else {
00253     urg.con->send(normal_reply,  sizeof(normal_reply)-1);
00254   }
00255 }
00256 
00257 
00258 void URG_Simulator::replyAdjustTimestamp(URG_Simulator::ScanInfo& urg) {
00259   char buffer[] = { "TMX\r00P\r\r23456\r\r" };
00260   char ticks_buffer[5];
00261   urg.con->recv(buffer, 4);
00262   long ticks;
00263 
00264   switch (buffer[2]) {
00265   case '0':
00266     urg.now_timeAdjustMode = true;
00267     urg.con->send(buffer, 9);
00268     break;
00269 
00270   case '1':
00271     ticks = static_cast<int>(urg.raw_timestamp);
00272     for (int i = 3; i >= 0; --i) {
00273       ticks_buffer[i] = decodeByte(ticks & 0x3f);
00274       ticks >>= 6;
00275     }
00276     ticks_buffer[5] = '\0';
00277     sprintf(buffer, "TM1\r00P\r%s;\r\r", ticks_buffer);
00278     urg.con->send(buffer, 16);
00279     break;
00280 
00281   case '2':
00282     urg.now_timeAdjustMode = false;
00283     urg.con->send(buffer, 9);
00284     break;
00285   }
00286 }
00287 
00288 
00289 char URG_Simulator::decodeByte(char ch) {
00290   return (((ch & 0x3f) | 0x40) - 0x10) & 0x7f;
00291 }
00292 
00293 
00294 void URG_Simulator::replyDataRequest(URG_Simulator::ScanInfo& urg) {
00295 
00296   enum { LF = '\n' };
00297   char buf[65];
00298   urg.con->recv(buf, 13);
00299 
00300   // 要求の取得
00301   char cmd = buf[0];
00302   char cmd2 = buf[1];
00303   int raw_group = atoi(&buf[10]);
00304   int group = (raw_group <= 0) ? 1 : raw_group;
00305   buf[10] = LF;
00306   int end_index = atoi(&buf[6]);
00307   buf[6] = LF;
00308   int begin_index = atoi(&buf[2]);
00309 
00310   // 保持しているデータを整形して返す
00311   sprintf(buf, "%c%c%04d%04d%02d%c",
00312           cmd, cmd2, begin_index, end_index, raw_group, LF);
00313   urg.con->send(buf, static_cast<int>(strlen(buf)));
00314 
00315   //if (cmd == 'g') {
00316   urg.con->send("00P\r", 4);
00317 
00318   unsigned long timestamp = urg.raw_timestamp;
00319   for (int i = 3; i >= 0; --i) {
00320     buf[i] = decodeByte((char)(timestamp & 0x3f));
00321     timestamp >>= 6;
00322   }
00323   buf[4] = ';';                 // 正規のチェックサムではない
00324   buf[5] = '\r';
00325   //sprintf(buf, "%06x%c", static_cast<int>(urg.raw_timestamp + 100 -40), LF);
00326   urg.con->send(buf, 6);
00327   //}
00328 
00329   // 測定データを返す
00330   char buffer[4096];            // !!! 適当。URG 専用だな
00331   int total_steps = (end_index - begin_index + 1) / abs(group);
00332   int data_index = 0;
00333   for (int i = 0; i < total_steps; ++i) {
00334     long length = urg.length[i];
00335     buffer[data_index++] = decodeByte((length >> 12) & 0x3f);
00336     buffer[data_index++] = decodeByte((length >> 6) & 0x3f);
00337     buffer[data_index++] = decodeByte(length & 0x3f);
00338   }
00339 
00340   int left_byte = data_index;
00341   int sended = 0;
00342   while (left_byte > 0) {
00343     int send_size = left_byte;
00344     if (send_size > 64) {
00345       send_size = 64;
00346     }
00347     urg.con->send(&buffer[sended], send_size);
00348     urg.con->send(";\r", 2);
00349     sended += send_size;
00350     left_byte -= send_size;
00351   }
00352   urg.con->send("\r", 1);
00353 
00354 #if 0
00355   int total_steps = (end_index - begin_index + 1) / abs(group);
00356   int data_index = 0;
00357   int sensor_index = 0;
00358   for (int i = 0; i < total_steps; ++i) {
00359     if (i > 0 && i % 32 == 0) {
00360       buf[data_index++] = LF;
00361       urg.con->send(buf, data_index);
00362       data_index = 0;
00363     }
00364 
00365     int length = urg.length[sensor_index];
00366     for (int j = 0; j < 3; ++j) {
00367       buf[data_index++] = decodeByte((length >> 12) & 0x3f);
00368       length <<= 6;
00369 
00370       if (data_index != 0) {
00371         buf[data_index++] = LF;
00372       }
00373     }
00374     sensor_index += group;
00375   }
00376   buf[data_index++] = LF;
00377   urg.con->send(buf, data_index);
00378 #endif
00379 }
00380 
00381 
00382 void URG_Simulator::setEnvironment(const std::vector<crd_polygon_t>& objs) {
00383   env_polygons = objs;
00384 }
00385 

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