popupExample.cpp

Shows how to create popup windows in a client like MobileEyes

This example server program connects to a robot, and sends a message to clients (e.g. MobileEyes) to display in a dialog box when a sensor reading is detected in front of the robot within 1 meter. It also checks to see if that obstacle is not at the same angle as the previous detected obstacle -- it's probably the same one, unmoved -- to avoid sending repeated popups. The popup offers three choices, acknowlege and do nothing, turn the robot around 180 degrees, or exit the server.

00001 
00002 #include "Aria.h"
00003 #include "ArNetworking.h"
00004 
00016 class SensorDetectPopup
00017 {
00018 public:
00019   SensorDetectPopup(ArRobot *robot, ArServerHandlerPopup *popupServer);
00020 protected:
00021   ArRobot *myRobot;
00022   ArServerHandlerPopup *myPopupServer;
00023   bool myPopupDisplayed;
00024   double myPrevObstacleAngle;
00025   bool myPrevObstacleAngleValid;
00026   ArFunctor2C<SensorDetectPopup, ArTypes::Byte4, int> *myPopupClosedCB;
00027 
00028   void popupClosed(ArTypes::Byte4 popupID, int button);
00029   void sensorTask(void)  ;
00030 };
00031 
00032 
00033 int main(int argc, char **argv)
00034 {
00035   Aria::init();
00036   ArRobot robot;
00037   ArSonarDevice sonar;
00038   ArSick sick;
00039   robot.addRangeDevice(&sonar);
00040   ArServerBase server;
00041 
00042   // Argument parser:
00043   ArArgumentParser parser(&argc, argv);
00044 
00045   // Connector and server opener:
00046   ArSimpleConnector simpleConnector(&parser);
00047   ArServerSimpleOpener simpleOpener(&parser);
00048 
00049   // Get command-line and other parameters
00050   parser.loadDefaultArguments();
00051   if(!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed())
00052   {
00053     Aria::logOptions();
00054     return 1;
00055   }
00056 
00057   // connect to the robot
00058   if(!simpleConnector.connectRobot(&robot))
00059   {
00060     ArLog::log(ArLog::Terse, "popupExample: Error, could not connect to robot.");
00061     return 1;
00062   }
00063   robot.runAsync(true);
00064 
00065   // connect to the laser
00066   sick.runAsync();
00067   if(!simpleConnector.connectLaser(&sick))
00068   {
00069     ArLog::log(ArLog::Normal, "popupExample: Note, could not connect to a SICK laser.");
00070   }
00071   else
00072   {
00073     robot.addRangeDevice(&sick);
00074   }
00075 
00076   // Open the server
00077   if(!simpleOpener.open(&server))
00078   {
00079     ArLog::log(ArLog::Terse, "popupExample: Error, could not open server.");
00080     return 1;
00081   }
00082   server.runAsync();
00083   ArLog::log(ArLog::Normal, "popupExample: Server running. Press control-C to exit.");
00084   ArLog::log(ArLog::Normal, "popupExample: Each time an obstacle is detected near the robot, a new popup message will be created. Connect with MobileEyes to see them.");
00085 
00086   // Sends robot position etc.
00087   ArServerInfoRobot robotInfoServer(&server, &robot);
00088 
00089   // This service sends drawings e.g. showing range device positions
00090   ArServerInfoDrawings drawingsServer(&server);
00091   drawingsServer.addRobotsRangeDevices(&robot);
00092 
00093   // This service can send messages to clients to display as popup dialogs:
00094   ArServerHandlerPopup popupServer(&server);
00095 
00096   // This object contains the robot sensor interpretation task and creates
00097   // popups:
00098   SensorDetectPopup(&robot, &popupServer);
00099 
00100   robot.enableMotors();
00101   robot.waitForRunExit();
00102 
00103 }
00104 
00105 SensorDetectPopup::SensorDetectPopup(ArRobot *robot, ArServerHandlerPopup *popupServer) :
00106   myRobot(robot),
00107   myPopupServer(popupServer),
00108   myPopupDisplayed(false),
00109   myPrevObstacleAngleValid(false)
00110 {
00111  myRobot->lock();
00112  myRobot->addSensorInterpTask("sensorDetectPopup", 50, new ArFunctorC<SensorDetectPopup>(this, &SensorDetectPopup::sensorTask));
00113  myPopupClosedCB = new ArFunctor2C<SensorDetectPopup, ArTypes::Byte4, int>(this, &SensorDetectPopup::popupClosed);
00114  myRobot->unlock();
00115 }
00116 
00117 void SensorDetectPopup::sensorTask(void)
00118 {
00119   // Basic obstacle detection
00120   
00121   if (myPopupDisplayed) return;
00122   double detectAngle, detectRange;
00123   detectRange = myRobot->checkRangeDevicesCurrentPolar(-90, 90, &detectAngle);
00124   if (detectRange > 0 && detectRange <= 500)
00125   {
00126     if(myPrevObstacleAngleValid && fabs(detectAngle - myPrevObstacleAngle) < 0.0001)
00127       return;
00128     ArLog::log(ArLog::Normal, "popupExample: New obstacle detected at range %f, angle %f. Displaying popup dialog on client...", detectRange, detectAngle);
00129 
00130     ArServerHandlerPopupInfo info("popupExample", // ID
00131               "Object Detected",                  // Title
00132               "A range sensor detected a reading within 0.5 meters of the robot.", // Message
00133               ArServerHandlerPopup::INFORMATION,  // Type
00134               0,                                  // Default button
00135               0,                                  // Cancel/escape button
00136               5,                                 // Timeout (sec.)
00137               NULL,                               // Timeout String
00138               "OK", "Acknowleged.",               // Button 0 Label/Acknowlegement
00139               "Turn Around", "Requested rotate...",   // Button 1 Label/Acknowlegement
00140               "Shut Down", "Shutting down server..."  // Button 2 Label/Acknowlegement
00141              );
00142     int id = myPopupServer->createPopup(&info, myPopupClosedCB);
00143     ArLog::log(ArLog::Normal, "\t...Created a popup with ID=%d", id);
00144     myPopupDisplayed = true;
00145     myPrevObstacleAngle = detectAngle;
00146     myPrevObstacleAngleValid = true;
00147   }
00148 }
00149 
00150 void SensorDetectPopup::popupClosed(ArTypes::Byte4 popupID, int button)
00151 {
00152   // A client closed the popup
00153   ArLog::log(ArLog::Normal, "popupExample: a client closed popup dialog window with id=%d. Button=%d...", popupID, button);
00154   myPopupDisplayed = false;
00155 
00156   if(button < 0)
00157   {
00158     ArLog::log(ArLog::Normal, "\t...popup timed out or closed due to an error.");
00159     return;
00160   }
00161 
00162   if (button == 0)
00163   {
00164     ArLog::log(ArLog::Normal, "\t...OK pressed.");
00165     return;
00166   }
00167 
00168   if(button == 1)
00169   {
00170     ArLog::log(ArLog::Normal, "\t...180 degree rotate requested.");
00171     myRobot->lock();
00172     myRobot->setDeltaHeading(180);
00173     myRobot->unlock();
00174     return;
00175   }
00176 
00177   if(button == 2)
00178   {
00179     ArLog::log(ArLog::Normal, "\t...exit requested.");
00180     myRobot->stopRunning();
00181     Aria::shutdown();
00182     Aria::exit(0);
00183   }
00184 }
00185 
00186 

Generated on Fri Jul 31 12:37:28 2009 for ArNetworking by  doxygen 1.4.7