#include "Aria.h"
#include "ArNetworking.h"
#include "Arnl.h"
#include "ArLocalizationTask.h"
#include "ArDocking.h"
void logOptions(const char *progname)
{
ArLog::log(ArLog::Normal, "Usage: %s [options]\n", progname);
ArLog::log(ArLog::Normal, "[options] are any program options listed below, or any ARNL configuration");
ArLog::log(ArLog::Normal, "parameters as -name <value>, see params/arnl.p for list.");
ArLog::log(ArLog::Normal, "For example, -map <map file>.");
Aria::logOptions();
}
bool gyroErrored = false;
const char* getGyroStatusString(ArRobot* robot)
{
if(!robot || !robot->getOrigRobotConfig() || robot->getOrigRobotConfig()->getGyroType() < 2) return "N/A";
if(robot->getFaultFlags() & ArUtil::BIT4)
{
gyroErrored = true;
return "ERROR/OFF";
}
if(gyroErrored)
{
return "OK but error before";
}
return "OK";
}
int main(int argc, char **argv)
{
Aria::init();
Arnl::init();
ArRobot robot;
ArArgumentParser parser(&argc, argv);
ArRobotConnector robotConnector(&parser, &robot);
if (!robotConnector.connectRobot())
{
ArLog::log(ArLog::Normal, "Error: Could not connect to robot... exiting");
Aria::exit(3);
}
char fileDir[1024];
ArUtil::addDirectories(fileDir, sizeof(fileDir), Aria::getDirectory(),
"examples");
ArLog::log(ArLog::Normal, "Installation directory is: %s\nMaps directory is: %s\n", Aria::getDirectory(), fileDir);
ArLog::addToConfig(Aria::getConfig());
ArAnalogGyro gyro(&robot);
ArServerBase server;
ArServerSimpleOpener simpleOpener(&parser);
ArLaserConnector laserConnector(&parser, &robot, &robotConnector);
parser.addDefaultArgument("-connectLaser");
parser.loadDefaultArguments();
if (!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
{
logOptions(argv[0]);
Aria::exit(1);
}
ArGlobalFunctor1<int> shutdownFunctor(&Aria::exit, 9);
robot.addDisconnectOnErrorCB(&shutdownFunctor);
ArSonarDevice sonarDev;
robot.addRangeDevice(&sonarDev);
ArRobotConfig robotConfig(&robot);
robotConfig.addAnalogGyro(&gyro);
robot.runAsync(true);
if (!laserConnector.connectLasers())
{
ArLog::log(ArLog::Normal, "Could not connect to all lasers... exiting\n");
Aria::exit(2);
}
robot.lock();
ArLaser *firstLaser = robot.findLaser(1);
if (firstLaser == NULL || !firstLaser->isConnected())
{
ArLog::log(ArLog::Normal, "Did not have laser 1 or it is not connected, cannot start localization and/or mapping... exiting");
Aria::exit(2);
}
robot.unlock();
ArMap map(fileDir);
map.setIgnoreEmptyFileName(true);
map.setIgnoreCase(true);
ArPathPlanningTask pathTask(&robot, &sonarDev, &map);
ArLog::log(ArLog::Normal, "Creating laser localization task");
ArLocalizationTask locTask(&robot, firstLaser, &map);
std::map<int, ArLaser *>::iterator laserIt;
for (laserIt = robot.getLaserMap()->begin();
laserIt != robot.getLaserMap()->end();
laserIt++)
{
int laserNum = (*laserIt).first;
ArLaser *laser = (*laserIt).second;
if(!laser->isConnected())
continue;
laser->addDisconnectOnErrorCB(&shutdownFunctor);
laser->setCumulativeBufferSize(200);
pathTask.addRangeDevice(laser, ArPathPlanningTask::BOTH);
laser->setCumulativeCleanOffset(laserNum * 100);
laser->resetLastCumulativeCleanTime();
std::string laserPacketCountName;
laserPacketCountName = laser->getName();
laserPacketCountName += " Packet Count";
Aria::getInfoGroup()->addStringInt(
laserPacketCountName.c_str(), 10,
new ArRetFunctorC<int, ArLaser>(laser,
&ArLaser::getReadingCount));
}
ArClientSwitchManager clientSwitch(&server, &parser);
if (!simpleOpener.open(&server, fileDir, 240))
{
ArLog::log(ArLog::Normal, "Error: Could not open server.");
exit(2);
}
ArServerHandlerMultiRobot *handlerMultiRobot = NULL;
ArMultiRobotRangeDevice *multiRobotRangeDevice = NULL;
ArServerHandlerMultiRobotPeer *multiRobotPeer = NULL;
ArMultiRobotPeerRangeDevice *multiRobotPeerRangeDevice = NULL;
bool usingCentralServer = false;
if(clientSwitch.getCentralServerHostName() != NULL)
usingCentralServer = true;
if (usingCentralServer)
{
handlerMultiRobot = new ArServerHandlerMultiRobot(&server, &robot,
&pathTask,
&locTask, &map);
multiRobotRangeDevice = new ArMultiRobotRangeDevice(&server);
robot.addRangeDevice(multiRobotRangeDevice);
pathTask.addRangeDevice(multiRobotRangeDevice,
ArPathPlanningTask::BOTH);
multiRobotRangeDevice->setCurrentDrawingData(
new ArDrawingData("polyDots", ArColor(125, 125, 0),
100, 73, 1000), true);
multiRobotRangeDevice->setCumulativeDrawingData(
new ArDrawingData("polyDots", ArColor(125, 0, 125),
100, 72, 1000), true);
locTask.setMultiRobotCallback(multiRobotRangeDevice->getOtherRobotsCB());
}
else
{
pathTask.setUseCollisionRangeForPlanningFlag(true);
multiRobotPeerRangeDevice = new ArMultiRobotPeerRangeDevice(&map);
multiRobotPeer = new ArServerHandlerMultiRobotPeer(&server, &robot,
&pathTask, &locTask);
multiRobotPeer->setNewPrecedenceCallback(
multiRobotPeerRangeDevice->getSetPrecedenceCallback());
multiRobotPeer->setNewFingerprintCallback(
multiRobotPeerRangeDevice->getSetFingerprintCallback());
multiRobotPeerRangeDevice->setChangeFingerprintCB(
multiRobotPeer->getChangeFingerprintCB());
robot.addRangeDevice(multiRobotPeerRangeDevice);
pathTask.addRangeDevice(multiRobotPeerRangeDevice,
ArPathPlanningTask::BOTH);
multiRobotPeerRangeDevice->setCurrentDrawingData(
new ArDrawingData("polyDots", ArColor(125, 125, 0),
100, 72, 1000), true);
multiRobotPeerRangeDevice->setCumulativeDrawingData(
new ArDrawingData("polyDots", ArColor(125, 0, 125),
100, 72, 1000), true);
locTask.setMultiRobotCallback(
multiRobotPeerRangeDevice->getOtherRobotsCB());
}
robot.lock();
ArIRs irs;
robot.addRangeDevice(&irs);
pathTask.addRangeDevice(&irs, ArPathPlanningTask::CURRENT);
ArBumpers bumpers;
robot.addRangeDevice(&bumpers);
pathTask.addRangeDevice(&bumpers, ArPathPlanningTask::CURRENT);
ArForbiddenRangeDevice forbidden(&map);
robot.addRangeDevice(&forbidden);
pathTask.addRangeDevice(&forbidden, ArPathPlanningTask::CURRENT);
robot.unlock();
ArActionSlowDownWhenNotCertain actionSlowDown(&locTask);
pathTask.getPathPlanActionGroup()->addAction(&actionSlowDown, 140);
ArActionLost actionLostPath(&locTask, &pathTask);
pathTask.getPathPlanActionGroup()->addAction(&actionLostPath, 150);
ArGlobalReplanningRangeDevice replanDev(&pathTask);
ArServerInfoDrawings drawings(&server);
drawings.addRobotsRangeDevices(&robot);
drawings.addRangeDevice(&replanDev);
ArDrawingData drawingDataP("polyLine", ArColor(200,200,200), 1, 75);
ArFunctor2C<ArPathPlanningTask, ArServerClient *, ArNetPacket *>
drawingFunctorP(&pathTask, &ArPathPlanningTask::drawSearchRectangle);
drawings.addDrawing(&drawingDataP, "Local Plan Area", &drawingFunctorP);
ArDrawingData drawingDataL("polyDots", ArColor(0,255,0), 100, 75);
ArFunctor2C<ArLocalizationTask, ArServerClient *, ArNetPacket *>
drawingFunctorL(&locTask, &ArLocalizationTask::drawRangePoints);
drawings.addDrawing(&drawingDataL, "Localization Points", &drawingFunctorL);
ArServerHandlerCommands commands(&server);
ArServerInfoRobot serverInfoRobot(&server, &robot);
ArServerInfoSensor serverInfoSensor(&server, &robot);
ArServerInfoPath serverInfoPath(&server, &robot, &pathTask);
serverInfoPath.addSearchRectangleDrawing(&drawings);
serverInfoPath.addControlCommands(&commands);
ArServerInfoLocalization serverInfoLocalization(&server, &robot, &locTask);
ArServerHandlerLocalization serverLocHandler(&server, &robot, &locTask);
ArServerHandlerMap serverMap(&server, &map);
ArServerSimpleComUC uCCommands(&commands, &robot);
ArServerSimpleComMovementLogging loggingCommands(&commands, &robot);
ArServerSimpleComLogRobotConfig configCommands(&commands, &robot);
ArServerHandlerCommMonitor handlerCommMonitor(&server);
ArServerHandlerConfig handlerConfig(&server, Aria::getConfig(),
Arnl::getTypicalDefaultParamFileName(),
Aria::getDirectory());
ArServerModeGoto modeGoto(&server, &robot, &pathTask, &map,
locTask.getRobotHome(),
locTask.getRobotHomeCallback());
ArServerModeStop modeStop(&server, &robot);
ArSonarAutoDisabler sonarAutoDisabler(&robot);
ArServerModeRatioDrive modeRatioDrive(&server, &robot);
ArActionLost actionLostRatioDrive(&locTask, &pathTask, &modeRatioDrive);
modeRatioDrive.getActionGroup()->addAction(&actionLostRatioDrive, 110);
modeRatioDrive.addToConfig(Aria::getConfig(), "Teleop settings");
modeRatioDrive.addControlCommands(&commands);
ArServerModeWander modeWander(&server, &robot);
ArActionLost actionLostWander(&locTask, &pathTask, &modeWander);
modeWander.getActionGroup()->addAction(&actionLostWander, 110);
ArServerInfoStrings stringInfo(&server);
Aria::getInfoGroup()->addAddStringCallback(stringInfo.getAddStringFunctor());
Aria::getInfoGroup()->addStringInt(
"Motor Packet Count", 10,
new ArConstRetFunctorC<int, ArRobot>(&robot,
&ArRobot::getMotorPacCount));
Aria::getInfoGroup()->addStringDouble(
"Laser Localization Score", 8,
new ArRetFunctorC<double, ArLocalizationTask>(
&locTask, &ArLocalizationTask::getLocalizationScore),
"%.03f");
Aria::getInfoGroup()->addStringInt(
"Laser Loc Num Samples", 8,
new ArRetFunctorC<int, ArLocalizationTask>(
&locTask, &ArLocalizationTask::getCurrentNumSamples),
"%4d");
if(robot.getOrigRobotConfig() && robot.getOrigRobotConfig()->getGyroType() > 1)
{
Aria::getInfoGroup()->addStringString(
"Gyro/IMU Status", 10,
new ArGlobalRetFunctor1<const char*, ArRobot*>(&getGyroStatusString, &robot)
);
}
ArServerModeDock *modeDock = NULL;
modeDock = ArServerModeDock::createDock(&server, &robot, &locTask,
&pathTask);
if (modeDock != NULL)
{
modeDock->checkDock();
modeDock->addAsDefaultMode();
modeDock->addToConfig(Aria::getConfig());
modeDock->addControlCommands(&commands);
}
modeStop.addAsDefaultMode();
ArServerHandlerMapping handlerMapping(&server, &robot, firstLaser,
fileDir, "", true);
handlerMapping.addMappingStartCallback(
new ArFunctor1C<ArLocalizationTask, bool>
(&locTask, &ArLocalizationTask::setIdleFlag, true));
handlerMapping.addMappingEndCallback(
new ArFunctor1C<ArLocalizationTask, bool>
(&locTask, &ArLocalizationTask::setIdleFlag, false));
handlerMapping.addMappingStartCallback(actionLostPath.getDisableCB());
handlerMapping.addMappingStartCallback(actionLostRatioDrive.getDisableCB());
handlerMapping.addMappingStartCallback(actionLostWander.getDisableCB());
handlerMapping.addMappingEndCallback(actionLostPath.getEnableCB());
handlerMapping.addMappingEndCallback(actionLostRatioDrive.getEnableCB());
handlerMapping.addMappingEndCallback(actionLostWander.getEnableCB());
handlerMapping.addMappingStartCallback(forbidden.getDisableCB());
handlerMapping.addMappingEndCallback(forbidden.getEnableCB());
ArPoseStorage poseStorage(&robot);
if (poseStorage.restorePose("robotPose"))
serverLocHandler.setSimPose(robot.getPose());
else
robot.com(ArCommands::SIM_RESET);
#ifdef WIN32
ArLog::log(ArLog::Normal, "Note, file upload/download services are not implemented for Windows; not enabling them.");
#else
ArServerFileLister fileLister(&server, fileDir);
ArServerFileToClient fileToClient(&server, fileDir);
ArServerFileFromClient fileFromClient(&server, fileDir, "/tmp");
ArServerDeleteFileOnServer deleteFileOnServer(&server, fileDir);
#endif
ArHybridForwarderVideo videoForwarder(&server, "localhost", 7070);
ArPTZ *camera = NULL;
ArServerHandlerCamera *handlerCamera = NULL;
ArCameraCollection *cameraCollection = NULL;
if (videoForwarder.isForwardingVideo())
{
cameraCollection = new ArCameraCollection();
cameraCollection->addCamera("Cam1", "VCC4", "Camera", "VCC4");
videoForwarder.setCameraName("Cam1");
videoForwarder.addToCameraCollection(*cameraCollection);
bool invertedCamera = false;
camera = new ArVCC4(&robot, invertedCamera,
ArVCC4::COMM_UNKNOWN, true, true);
camera->init();
handlerCamera = new ArServerHandlerCamera("Cam1",
&server,
&robot,
camera,
cameraCollection);
pathTask.addGoalFinishedCB(
new ArFunctorC<ArServerHandlerCamera>(
handlerCamera,
&ArServerHandlerCamera::cameraModeLookAtGoalClearGoal));
}
if (cameraCollection != NULL) {
new ArServerHandlerCameraCollection(&server, cameraCollection);
}
Aria::getConfig()->useArgumentParser(&parser);
ArLog::log(ArLog::Normal, "Loading config file %s into ArConfig...", Arnl::getTypicalParamFileName());
if (!Aria::getConfig()->parseFile(Arnl::getTypicalParamFileName()))
{
ArLog::log(ArLog::Normal, "Trouble loading configuration file, exiting");
Aria::exit(5);
}
if (!simpleOpener.checkAndLog() || !parser.checkHelpAndWarnUnparsed())
{
logOptions(argv[0]);
Aria::exit(6);
}
if (map.getFileName() == NULL || strlen(map.getFileName()) <= 0)
{
ArLog::log(ArLog::Normal, "");
ArLog::log(ArLog::Normal, "### No map file is set up, you can make a map with the following procedure");
ArLog::log(ArLog::Normal, " 0) You can find this information in README.txt or docs/Mapping.txt");
ArLog::log(ArLog::Normal, " 1) Connect to this server with MobileEyes");
ArLog::log(ArLog::Normal, " 2) Go to Tools->Map Creation->Start Scan");
ArLog::log(ArLog::Normal, " 3) Give the map a name and hit okay");
ArLog::log(ArLog::Normal, " 4) Drive the robot around your space (see docs/Mapping.txt");
ArLog::log(ArLog::Normal, " 5) Go to Tools->Map Creation->Stop Scan");
ArLog::log(ArLog::Normal, " 6) Start up Mapper3");
ArLog::log(ArLog::Normal, " 7) Go to File->Open on Robot");
ArLog::log(ArLog::Normal, " 8) Select the .2d you created");
ArLog::log(ArLog::Normal, " 9) Create a .map");
ArLog::log(ArLog::Normal, " 10) Go to File->Save on Robot");
ArLog::log(ArLog::Normal, " 11) In MobileEyes, go to Tools->Robot Config");
ArLog::log(ArLog::Normal, " 12) Choose the Files section");
ArLog::log(ArLog::Normal, " 13) Enter the path and name of your new .map file for the value of the Map parameter.");
ArLog::log(ArLog::Normal, " 14) Press OK and your new map should become the map used");
ArLog::log(ArLog::Normal, "");
}
ArLog::log(ArLog::Normal, "");
ArLog::log(ArLog::Normal,
"Directory for maps and file serving: %s", fileDir);
ArLog::log(ArLog::Normal, "See the ARNL README.txt for more information");
ArLog::log(ArLog::Normal, "");
locTask.localizeRobotAtHomeBlocking();
clientSwitch.runAsync();
server.runAsync();
ArKeyHandler *keyHandler;
if ((keyHandler = Aria::getKeyHandler()) == NULL)
{
keyHandler = new ArKeyHandler;
Aria::setKeyHandler(keyHandler);
robot.lock();
robot.attachKeyHandler(keyHandler);
robot.unlock();
puts("Server running. To exit, press escape.");
}
robot.enableMotors();
robot.waitForRunExit();
Aria::exit(0);
}