TestShortSingleDelay.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2012, 2013 Instituto de Sistemas e Robotica, Instituto Superior Tecnico
00003  *
00004  * This file is part of SocRob Multicast.
00005  *
00006  * SocRob Multicast is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * SocRob Multicast is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with SocRob Multicast.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #ifndef TESTSHORTSINGLEDELAY_HPP
00021 #define TESTSHORTSINGLEDELAY_HPP
00022 
00023 #include <iostream>
00024 #include <fstream>
00025 #include <limits>
00026 
00027 #include <boost/thread/mutex.hpp>
00028 #include <boost/random.hpp>
00029 #include <boost/lexical_cast.hpp>
00030 
00031 #include <ros/ros.h>
00032 
00033 #include <socrob/multicast.h>
00034 
00035 #include <std_msgs/UInt8.h>
00036 #include <std_msgs/UInt32.h>
00037 #include <std_msgs/Time.h>
00038 
00039 
00040 
00041 using namespace std;
00042 using namespace ros;
00043 using namespace socrob::multicast;
00044 using boost::lexical_cast;
00045 
00046 
00047 
00048 class TestShortSingleDelay
00049 {
00050     boost::mutex mutex_;
00051     
00052     int sid_;
00053     
00054     const uint8_t MAGIC_BYTE_;
00055     
00056     unsigned round_number_;
00057     unsigned round_uid_;
00058     Time round_tx_;
00059     
00060     bool waiting_;
00061     
00062     long double acc_arrival_delay_;
00063     long double acc_complete_delay_;
00064     unsigned long num_rounds_;
00065     
00066     unsigned long failed_;
00067     
00068     boost::variate_generator<boost::mt19937, boost::uniform_int<unsigned> > random_uid_;
00069     
00070     Time output_time_base_;
00071     unsigned output_line_;
00072     ofstream output_;
00073     
00074   public:
00075     TestShortSingleDelay (int sid,
00076                           string const& type) :
00077       sid_ (sid),
00078       MAGIC_BYTE_ (1),
00079       round_number_ (0),
00080       round_uid_(),
00081       round_tx_ (Time::now()),
00082       waiting_ (false),
00083       acc_arrival_delay_ (0),
00084       acc_complete_delay_ (0),
00085       num_rounds_ (0),
00086       failed_ (0),
00087       random_uid_ (boost::mt19937 (Time::now().toNSec()),
00088                    boost::uniform_int<unsigned> (numeric_limits<unsigned>::min(), numeric_limits<unsigned>::max())),
00089       output_time_base_ (Time::now()) {
00090       if (0 != sid_) {
00091         return;
00092       }
00093       
00094       output_.open ( ("/tmp/TestShortSingleDelay_" + type + "_" + lexical_cast<string> (output_time_base_.sec) + ".csv").c_str());
00095       output_ << "\"Round Number\""
00096               << ";\"Destination\""
00097               << ";\"Handler Delay\""
00098               << ";\"Callback Delay\""
00099               << endl;
00100       output_line_ = 1;
00101     }
00102     
00103     
00104     
00105     ~TestShortSingleDelay() {
00106       unsigned l = output_line_;
00107       output_ << ";;;" << endl;
00108       output_ << "\"Average Handler Delay:\";=AVERAGE(C2:C" << l << ")" << endl;
00109       output_ << "\"Average Callback Delay:\";=AVERAGE(D2:D" << l << ")" << endl;
00110       output_ << "\"Failed Starts:\";" << failed_ << endl;
00111     }
00112     
00113     
00114     
00115     bool
00116     is_question (vector<uint8_t> & question) {
00117       std_msgs::UInt8 magic_msg;
00118       deserialize (magic_msg, question);
00119       
00120       if (magic_msg.data == MAGIC_BYTE_) {
00121         return true;
00122       }
00123       
00124       return false;
00125     }
00126     
00127     
00128     
00129     void
00130     timer (socrob::multicast::Manager& manager) {
00131       if (0 != sid_) {
00132         return;
00133       }
00134       
00135       vector<uint8_t> question;
00136       std_msgs::UInt8 magic_msg;
00137       magic_msg.data = MAGIC_BYTE_;
00138       serialize_append (question, magic_msg);
00139       
00140       id_type agent;
00141       
00142       {
00143         boost::lock_guard<boost::mutex> _ (mutex_);
00144         
00145         if (waiting_) {
00146           Duration age = Time::now() - round_tx_;
00147           if (age > Duration (1, 0)) {
00148             ROS_WARN_STREAM_THROTTLE (1, "Last round (" << round_number_ << ") was created " << age << " seconds ago, still waiting...");
00149           }
00150           return;
00151         }
00152         
00153         round_number_++;
00154         round_uid_ = random_uid_();
00155         round_tx_ = Time::now();
00156         waiting_ = true;
00157         agent = (round_number_ % 4) + 1;
00158         
00159         std_msgs::UInt32 round_number_msg;
00160         round_number_msg.data = round_number_;
00161         serialize_append (question, round_number_msg);
00162         
00163         std_msgs::UInt32 round_uid_msg;
00164         round_uid_msg.data = round_uid_;
00165         serialize_append (question, round_uid_msg);
00166       }
00167       
00168       // This cannot be in the critical region because it may call the callback right away.
00169       Rate rate (1000);
00170       while (! manager.startShortRound (question, agent, boost::bind (&TestShortSingleDelay::short_callback, this, _1))) {
00171         boost::lock_guard<boost::mutex> _ (mutex_);
00172         failed_++;
00173         rate.sleep();
00174       }
00175     }
00176     
00177     
00178     
00179     void
00180     short_handler (vector<uint8_t>& answer,
00181                    id_type from,
00182                    vector<uint8_t> & question) {
00183       Time now = Time::now();
00184       
00185       size_t offset = 0;
00186       std_msgs::UInt8 magic_msg;
00187       offset += deserialize (magic_msg, question, offset);
00188       std_msgs::UInt32 number_msg;
00189       offset += deserialize (number_msg, question, offset);
00190       std_msgs::UInt32 uid_msg;
00191       offset += deserialize (uid_msg, question, offset);
00192       
00193       if (magic_msg.data != MAGIC_BYTE_) {
00194         ROS_FATAL_STREAM ("TestShortSingleDelay::short_handler received a question with wrong magic byte.");
00195         abort();
00196       }
00197       
00198       serialize_append (answer, number_msg);
00199       
00200       serialize_append (answer, uid_msg);
00201       
00202       std_msgs::UInt8 sid_msg;
00203       sid_msg.data = sid_;
00204       serialize_append (answer, sid_msg);
00205       
00206       std_msgs::Time time_msg;
00207       time_msg.data = now;
00208       serialize_append (answer, time_msg);
00209     }
00210     
00211     
00212     
00213     void
00214     short_callback (map<id_type, vector<uint8_t> > & answers) {
00215       Time now = Time::now();
00216       
00217       boost::lock_guard<boost::mutex> _ (mutex_);
00218       
00219       if (! waiting_) {
00220         ROS_FATAL_STREAM ("Callback called unexpectedly while short rounds not active");
00221         abort();
00222       }
00223       waiting_ = false;
00224       
00225       if (0 == answers.size()) {
00226         ROS_WARN_STREAM ("Did not receive any answer in this round while testing short rounds single.");
00227         return;
00228       }
00229       
00230       if (1 != answers.size()) {
00231         ROS_FATAL_STREAM ("Received too many answers in this round while testing short rounds single.");
00232         abort();
00233       }
00234       
00235       vector<uint8_t> & answer = answers.begin()->second;
00236       
00237       size_t offset = 0;
00238       std_msgs::UInt32 number_msg;
00239       offset += deserialize (number_msg, answer, offset);
00240       std_msgs::UInt32 uid_msg;
00241       offset += deserialize (uid_msg, answer, offset);
00242       std_msgs::UInt8 sid_msg;
00243       offset += deserialize (sid_msg, answer, offset);
00244       std_msgs::Time arrival_time_msg;
00245       offset += deserialize (arrival_time_msg, answer, offset);
00246       
00247       unsigned sent_number = number_msg.data;
00248       unsigned sent_uid = uid_msg.data;
00249       id_type sid = sid_msg.data;
00250       Time ans_arrival_time = arrival_time_msg.data;
00251       
00252       if (sid != answers.begin()->first) {
00253         ROS_FATAL_STREAM ("Received answer with agent number mismatch while testing short rounds single.");
00254         abort();
00255       }
00256       if (sid != (round_number_ % 4) + 1) {
00257         ROS_FATAL_STREAM ("Received answer from wrong agent while testing short rounds single.");
00258         abort();
00259       }
00260       if (sent_number != round_number_) {
00261         ROS_FATAL_STREAM ("Received answer wrong round number while testing short rounds single.");
00262         abort();
00263       }
00264       if (sent_uid != round_uid_) {
00265         ROS_FATAL_STREAM ("Received answer with right number but wrong UID while testing short rounds single.");
00266         abort();
00267       }
00268       
00269       Duration arrival_delay = ans_arrival_time - round_tx_;
00270       Duration complete_delay = now - round_tx_;
00271       
00272       ROS_INFO_STREAM ("Short round " << round_number_ << " to " << ( (round_number_ % 4) + 1) << ": question took " << arrival_delay << " seconds to arrive at destination, and " << complete_delay << " seconds from start to callback.");
00273       
00274       /*unsigned l =*/
00275       ++ (output_line_);
00276       output_ << round_number_
00277               << ";" << ( (round_number_ % 4) + 1)
00278               << ";" << arrival_delay
00279               << ";" << complete_delay
00280               << endl;
00281               
00282       acc_arrival_delay_ += (long double) arrival_delay.sec + 1e-9 * (long double) arrival_delay.nsec;
00283       acc_complete_delay_ += (long double) complete_delay.sec + 1e-9 * (long double) complete_delay.nsec;
00284       num_rounds_++;
00285     }
00286     
00287     
00288     
00289     void
00290     statistics() {
00291       if (0 != sid_) {
00292         return;
00293       }
00294       
00295       acc_arrival_delay_ /= num_rounds_;
00296       acc_complete_delay_ /= num_rounds_;
00297       
00298       cout << "Final results at " << sid_ << " for short single: handler delay: " << lexical_cast<string> (acc_arrival_delay_) << ", callback delay: " << lexical_cast<string> (acc_complete_delay_) << "." << endl;
00299       cout << "Failed rounds at " << sid_ << ": " << failed_ << endl;
00300     }
00301 };
00302 
00303 #endif


socrob_multicast
Author(s): Joao Reis/jreis@isr.ist.utl.pt
autogenerated on Mon Jan 6 2014 11:47:49