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
1.4.7