00001
00031 #include "Aria.h"
00032 #include "ArNetworking.h"
00033 #include "Arnl.h"
00034
00035 #include "ArLocalizationTask.h"
00036 #include "ArDocking.h"
00037
00038 void logOptions(const char *progname)
00039 {
00040 ArLog::log(ArLog::Normal, "Usage: %s [options]\n", progname);
00041 ArLog::log(ArLog::Normal, "[options] are any program options listed below, or any ARNL configuration");
00042 ArLog::log(ArLog::Normal, "parameters as -name <value>, see params/arnl.p for list.");
00043 ArLog::log(ArLog::Normal, "For example, -map <map file>.");
00044 Aria::logOptions();
00045 }
00046
00047 bool gyroErrored = false;
00048 const char* getGyroStatusString(ArRobot* robot)
00049 {
00050 if(!robot || !robot->getOrigRobotConfig() || robot->getOrigRobotConfig()->getGyroType() < 2) return "N/A";
00051 if(robot->getFaultFlags() & ArUtil::BIT4)
00052 {
00053 gyroErrored = true;
00054 return "ERROR/OFF";
00055 }
00056 if(gyroErrored)
00057 {
00058 return "OK but error before";
00059 }
00060 return "OK";
00061 }
00062
00063 int main(int argc, char **argv)
00064 {
00065
00066 Aria::init();
00067 Arnl::init();
00068
00069
00070
00071 ArRobot robot;
00072
00073
00074 ArArgumentParser parser(&argc, argv);
00075
00076
00077
00078 ArRobotConnector robotConnector(&parser, &robot);
00079
00080
00081 if (!robotConnector.connectRobot())
00082 {
00083 ArLog::log(ArLog::Normal, "Error: Could not connect to robot... exiting");
00084 Aria::exit(3);
00085 }
00086
00087
00088
00089
00090
00091
00092 char fileDir[1024];
00093 ArUtil::addDirectories(fileDir, sizeof(fileDir), Aria::getDirectory(),
00094 "examples");
00095 ArLog::log(ArLog::Normal, "Installation directory is: %s\nMaps directory is: %s\n", Aria::getDirectory(), fileDir);
00096
00097
00098
00099
00100
00101
00102
00103 ArLog::addToConfig(Aria::getConfig());
00104
00105
00106
00107 ArAnalogGyro gyro(&robot);
00108
00109
00110 ArServerBase server;
00111
00112
00113
00114 ArServerSimpleOpener simpleOpener(&parser);
00115
00116
00117 ArLaserConnector laserConnector(&parser, &robot, &robotConnector);
00118
00119
00120
00121 parser.addDefaultArgument("-connectLaser");
00122
00123
00124
00125 parser.loadDefaultArguments();
00126
00127
00128 if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
00129 {
00130 logOptions(argv[0]);
00131 Aria::exit(1);
00132 }
00133
00134
00135
00136
00137 ArGlobalFunctor1<int> shutdownFunctor(&Aria::exit, 9);
00138 robot.addDisconnectOnErrorCB(&shutdownFunctor);
00139
00140
00141
00142
00143 ArSonarDevice sonarDev;
00144 robot.addRangeDevice(&sonarDev);
00145
00146
00147
00148
00149
00150 ArRobotConfig robotConfig(&robot);
00151
00152
00153 robotConfig.addAnalogGyro(&gyro);
00154
00155
00156 robot.runAsync(true);
00157
00158
00159
00160
00161 if (!laserConnector.connectLasers())
00162 {
00163 ArLog::log(ArLog::Normal, "Could not connect to all lasers... exiting\n");
00164 Aria::exit(2);
00165 }
00166
00167
00168
00169 robot.lock();
00170 ArLaser *firstLaser = robot.findLaser(1);
00171 if (firstLaser == NULL || !firstLaser->isConnected())
00172 {
00173 ArLog::log(ArLog::Normal, "Did not have laser 1 or it is not connected, cannot start localization and/or mapping... exiting");
00174 Aria::exit(2);
00175 }
00176 robot.unlock();
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 ArMap map(fileDir);
00188
00189
00190 map.setIgnoreEmptyFileName(true);
00191
00192
00193
00194 map.setIgnoreCase(true);
00195
00196
00197
00198
00199
00200 ArPathPlanningTask pathTask(&robot, &sonarDev, &map);
00201
00202 ArLog::log(ArLog::Normal, "Creating laser localization task");
00203
00204 ArLocalizationTask locTask(&robot, firstLaser, &map);
00205
00206
00207
00208
00209
00210 std::map<int, ArLaser *>::iterator laserIt;
00211 for (laserIt = robot.getLaserMap()->begin();
00212 laserIt != robot.getLaserMap()->end();
00213 laserIt++)
00214 {
00215 int laserNum = (*laserIt).first;
00216 ArLaser *laser = (*laserIt).second;
00217
00218
00219 if(!laser->isConnected())
00220 continue;
00221
00222
00223
00224 laser->addDisconnectOnErrorCB(&shutdownFunctor);
00225
00226 laser->setCumulativeBufferSize(200);
00227
00228 pathTask.addRangeDevice(laser, ArPathPlanningTask::BOTH);
00229
00230 laser->setCumulativeCleanOffset(laserNum * 100);
00231
00232 laser->resetLastCumulativeCleanTime();
00233
00234
00235
00236
00237 std::string laserPacketCountName;
00238 laserPacketCountName = laser->getName();
00239 laserPacketCountName += " Packet Count";
00240 Aria::getInfoGroup()->addStringInt(
00241 laserPacketCountName.c_str(), 10,
00242 new ArRetFunctorC<int, ArLaser>(laser,
00243 &ArLaser::getReadingCount));
00244 }
00245
00246
00247
00248
00249 ArClientSwitchManager clientSwitch(&server, &parser);
00250
00251
00252
00253
00254
00255
00256
00257 if (!simpleOpener.open(&server, fileDir, 240))
00258 {
00259 ArLog::log(ArLog::Normal, "Error: Could not open server.");
00260 exit(2);
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 ArServerHandlerMultiRobot *handlerMultiRobot = NULL;
00278 ArMultiRobotRangeDevice *multiRobotRangeDevice = NULL;
00279 ArServerHandlerMultiRobotPeer *multiRobotPeer = NULL;
00280 ArMultiRobotPeerRangeDevice *multiRobotPeerRangeDevice = NULL;
00281
00282
00283 bool usingCentralServer = false;
00284 if(clientSwitch.getCentralServerHostName() != NULL)
00285 usingCentralServer = true;
00286
00287
00288
00289 if (usingCentralServer)
00290 {
00291
00292
00293 handlerMultiRobot = new ArServerHandlerMultiRobot(&server, &robot,
00294 &pathTask,
00295 &locTask, &map);
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 multiRobotRangeDevice = new ArMultiRobotRangeDevice(&server);
00310
00311 robot.addRangeDevice(multiRobotRangeDevice);
00312 pathTask.addRangeDevice(multiRobotRangeDevice,
00313 ArPathPlanningTask::BOTH);
00314
00315
00316 multiRobotRangeDevice->setCurrentDrawingData(
00317 new ArDrawingData("polyDots", ArColor(125, 125, 0),
00318 100, 73, 1000), true);
00319 multiRobotRangeDevice->setCumulativeDrawingData(
00320 new ArDrawingData("polyDots", ArColor(125, 0, 125),
00321 100, 72, 1000), true);
00322
00323
00324
00325 locTask.setMultiRobotCallback(multiRobotRangeDevice->getOtherRobotsCB());
00326 }
00327
00328 else
00329 {
00330
00331 pathTask.setUseCollisionRangeForPlanningFlag(true);
00332
00333 multiRobotPeerRangeDevice = new ArMultiRobotPeerRangeDevice(&map);
00334
00335 multiRobotPeer = new ArServerHandlerMultiRobotPeer(&server, &robot,
00336 &pathTask, &locTask);
00337
00338 multiRobotPeer->setNewPrecedenceCallback(
00339 multiRobotPeerRangeDevice->getSetPrecedenceCallback());
00340
00341
00342 multiRobotPeer->setNewFingerprintCallback(
00343 multiRobotPeerRangeDevice->getSetFingerprintCallback());
00344
00345
00346 multiRobotPeerRangeDevice->setChangeFingerprintCB(
00347 multiRobotPeer->getChangeFingerprintCB());
00348
00349 robot.addRangeDevice(multiRobotPeerRangeDevice);
00350 pathTask.addRangeDevice(multiRobotPeerRangeDevice,
00351 ArPathPlanningTask::BOTH);
00352
00353
00354
00355 multiRobotPeerRangeDevice->setCurrentDrawingData(
00356 new ArDrawingData("polyDots", ArColor(125, 125, 0),
00357 100, 72, 1000), true);
00358 multiRobotPeerRangeDevice->setCumulativeDrawingData(
00359 new ArDrawingData("polyDots", ArColor(125, 0, 125),
00360 100, 72, 1000), true);
00361
00362
00363 locTask.setMultiRobotCallback(
00364 multiRobotPeerRangeDevice->getOtherRobotsCB());
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 robot.lock();
00376 ArIRs irs;
00377 robot.addRangeDevice(&irs);
00378 pathTask.addRangeDevice(&irs, ArPathPlanningTask::CURRENT);
00379
00380
00381
00382 ArBumpers bumpers;
00383 robot.addRangeDevice(&bumpers);
00384 pathTask.addRangeDevice(&bumpers, ArPathPlanningTask::CURRENT);
00385
00386
00387
00388
00389 ArForbiddenRangeDevice forbidden(&map);
00390 robot.addRangeDevice(&forbidden);
00391 pathTask.addRangeDevice(&forbidden, ArPathPlanningTask::CURRENT);
00392
00393 robot.unlock();
00394
00395
00396
00397 ArActionSlowDownWhenNotCertain actionSlowDown(&locTask);
00398 pathTask.getPathPlanActionGroup()->addAction(&actionSlowDown, 140);
00399
00400
00401 ArActionLost actionLostPath(&locTask, &pathTask);
00402 pathTask.getPathPlanActionGroup()->addAction(&actionLostPath, 150);
00403
00404
00405
00406
00407
00408
00409 ArGlobalReplanningRangeDevice replanDev(&pathTask);
00410
00411
00412
00413 ArServerInfoDrawings drawings(&server);
00414 drawings.addRobotsRangeDevices(&robot);
00415 drawings.addRangeDevice(&replanDev);
00416
00417
00418
00419
00420 ArDrawingData drawingDataP("polyLine", ArColor(200,200,200), 1, 75);
00421 ArFunctor2C<ArPathPlanningTask, ArServerClient *, ArNetPacket *>
00422 drawingFunctorP(&pathTask, &ArPathPlanningTask::drawSearchRectangle);
00423 drawings.addDrawing(&drawingDataP, "Local Plan Area", &drawingFunctorP);
00424
00425
00426 ArDrawingData drawingDataL("polyDots", ArColor(0,255,0), 100, 75);
00427 ArFunctor2C<ArLocalizationTask, ArServerClient *, ArNetPacket *>
00428 drawingFunctorL(&locTask, &ArLocalizationTask::drawRangePoints);
00429 drawings.addDrawing(&drawingDataL, "Localization Points", &drawingFunctorL);
00430
00431
00432
00433
00434
00435 ArServerHandlerCommands commands(&server);
00436
00437
00438
00439 ArServerInfoRobot serverInfoRobot(&server, &robot);
00440 ArServerInfoSensor serverInfoSensor(&server, &robot);
00441 ArServerInfoPath serverInfoPath(&server, &robot, &pathTask);
00442 serverInfoPath.addSearchRectangleDrawing(&drawings);
00443 serverInfoPath.addControlCommands(&commands);
00444
00445
00446
00447 ArServerInfoLocalization serverInfoLocalization(&server, &robot, &locTask);
00448 ArServerHandlerLocalization serverLocHandler(&server, &robot, &locTask);
00449
00450
00451
00452
00453
00454
00455
00456
00457 ArServerHandlerMap serverMap(&server, &map);
00458
00459
00460 ArServerSimpleComUC uCCommands(&commands, &robot);
00461 ArServerSimpleComMovementLogging loggingCommands(&commands, &robot);
00462 ArServerSimpleComLogRobotConfig configCommands(&commands, &robot);
00463
00464
00465
00466
00467
00468
00469 ArServerHandlerCommMonitor handlerCommMonitor(&server);
00470
00471
00472
00473
00474 ArServerHandlerConfig handlerConfig(&server, Aria::getConfig(),
00475 Arnl::getTypicalDefaultParamFileName(),
00476 Aria::getDirectory());
00477
00478
00479
00480
00481
00482
00483
00484
00485 ArServerModeGoto modeGoto(&server, &robot, &pathTask, &map,
00486 locTask.getRobotHome(),
00487 locTask.getRobotHomeCallback());
00488
00489
00490
00491 ArServerModeStop modeStop(&server, &robot);
00492
00493
00494
00495
00496
00497 ArSonarAutoDisabler sonarAutoDisabler(&robot);
00498
00499
00500 ArServerModeRatioDrive modeRatioDrive(&server, &robot);
00501
00502
00503
00504
00505
00506
00507
00508
00509 ArActionLost actionLostRatioDrive(&locTask, &pathTask, &modeRatioDrive);
00510 modeRatioDrive.getActionGroup()->addAction(&actionLostRatioDrive, 110);
00511
00512
00513 modeRatioDrive.addToConfig(Aria::getConfig(), "Teleop settings");
00514 modeRatioDrive.addControlCommands(&commands);
00515
00516
00517 ArServerModeWander modeWander(&server, &robot);
00518 ArActionLost actionLostWander(&locTask, &pathTask, &modeWander);
00519 modeWander.getActionGroup()->addAction(&actionLostWander, 110);
00520
00521
00522
00523
00524
00525 ArServerInfoStrings stringInfo(&server);
00526 Aria::getInfoGroup()->addAddStringCallback(stringInfo.getAddStringFunctor());
00527
00528
00529
00530
00531 Aria::getInfoGroup()->addStringInt(
00532 "Motor Packet Count", 10,
00533 new ArConstRetFunctorC<int, ArRobot>(&robot,
00534 &ArRobot::getMotorPacCount));
00535
00536 Aria::getInfoGroup()->addStringDouble(
00537 "Laser Localization Score", 8,
00538 new ArRetFunctorC<double, ArLocalizationTask>(
00539 &locTask, &ArLocalizationTask::getLocalizationScore),
00540 "%.03f");
00541 Aria::getInfoGroup()->addStringInt(
00542 "Laser Loc Num Samples", 8,
00543 new ArRetFunctorC<int, ArLocalizationTask>(
00544 &locTask, &ArLocalizationTask::getCurrentNumSamples),
00545 "%4d");
00546
00547
00548
00549
00550
00551
00552 if(robot.getOrigRobotConfig() && robot.getOrigRobotConfig()->getGyroType() > 1)
00553 {
00554 Aria::getInfoGroup()->addStringString(
00555 "Gyro/IMU Status", 10,
00556 new ArGlobalRetFunctor1<const char*, ArRobot*>(&getGyroStatusString, &robot)
00557 );
00558 }
00559
00560
00561
00562 ArServerModeDock *modeDock = NULL;
00563 modeDock = ArServerModeDock::createDock(&server, &robot, &locTask,
00564 &pathTask);
00565 if (modeDock != NULL)
00566 {
00567 modeDock->checkDock();
00568 modeDock->addAsDefaultMode();
00569 modeDock->addToConfig(Aria::getConfig());
00570 modeDock->addControlCommands(&commands);
00571 }
00572
00573
00574
00575
00576
00577 modeStop.addAsDefaultMode();
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 ArServerHandlerMapping handlerMapping(&server, &robot, firstLaser,
00588 fileDir, "", true);
00589
00590
00591 handlerMapping.addMappingStartCallback(
00592 new ArFunctor1C<ArLocalizationTask, bool>
00593 (&locTask, &ArLocalizationTask::setIdleFlag, true));
00594
00595
00596 handlerMapping.addMappingEndCallback(
00597 new ArFunctor1C<ArLocalizationTask, bool>
00598 (&locTask, &ArLocalizationTask::setIdleFlag, false));
00599
00600
00601
00602 handlerMapping.addMappingStartCallback(actionLostPath.getDisableCB());
00603 handlerMapping.addMappingStartCallback(actionLostRatioDrive.getDisableCB());
00604 handlerMapping.addMappingStartCallback(actionLostWander.getDisableCB());
00605
00606
00607 handlerMapping.addMappingEndCallback(actionLostPath.getEnableCB());
00608 handlerMapping.addMappingEndCallback(actionLostRatioDrive.getEnableCB());
00609 handlerMapping.addMappingEndCallback(actionLostWander.getEnableCB());
00610
00611
00612
00613 handlerMapping.addMappingStartCallback(forbidden.getDisableCB());
00614
00615
00616 handlerMapping.addMappingEndCallback(forbidden.getEnableCB());
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 ArPoseStorage poseStorage(&robot);
00639 if (poseStorage.restorePose("robotPose"))
00640 serverLocHandler.setSimPose(robot.getPose());
00641 else
00642 robot.com(ArCommands::SIM_RESET);
00643
00644
00645
00646
00647
00648 #ifdef WIN32
00649
00650 ArLog::log(ArLog::Normal, "Note, file upload/download services are not implemented for Windows; not enabling them.");
00651 #else
00652
00653
00654
00655 ArServerFileLister fileLister(&server, fileDir);
00656 ArServerFileToClient fileToClient(&server, fileDir);
00657 ArServerFileFromClient fileFromClient(&server, fileDir, "/tmp");
00658 ArServerDeleteFileOnServer deleteFileOnServer(&server, fileDir);
00659
00660 #endif
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 ArHybridForwarderVideo videoForwarder(&server, "localhost", 7070);
00672
00673
00674
00675 ArPTZ *camera = NULL;
00676 ArServerHandlerCamera *handlerCamera = NULL;
00677 ArCameraCollection *cameraCollection = NULL;
00678
00679
00680 if (videoForwarder.isForwardingVideo())
00681 {
00682
00683 cameraCollection = new ArCameraCollection();
00684 cameraCollection->addCamera("Cam1", "VCC4", "Camera", "VCC4");
00685
00686 videoForwarder.setCameraName("Cam1");
00687 videoForwarder.addToCameraCollection(*cameraCollection);
00688
00689 bool invertedCamera = false;
00690 camera = new ArVCC4(&robot, invertedCamera,
00691 ArVCC4::COMM_UNKNOWN, true, true);
00692 camera->init();
00693
00694 handlerCamera = new ArServerHandlerCamera("Cam1",
00695 &server,
00696 &robot,
00697 camera,
00698 cameraCollection);
00699
00700 pathTask.addGoalFinishedCB(
00701 new ArFunctorC<ArServerHandlerCamera>(
00702 handlerCamera,
00703 &ArServerHandlerCamera::cameraModeLookAtGoalClearGoal));
00704 }
00705
00706
00707
00708
00709 if (cameraCollection != NULL) {
00710 new ArServerHandlerCameraCollection(&server, cameraCollection);
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 Aria::getConfig()->useArgumentParser(&parser);
00723
00724
00725 ArLog::log(ArLog::Normal, "Loading config file %s into ArConfig...", Arnl::getTypicalParamFileName());
00726 if (!Aria::getConfig()->parseFile(Arnl::getTypicalParamFileName()))
00727 {
00728 ArLog::log(ArLog::Normal, "Trouble loading configuration file, exiting");
00729 Aria::exit(5);
00730 }
00731
00732
00733 if (!simpleOpener.checkAndLog() || !parser.checkHelpAndWarnUnparsed())
00734 {
00735 logOptions(argv[0]);
00736 Aria::exit(6);
00737 }
00738
00739
00740 if (map.getFileName() == NULL || strlen(map.getFileName()) <= 0)
00741 {
00742 ArLog::log(ArLog::Normal, "");
00743 ArLog::log(ArLog::Normal, "### No map file is set up, you can make a map with the following procedure");
00744 ArLog::log(ArLog::Normal, " 0) You can find this information in README.txt or docs/Mapping.txt");
00745 ArLog::log(ArLog::Normal, " 1) Connect to this server with MobileEyes");
00746 ArLog::log(ArLog::Normal, " 2) Go to Tools->Map Creation->Start Scan");
00747 ArLog::log(ArLog::Normal, " 3) Give the map a name and hit okay");
00748 ArLog::log(ArLog::Normal, " 4) Drive the robot around your space (see docs/Mapping.txt");
00749 ArLog::log(ArLog::Normal, " 5) Go to Tools->Map Creation->Stop Scan");
00750 ArLog::log(ArLog::Normal, " 6) Start up Mapper3");
00751 ArLog::log(ArLog::Normal, " 7) Go to File->Open on Robot");
00752 ArLog::log(ArLog::Normal, " 8) Select the .2d you created");
00753 ArLog::log(ArLog::Normal, " 9) Create a .map");
00754 ArLog::log(ArLog::Normal, " 10) Go to File->Save on Robot");
00755 ArLog::log(ArLog::Normal, " 11) In MobileEyes, go to Tools->Robot Config");
00756 ArLog::log(ArLog::Normal, " 12) Choose the Files section");
00757 ArLog::log(ArLog::Normal, " 13) Enter the path and name of your new .map file for the value of the Map parameter.");
00758 ArLog::log(ArLog::Normal, " 14) Press OK and your new map should become the map used");
00759 ArLog::log(ArLog::Normal, "");
00760 }
00761
00762
00763 ArLog::log(ArLog::Normal, "");
00764 ArLog::log(ArLog::Normal,
00765 "Directory for maps and file serving: %s", fileDir);
00766
00767 ArLog::log(ArLog::Normal, "See the ARNL README.txt for more information");
00768 ArLog::log(ArLog::Normal, "");
00769
00770
00771
00772
00773
00774
00775
00776 locTask.localizeRobotAtHomeBlocking();
00777
00778
00779
00780 clientSwitch.runAsync();
00781
00782
00783 server.runAsync();
00784
00785
00786
00787
00788
00789
00790
00791 ArKeyHandler *keyHandler;
00792 if ((keyHandler = Aria::getKeyHandler()) == NULL)
00793 {
00794 keyHandler = new ArKeyHandler;
00795 Aria::setKeyHandler(keyHandler);
00796 robot.lock();
00797 robot.attachKeyHandler(keyHandler);
00798 robot.unlock();
00799 puts("Server running. To exit, press escape.");
00800 }
00801
00802
00803
00804 robot.enableMotors();
00805 robot.waitForRunExit();
00806 Aria::exit(0);
00807 }
00808