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