qa_worldinfo.cpp

00001
00002 /***************************************************************************
00003  *  qa_worldinfo.cpp - Fawkes QA WorldInfoTransceiver
00004  *
00005  *  Created: Thu May 03 16:14:59 2007
00006  *  Copyright  2006-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 /// @cond QA
00025 
00026 #include <core/threading/thread.h>
00027 #include <netcomm/worldinfo/transceiver.h>
00028 #ifdef HAVE_AVAHI
00029 #include <netcomm/dns-sd/avahi_thread.h>
00030 #endif
00031 #include <netcomm/utils/resolver.h>
00032 #include <utils/system/signal.h>
00033 #include <utils/system/argparser.h>
00034
00035 #include <netdb.h>
00036 #include <cstdlib>
00037 #include <cstdio>
00038 #include <cstring>
00039 #include <iostream>
00040
00041 using namespace std;
00042 using namespace fawkes;
00043
00044 class WorldInfoSenderThread : public Thread
00045 {
00046 public:
00047   WorldInfoSenderThread(unsigned short int port, bool loop, NetworkNameResolver *rs)
00048     : Thread("WorldInfoSenderThread", Thread::OPMODE_CONTINUOUS)
00049   {
00050     i = 0;
00051     try {
00052       t = new WorldInfoTransceiver("224.16.0.1", port,
00053                                    "AllemaniACsX", "DoesAnyOneCare",
00054                                    rs);
00055       t->set_loop( loop );
00056     } catch (Exception &e) {
00057       e.print_trace();
00058       throw;
00059     }
00060     covariance = (float *)malloc(WORLDINFO_COVARIANCE_SIZE_3X3 * sizeof(float));
00061     for (unsigned int j = 0; j < WORLDINFO_COVARIANCE_SIZE_3X3; ++j) {
00062       covariance[j] = j;
00063     }
00064   }
00065
00066   ~WorldInfoSenderThread()
00067   {
00068     printf("Closing sender\n");
00069     delete t;
00070     free(covariance);
00071   }
00072
00073   virtual void loop()
00074   {
00075     printf("Sending %u\n", i);
00076     t->set_pose(i, i+1, i+2, covariance);
00077     t->set_velocity(i+3, i+4, i+5, covariance);
00078     t->set_ball_pos(i+6, i+7, i+8, covariance);
00079     t->set_ball_visible(i % 2 == 0, (i % 2 == 0 ? -1 : 1) * i+9);
00080     t->set_ball_velocity(i+9, i+10, i+11, covariance);
00081     t->add_opponent(i+12, i+13, i+14, covariance);
00082     t->add_opponent(i+15, i+16, i+17, covariance);
00083     t->add_disappeared_opponent(i+18);
00084     t->add_disappeared_opponent(i+19);
00085     t->set_gamestate(GS_FROZEN, TEAM_BOTH);
00086     t->send();
00087     ++i;
00088   }
00089
00090  private:
00091   WorldInfoTransceiver *t;
00092   unsigned int i;
00093   float *covariance;
00094 };
00095
00096
00097 class WorldInfoReceiverThread : public Thread, public WorldInfoHandler
00098 {
00099 public:
00100   WorldInfoReceiverThread(unsigned short int port, unsigned int max_num_msgs,
00101                           NetworkNameResolver *rs)
00102     : Thread("WorldInfoReceiverThread", Thread::OPMODE_CONTINUOUS)
00103   {
00104     this->max_num_msgs = max_num_msgs;
00105     try {
00106       t = new WorldInfoTransceiver("224.16.0.1", port,
00107                                    "AllemaniACs", "WorldInfoQA",
00108                                    rs);
00109       t->add_handler(this);
00110     } catch (Exception &e) {
00111       e.print_trace();
00112       throw;
00113     }
00114   }
00115
00116   ~WorldInfoReceiverThread()
00117   {
00118     printf("Closing receiver\n");
00119     delete t;
00120   }
00121
00122   virtual void loop()
00123   {
00124     printf("Waiting for data\n");
00125     t->flush_sequence_numbers(10);
00126     t->recv( /* block = */ true, max_num_msgs );
00127   }
00128
00129   virtual void pose_rcvd(const char *from_host,
00130                          float x, float y, float theta,
00131                          float *covariance)
00132   {
00133     cout << "Pose[" << from_host << "]: (x,y,th)=("
00134          << x << "," << y << "," << theta << "), cov=(";
00135     for ( unsigned int i = 0; i < WORLDINFO_COVARIANCE_SIZE_3X3; ++i) {
00136       cout << covariance[i];
00137       if ( i != WORLDINFO_COVARIANCE_SIZE_3X3 - 1 ) {
00138         cout << ",";
00139       }
00140     }
00141     cout << ")" << endl;
00142   }
00143
00144   virtual void velocity_rcvd(const char *from_host, float vel_x,
00145                              float vel_y, float vel_theta, float *covariance)
00146   {
00147     cout << "Velo[" << from_host << "]: (vx,vy,vth)=("
00148          << vel_x << "," << vel_y << "," << vel_theta << ")" << endl;
00149   }
00150
00151   virtual void ball_pos_rcvd(const char *from_host,
00152                              bool visible, int visibility_history,
00153                              float dist,  float bearing, float slope,
00154                              float *covariance)
00155   {
00156     printf("Ball[%s]: vis: %i  vishis: %i   (d,b,s)=(%f,%f,%f)  cov=(%f,%f,%f,%f,%f,%f,%f,%f,%f)\n",
00157            from_host, visible, visibility_history, dist, bearing, slope,
00158            covariance[0], covariance[1], covariance[2],
00159            covariance[3], covariance[4], covariance[5],
00160            covariance[6], covariance[7], covariance[8]);
00161   }
00162
00163   virtual void ball_velocity_rcvd(const char *from_host,
00164                                   float vel_x, float vel_y, float vel_z, float *covariance)
00165   {
00166     cout << "BVel[" << from_host << "]: (vx,vy,vz)=("
00167          << vel_x << "," << vel_y << "," << vel_z << ")" << endl;
00168   }
00169
00170   virtual void opponent_pose_rcvd(const char *from_host, unsigned int uid,
00171                                   float distance, float bearing, float *covariance)
00172   {
00173     printf("Oppt[%s]: (uid,d,b)=(%u,%f,%f)  cov=(%f,%f,%f,%f)\n",
00174            from_host, uid, distance, bearing,
00175            covariance[0], covariance[1], covariance[2], covariance[3] );
00176   }
00177
00178
00179   virtual void opponent_disapp_rcvd(const char *from_host, unsigned int uid)
00180   {
00181     printf("OpptDisapp[%s]: uid=%u\n", from_host, uid);
00182   }
00183
00184   virtual void gamestate_rcvd(const char *from_host,
00185                               worldinfo_gamestate_t game_state,
00186                               worldinfo_gamestate_team_t state_team,
00187                               unsigned int score_cyan, unsigned int score_magenta,
00188                               worldinfo_gamestate_team_t our_team,
00189                               worldinfo_gamestate_goalcolor_t our_goal_color,
00190                               worldinfo_gamestate_half_t half)
00191   {
00192     printf("Gamestate[%s]:  gs=%s  gs_team=%s  score: %u:%u  our_team: %s  our_goal: %s  half: %s\n",
00193            from_host,
00194            worldinfo_gamestate_tostring(game_state),
00195            worldinfo_gamestate_team_tostring(state_team),
00196            score_cyan, score_magenta,
00197            worldinfo_gamestate_team_tostring(our_team),
00198            worldinfo_gamestate_goalcolor_tostring(our_goal_color),
00199            worldinfo_gamestate_half_tostring(half));
00200
00201   }
00202
00203  private:
00204   WorldInfoTransceiver *t;
00205   unsigned int max_num_msgs;
00206 };
00207
00208
00209 class WorldInfoQAMain : public SignalHandler
00210 {
00211  public:
00212   WorldInfoQAMain(ArgumentParser *argp)
00213   {
00214 #ifdef HAVE_AVAHI
00215     if ( argp->has_arg("a") ) {
00216       at = new AvahiThread();
00217       at->start();
00218       printf("Waiting for Avahi thread to initialize\n");
00219       at->wait_initialized();
00220     } else {
00221       at = NULL;
00222     }
00223     rs = new NetworkNameResolver(at);
00224 #else
00225     rs = new NetworkNameResolver();
00226 #endif
00227     s = NULL;
00228     r = NULL;
00229     this->argp = argp;
00230     if ( argp->has_arg("r") ) {
00231       printf("Going to be a receiver\n");
00232       r = new WorldInfoReceiverThread(2806, argp->has_arg("s") ? 1 : 0, rs);
00233     } else {
00234       s = new WorldInfoSenderThread(2806, argp->has_arg("l"), rs);
00235     }
00236   }
00237
00238   ~WorldInfoQAMain()
00239   {
00240 #ifdef HAVE_AVAHI
00241     if ( at != NULL ) {
00242       at->cancel();
00243       at->join();
00244       delete at;
00245     }
00246 #endif
00247     delete s;
00248     delete r;
00249   }
00250
00251
00252   virtual void handle_signal(int signum)
00253   {
00254     printf("Signal received, cancelling threads\n");
00255     if ( s != NULL )  s->cancel();
00256     if ( r != NULL )  r->cancel();
00257     printf("Threads cancelled\n");
00258   }
00259
00260   void run()
00261   {
00262     if ( s != NULL ) {
00263       s->start();
00264       s->join();
00265     }
00266     if ( r != NULL ) {
00267       r->start();
00268       r->join();
00269     }
00270   }
00271
00272  private:
00273   ArgumentParser *argp;
00274   WorldInfoSenderThread *s;
00275   WorldInfoReceiverThread *r;
00276   NetworkNameResolver *rs;
00277 #ifdef HAVE_AVAHI
00278   AvahiThread *at;
00279 #endif
00280 };
00281
00282 int
00283 main(int argc, char **argv)
00284 {
00285   ArgumentParser *argp = new ArgumentParser(argc, argv, "arlsh");
00286
00287   if ( argp->has_arg("h") ) {
00288     cout << "Usage: " << argv[0] << "[-r] [-h] [-s] [-l] [-a]" << endl
00289          << " -r   receiver (sender otherwise)" << endl
00290          << " -h   this help message" << endl
00291          << " -s   single per recv, only process a single message per recv()" << endl
00292 #ifdef HAVE_AVAHI
00293          << " -a   enable Avahi for mDNS lookup" << endl
00294 #else
00295          << " -a   not available (Avahi not installed)" << endl
00296 #endif
00297          << " -l   enable multicast loop back" << endl;
00298     return 0;
00299   }
00300
00301   WorldInfoQAMain m(argp);
00302   SignalManager::register_handler(SIGINT, &m);
00303   SignalManager::ignore(SIGPIPE);
00304
00305   m.run();
00306
00307   SignalManager::finalize();
00308
00309   delete argp;
00310   return 0;
00311 }
00312 
00313 /// @endcond