The central server can also hold common configuration options and/or a common map.
You use this example program as-is, or add to it to implement multi-robot coordination etc.
Note, this server uses the default server port, 7272. Any other servers running on the same computer will need to use a different port (e.g. use the -serverPort argument).
00001 #include "Aria.h" 00002 #include "ArNetworking.h" 00003 #include "Arnl.h" 00004 00005 00033 // Called whenever a new robot server connects and a forwarder is created for 00034 // it. (Defined after main() below.) 00035 void robotForwarderAdded(ArCentralForwarder *forwarder); 00036 00037 int main(int argc, char **argv) 00038 { 00039 Aria::init(); 00040 ArArgumentParser parser(&argc, argv); 00041 00042 /* This server accepts connections from the several robot servers. It's port 00043 * number is set using the -<name>ServerPort argument, where <name> is given 00044 * here as "robot". (A default of 5000 set below, this number should always 00045 * be used). */ 00046 00047 ArServerSimpleOpener robotServersOpener(&parser, "robot"); 00048 ArServerBase robotServer(true, "RobotServer", false); 00049 00050 // Set robotServerPort to 5000, to avoid conflicting with the 00051 // server port used for clients, which will use the normal 00052 // default of 7272. 00053 parser.addDefaultArgument("-robotServerPort 5000", 1); 00054 00055 00056 /* This server accepts connections from clients: */ 00057 00058 ArServerSimpleOpener clientOpener(&parser, "client"); 00059 ArServerBase clientServer(true, "ClientServer", false, "", "", true); 00060 00061 // Load other defaults from files and environment 00062 parser.loadDefaultArguments(1); 00063 00064 00065 /* Parse arguments */ 00066 if(!Aria::parseArgs() || !parser.checkHelpAndWarnUnparsed()) 00067 { 00068 Aria::logOptions(); 00069 Aria::exit(0); 00070 } 00071 00072 /* Open servers */ 00073 00074 ArLog::log(ArLog::Normal, "Opening connection point for robot servers..."); 00075 if (!robotServersOpener.open(&robotServer, "", 120) || !robotServersOpener.checkAndLog()) 00076 { 00077 ArLog::log(ArLog::Terse, "Could not open connection point (server) for robot servers"); 00078 Aria::exit(1); 00079 } 00080 00081 ArLog::log(ArLog::Normal, "Opening server for clients..."); 00082 if (!clientOpener.open(&clientServer, "", 120) || !clientOpener.checkAndLog()) 00083 { 00084 ArLog::log(ArLog::Terse, "Could not open server for clients"); 00085 Aria::exit(1); 00086 } 00087 00088 00089 /* This keeps track of the several robot servers. When a robot server 00090 * connects to the robotsServer connection point, an ArCentralForwarder 00091 * object is created for that robot server. When a client 00092 * connects to the clientServer, it is informed of ports it can 00093 * connect to to reach the robot servers via the forwarder objects. 00094 */ 00095 ArCentralManager centralManager(&robotServer, &clientServer); 00096 00097 /* ArCentralManager also can invoke callbacks whenever a new robot server 00098 * connects and its ArCentralForwarder object is created. Commands can 00099 * be sent to the robots via these forwarders. 00100 * Here is an example: 00101 */ 00102 ArGlobalFunctor1<ArCentralForwarder*> exampleNewForwarderCB(&robotForwarderAdded); 00103 centralManager.addForwarderAddedCallback(&exampleNewForwarderCB); 00104 00105 /* Clients can send config requests to/from the robot servers, but 00106 * this allows you to also modify this central server's global configuration 00107 * (if you or any Aria class adds options to the global Aria ArConfig 00108 * object). 00109 */ 00110 ArServerHandlerConfig handlerConfig(&clientServer, Aria::getConfig()); 00111 00112 /* monitor communication between the server and client. */ 00113 ArServerHandlerCommMonitor commMonitor(&clientServer); 00114 00115 /* custom/simple commands, but give them different names than the robot 00116 * servers' simple commands: 00117 */ 00118 ArServerHandlerCommands commands(&clientServer); 00119 commands.setPrefix("CentralServer"); 00120 00121 ArServerSimpleServerCommands *serverCommands = NULL; 00122 serverCommands = new ArServerSimpleServerCommands(&commands, &clientServer); 00123 00124 /* Drawings for the client, used to draw information about multiple robots. */ 00125 ArServerInfoDrawings drawings(&clientServer); 00126 00127 /* Keep track of each robot, and send positions to other robots to use, and 00128 * drawings to clients showing points on the robots */ 00129 ArCentralMultiRobot *centralMultiRobot = NULL; 00130 centralMultiRobot = new ArCentralMultiRobot(¢ralManager, Aria::getConfig(), &drawings); 00131 00132 /* Load a config file if given */ 00133 /* 00134 char errorBuffer[1024]; 00135 if (!Aria::getConfig()->parseFile(parser.getArg(1), true, false, 00136 errorBuffer, sizeof(errorBuffer))) 00137 { 00138 ArLog::log(ArLog::Terse, "### Warning: Error loading configuration file \"%s\": %s", argv[1], errorBuffer); 00139 } 00140 00141 // write it back in case new items need to be added: 00142 Aria::getConfig()->writeFile(Aria::getConfig()->getFileName()); 00143 */ 00144 00145 /* Run servers */ 00146 clientServer.runAsync(); 00147 robotServer.run(); 00148 Aria::exit(0); 00149 } 00150 00151 00152 // Called whenever a new robot server connects and a forwarder is created for 00153 // it. 00154 void robotForwarderAdded(ArCentralForwarder *forwarder) 00155 { 00156 // Note that when a robot server connects to this central server, the central 00157 // server takes on the "client" role with respect to that server. So to send 00158 // requests or get information from a robot server, use the forwarder's 00159 // "client" object. (The forwarder's "server" object is the local port that 00160 // clients such as MobileEyes connect to.) 00161 ArLog::log(ArLog::Normal, "centralServerExample: New forwarder added for robot server named \"%s\" at host %s.", forwarder->getRobotName(), forwarder->getClient()->getHost()); 00162 }