BaseArnl: centralServerExample.cpp

- Main Page
- Classes
- Related Pages
- Examples

# centralServerExample.cpp

Example of a central server which allows clients to communicate with multiple robot servers through one connection, and for the multiple robot servers to share information. This is a simple "central robot server": it uses ArCentralManager for ArNetworking to multiplex several ArNetworking connections through one ArNetworking server. Servers (e.g. guiServer) running on several robots can then be invoked with the "-centralServer" argument (and others), and they will accept client connections through this central server. Clients supporting multiple robots, such as recent version of MobileEyes, can connect to the central server.

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(&centralManager, 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 }