Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

ArServerHandlerMapping.cpp

Go to the documentation of this file.
00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArServerHandlerMapping.h"
00029 
00043 AREXPORT ArServerHandlerMapping::ArServerHandlerMapping(
00044         ArServerBase *server, ArRobot *robot, ArSick *sick,
00045         const char *baseDirectory, const char *tempDirectory,
00046         bool useReflectorValues) :
00047   myMappingStartCB(this, &ArServerHandlerMapping::serverMappingStart),
00048   myMappingEndCB(this, &ArServerHandlerMapping::serverMappingEnd),
00049   myMappingStatusCB(this, &ArServerHandlerMapping::serverMappingStatus),
00050   myPacketHandlerCB(this, &ArServerHandlerMapping::packetHandler),
00051   myLoopStartCB(this, &ArServerHandlerMapping::simpleLoopStart),
00052   myLoopEndCB(this, &ArServerHandlerMapping::simpleLoopEnd)
00053 {
00054   myServer = server;
00055   myRobot = robot;
00056   mySick = sick;
00057   myUseReflectorValues = useReflectorValues;
00058 
00059   if (baseDirectory != NULL && strlen(baseDirectory) > 0)
00060     myBaseDirectory = baseDirectory;
00061   else
00062     myBaseDirectory = "";
00063   if (tempDirectory != NULL && strlen(tempDirectory) > 0)
00064     myTempDirectory = tempDirectory;
00065   else
00066     myTempDirectory = myBaseDirectory;
00067 
00068   if (myServer != NULL)
00069   {
00070     myServer->addData("mappingStart", "Starts making a map",
00071                       &myMappingStartCB, "string: name of map file",
00072                       "byte: 0 (started mapping), 1 (already mapping), 2 (could not start map)",
00073                       "Mapping", "RETURN_SINGLE");
00074     myServer->addData("mappingEnd", "Stops making a map",
00075                       &myMappingEndCB, "none",
00076                       "byte: 0 (ended mapping), 1 (no mapping to end), 2 (could not move temporary file to permanent file)", 
00077                       "Mapping", "RETURN_SINGLE");
00078     myServer->addData("mappingStatus", "Gets the status of mapping",
00079                       &myMappingStatusCB, "none",
00080               "string: mapName if mapping, empty string if not mapping", 
00081                       "RobotInfo", "RETURN_SINGLE");
00082     myServer->addData("mappingStatusBroadcast", "Gets the status of mapping, also sent when mapping starts or ends (this is a new/better mappingStatus)",
00083                       &myMappingStatusCB, "none",
00084               "string: mapName if mapping, empty string if not mapping", 
00085                       "RobotInfo", "RETURN_SINGLE");
00086   }
00087   mySickLogger = NULL;
00088   myMapName = "";
00089   myFileName = "";
00090   myHandlerCommands = NULL;
00091   
00092   myPacketHandlerCB.setName("ArServerHandlerMapping");
00093   myRobot->addPacketHandler(&myPacketHandlerCB);
00094 }
00095 
00096 AREXPORT ArServerHandlerMapping::~ArServerHandlerMapping()
00097 {
00098   delete mySickLogger;
00099   mySickLogger = NULL;
00100 }
00101 
00102 AREXPORT void ArServerHandlerMapping::serverMappingStart(
00103         ArServerClient *client, ArNetPacket *packet)
00104 {
00105   ArNetPacket sendPacket;
00106   char buf[512];
00107   packet->bufToStr(buf, sizeof(buf));
00108 
00109   // see if we're already mapping
00110   if (mySickLogger != NULL)
00111   {
00112     ArLog::log(ArLog::Normal, "MappingStart: Map already being made");
00113     sendPacket.byteToBuf(1);
00114     if (client != NULL)
00115       client->sendPacketTcp(&sendPacket);
00116     return;
00117   }
00118 
00119   // call our mapping started callbacks
00120   std::list<ArFunctor *>::iterator fit;
00121   for (fit = myMappingStartCallbacks.begin(); 
00122        fit != myMappingStartCallbacks.end(); 
00123        fit++)
00124     (*fit)->invoke();
00125 
00126   myRobot->lock();
00127   // lower case everything (to avoid case conflicts)
00128   ArUtil::lower(buf, buf, sizeof(buf));
00129   myMapName = buf;
00130 
00131   myFileName = myMapName;
00132   if (strstr(myMapName.c_str(), ".2d") == NULL)
00133     myFileName += ".2d";
00134 
00135   mySickLogger = new ArSickLogger(myRobot, mySick, 300, 25, myFileName.c_str(),
00136                                   true, Aria::getJoyHandler(), 
00137                                   myTempDirectory.c_str(), 
00138                                   myUseReflectorValues,
00139                                   Aria::getRobotJoyHandler());
00140   if (mySickLogger == NULL)
00141   {
00142     ArLog::log(ArLog::Normal, "MappingStart: mySickLogger == NULL");
00143     sendPacket.byteToBuf(2);
00144     if (client != NULL)
00145       client->sendPacketTcp(&sendPacket);
00146     myMapName = "";
00147     myFileName = "";
00148     myRobot->unlock();
00149     return;
00150   }
00151   if (!mySickLogger->wasFileOpenedSuccessfully())
00152   {
00153     ArLog::log(ArLog::Normal, "MappingStart: Cannot open map file %s", 
00154                myFileName.c_str());
00155     sendPacket.byteToBuf(2);
00156     if (client != NULL)
00157       client->sendPacketTcp(&sendPacket);
00158     myMapName = "";
00159     myFileName = "";
00160     delete mySickLogger;
00161     mySickLogger = NULL;
00162     myRobot->unlock();
00163     return;
00164   }
00165 
00166   // toss our strings for the start on there
00167   std::list<std::string>::iterator it;
00168   
00169   for (it = myStringsForStartOfLog.begin(); 
00170        it != myStringsForStartOfLog.end(); 
00171        it++)
00172     mySickLogger->addInfoToLogPlain((*it).c_str());
00173   myRobot->unlock();
00174   
00175   
00176   ArLog::log(ArLog::Normal, "MappingStart: Map %s started", 
00177              myFileName.c_str());
00178   sendPacket.byteToBuf(0);
00179   if (client != NULL)
00180     client->sendPacketTcp(&sendPacket);
00181   
00182   ArNetPacket broadcastPacket;
00183   broadcastPacket.strToBuf(myFileName.c_str());
00184   myServer->broadcastPacketTcp(&broadcastPacket, "mappingStatusBroadcast");
00185 }
00186 
00187 
00188 AREXPORT void ArServerHandlerMapping::serverMappingEnd(
00189         ArServerClient *client, ArNetPacket *packet)
00190 {
00191   std::list<ArFunctor *>::iterator fit;
00192 
00193   ArNetPacket sendPacket;
00194   if (mySickLogger == NULL)
00195   {
00196     ArLog::log(ArLog::Normal, "MappingEnd: No map being made");
00197     sendPacket.byteToBuf(1);
00198     if (client != NULL)
00199       client->sendPacketTcp(&sendPacket);
00200     return;
00201   }
00202 
00203   myRobot->lock();
00204   delete mySickLogger;
00205   mySickLogger = NULL;
00206 
00207   // now, if our temp directory and base directory are different we
00208   // need to move it and put the result in the packet, otherwise put
00209   // in we're okay
00210   if (ArUtil::strcasecmp(myBaseDirectory, myTempDirectory) != 0)
00211   {
00212 #ifndef WIN32
00213     char *mvName = "mv";
00214 #else
00215     char *mvName = "move";
00216 #endif
00217     char systemBuf[6400];
00218     char fromBuf[1024];
00219     char toBuf[1024];
00220 
00221     if (myTempDirectory.size() > 0)
00222       snprintf(fromBuf, sizeof(fromBuf), "%s%s", 
00223                myTempDirectory.c_str(), myFileName.c_str());
00224     else
00225       snprintf(fromBuf, sizeof(fromBuf), "%s", myFileName.c_str());
00226     ArUtil::fixSlashes(fromBuf, sizeof(fromBuf));
00227 
00228     if (myTempDirectory.size() > 0)
00229       snprintf(toBuf, sizeof(toBuf), "%s%s", 
00230                myBaseDirectory.c_str(), myFileName.c_str());
00231     else
00232       snprintf(toBuf, sizeof(toBuf), "%s", myFileName.c_str());
00233     ArUtil::fixSlashes(toBuf, sizeof(toBuf));
00234 
00235     sprintf(systemBuf, "%s \"%s\" \"%s\"", mvName, fromBuf, toBuf);
00236     ArLog::log(ArLog::Verbose, "Moving with '%s'", systemBuf);
00237     // call our pre move callbacks
00238     for (fit = myPreMoveCallbacks.begin(); 
00239          fit != myPreMoveCallbacks.end(); 
00240          fit++)
00241       (*fit)->invoke();
00242 
00243     // move file
00244     int ret;
00245     if ((ret = system(systemBuf)) == 0)
00246     {
00247       ArLog::log(ArLog::Verbose, "ArServerHandlerMapping: Moved file %s (with %s)", 
00248                  myFileName.c_str(), systemBuf);
00249       sendPacket.byteToBuf(0);
00250     }
00251     else
00252     {
00253       ArLog::log(ArLog::Normal, 
00254                  "ArServerHandlerMapping: Couldn't move file for %s (ret of '%s' is %d) removing file", 
00255                  myFileName.c_str(), systemBuf, ret);
00256       unlink(fromBuf);
00257       sendPacket.uByte2ToBuf(2);
00258     }
00259 
00260     // call our post move callbacks
00261     for (fit = myPostMoveCallbacks.begin(); 
00262          fit != myPostMoveCallbacks.end(); 
00263          fit++)
00264       (*fit)->invoke();
00265 
00266   }
00267   else
00268   {
00269     // just put in things are okay, it'll get sent below
00270     sendPacket.byteToBuf(0);
00271   }
00272 
00273 
00274   ArLog::log(ArLog::Normal, "MappingEnd: Stopped mapping %s", 
00275              myFileName.c_str());
00276   myMapName = "";
00277   myFileName = "";
00278 
00279   myRobot->unlock();
00280   if (client != NULL)
00281     client->sendPacketTcp(&sendPacket);
00282 
00283   // call our mapping started callbacks
00284   for (fit = myMappingEndCallbacks.begin(); 
00285        fit != myMappingEndCallbacks.end(); 
00286        fit++)
00287     (*fit)->invoke();
00288 
00289   ArNetPacket broadcastPacket;
00290   broadcastPacket.strToBuf(myFileName.c_str());
00291   myServer->broadcastPacketTcp(&broadcastPacket, "mappingStatusBroadcast");
00292 }
00293 
00294 
00295 AREXPORT void ArServerHandlerMapping::serverMappingStatus(
00296         ArServerClient *client, ArNetPacket *packet)
00297 {
00298   ArNetPacket sendPacket;
00299   sendPacket.strToBuf(myMapName.c_str());
00300   client->sendPacketTcp(&sendPacket);
00301 }
00302 
00303 AREXPORT void ArServerHandlerMapping::addStringForStartOfLogs(
00304         const char *str, ArListPos::Pos position)
00305 {
00306   if (position == ArListPos::FIRST)
00307     myStringsForStartOfLog.push_front(str);
00308   else if (position == ArListPos::LAST)
00309     myStringsForStartOfLog.push_back(str);
00310   else 
00311     ArLog::log(ArLog::Terse, "ArServerHandlerMapping::addStringForStartOfLogs: Invalid position.");
00312 }
00313 
00314 AREXPORT void ArServerHandlerMapping::remStringForStartOfLogs(
00315         char *str)
00316 {
00317   myStringsForStartOfLog.remove(str);
00318 }
00319 
00320 AREXPORT void ArServerHandlerMapping::addMappingStartCallback(
00321         ArFunctor *functor, ArListPos::Pos position)
00322 {
00323   if (position == ArListPos::FIRST)
00324     myMappingStartCallbacks.push_front(functor);
00325   else if (position == ArListPos::LAST)
00326     myMappingStartCallbacks.push_back(functor);
00327   else
00328     ArLog::log(ArLog::Terse, 
00329        "ArServerHandlerMapping::addMappingStartCallback: Invalid position.");
00330 }
00331 
00332 AREXPORT void ArServerHandlerMapping::remMappingStartCallback(
00333         ArFunctor *functor)
00334 {
00335   myMappingStartCallbacks.remove(functor);
00336 }
00337 
00338 AREXPORT void ArServerHandlerMapping::addMappingEndCallback(
00339         ArFunctor *functor, ArListPos::Pos position)
00340 {
00341   if (position == ArListPos::FIRST)
00342     myMappingEndCallbacks.push_front(functor);
00343   else if (position == ArListPos::LAST)
00344     myMappingEndCallbacks.push_back(functor);
00345   else
00346     ArLog::log(ArLog::Terse, 
00347        "ArServerHandlerMapping::addMappingEndCallback: Invalid position.");
00348 }
00349 
00350 AREXPORT void ArServerHandlerMapping::remMappingEndCallback(
00351         ArFunctor *functor)
00352 {
00353   myMappingEndCallbacks.remove(functor);
00354 }
00355 
00356 AREXPORT void ArServerHandlerMapping::addPreMoveCallback(
00357         ArFunctor *functor, ArListPos::Pos position)
00358 {
00359   if (position == ArListPos::FIRST)
00360     myPreMoveCallbacks.push_front(functor);
00361   else if (position == ArListPos::LAST)
00362     myPreMoveCallbacks.push_back(functor);
00363   else
00364     ArLog::log(ArLog::Terse, 
00365        "ArServerHandlerMapping::addPreMoveCallback: Invalid position.");
00366 }
00367 
00368 AREXPORT void ArServerHandlerMapping::remPreMoveCallback(
00369         ArFunctor *functor)
00370 {
00371   myPreMoveCallbacks.remove(functor);
00372 }
00373 
00374 AREXPORT void ArServerHandlerMapping::addPostMoveCallback(
00375         ArFunctor *functor, ArListPos::Pos position)
00376 {
00377   if (position == ArListPos::FIRST)
00378     myPostMoveCallbacks.push_front(functor);
00379   else if (position == ArListPos::LAST)
00380     myPostMoveCallbacks.push_back(functor);
00381   else
00382     ArLog::log(ArLog::Terse, 
00383        "ArServerHandlerMapping::addPostMoveCallback: Invalid position.");
00384 }
00385 
00386 AREXPORT void ArServerHandlerMapping::remPostMoveCallback(
00387         ArFunctor *functor)
00388 {
00389   myPostMoveCallbacks.remove(functor);
00390 }
00391 
00392 AREXPORT void ArServerHandlerMapping::addSimpleCommands(
00393         ArServerHandlerCommands *handlerCommands)
00394 {
00395   myHandlerCommands = handlerCommands;
00396   myHandlerCommands->addStringCommand(
00397           "mappingLoopStart", 
00398           "If mapping is happening it starts a new loop with the tag of the given string", 
00399           &myLoopStartCB);
00400 
00401   myHandlerCommands->addStringCommand(
00402           "mappingLoopEnd", 
00403           "If mapping is happening it ends a loop with the tag of the given string", 
00404           &myLoopEndCB);
00405 }
00406 
00407 AREXPORT void ArServerHandlerMapping::simpleLoopStart(ArArgumentBuilder *arg)
00408 {
00409   if (mySickLogger != NULL) 
00410     mySickLogger->addTagToLog("loop start %s", arg->getFullString());
00411 }
00412 
00413 AREXPORT void ArServerHandlerMapping::simpleLoopEnd(ArArgumentBuilder *arg)
00414 {
00415   if (mySickLogger != NULL) 
00416     mySickLogger->addTagToLog("loop end %s", arg->getFullString());
00417 }
00418 
00420 AREXPORT bool ArServerHandlerMapping::packetHandler(ArRobotPacket *packet)
00421 {
00422   if (packet->getID() != 0x97)
00423     return false;
00424 
00425   myRobot->unlock();
00426   char argument = packet->bufToByte();
00427   if (argument == 1)
00428   {
00429     // see if we're already mapping
00430     if (mySickLogger != NULL)
00431     {
00432       ArLog::log(ArLog::Normal, 
00433                  "ArServerHandlerMapping::packetHandler: Start scan requested when already mapping");
00434     }
00435     else
00436     {
00437       // build a name
00438       time_t now;
00439       struct tm nowStruct;
00440       now = time(NULL);
00441       char buf[1024];
00442 
00443           if (ArUtil::localtime(&now, &nowStruct))
00444       {
00445         sprintf(buf, "%02d%02d%02d_%02d%02d%02d", 
00446                 (nowStruct.tm_year%100), nowStruct.tm_mon+1, nowStruct.tm_mday, 
00447                 nowStruct.tm_hour, nowStruct.tm_min, nowStruct.tm_sec);
00448       }
00449       else
00450       {
00451         ArLog::log(ArLog::Normal, 
00452                    "ArServerHandlerMapping::packetHandler: Could not make good packet name (error getting time), so just naming it \"lcd\"");
00453         sprintf(buf, "lcd");
00454       }
00455 
00456       ArLog::log(ArLog::Normal, "Starting scan '%s' from LCD", buf);
00457       ArNetPacket fakePacket;
00458       fakePacket.strToBuf(buf);
00459       fakePacket.finalizePacket();
00460       serverMappingStart(NULL, &fakePacket);
00461     }
00462   }
00463   else if (argument == 0)
00464   {
00465     if (mySickLogger == NULL)
00466     {
00467       ArLog::log(ArLog::Normal, 
00468                  "ArServerHandlerMapping::packetHandler: Stop scan requested when not mapping");
00469     }
00470     else
00471     {
00472       ArLog::log(ArLog::Normal, "Stopping scan from LCD");
00473       serverMappingEnd(NULL, NULL);
00474     }
00475   }
00476   else
00477   {
00478     ArLog::log(ArLog::Normal, "ArServerHandlerMapping::packetHandler: Unknown scan argument %d", argument);
00479   }
00480   myRobot->lock();
00481   return true;
00482 }

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0