00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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