00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef TESTSHORTMULTIPLEINLONGDELAY_HPP
00021 #define TESTSHORTMULTIPLEINLONGDELAY_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 #include <boost/foreach.hpp>
00031 #define foreach BOOST_FOREACH
00032
00033 #include <ros/ros.h>
00034
00035 #include <socrob/multicast.h>
00036
00037 #include <std_msgs/UInt8.h>
00038 #include <std_msgs/UInt32.h>
00039 #include <std_msgs/Time.h>
00040
00041
00042
00043 using namespace std;
00044 using namespace ros;
00045 using namespace socrob::multicast;
00046 using boost::lexical_cast;
00047
00048
00049
00050 class TestShortMultipleInLongDelay
00051 {
00052 boost::mutex mutex_;
00053
00054 int sid_;
00055
00056 const uint8_t QUESTION_MAGIC_BYTE_;
00057 const uint8_t ANSWER_MAGIC_BYTE_;
00058
00059 bool waiting_;
00060 unsigned round_number_;
00061 unsigned round_uid_;
00062 Time round_tx_;
00063 map<id_type, Time> round_answers_;
00064
00065 bool answer_;
00066 unsigned answer_number_;
00067 unsigned answer_uid_;
00068 Time answer_time_;
00069
00070 long double acc_max_arrival_delay_;
00071 long double acc_avg_arrival_delay_;
00072 long double acc_complete_delay_;
00073 unsigned long num_rounds_;
00074
00075 boost::variate_generator<boost::mt19937, boost::uniform_int<unsigned> > random_uid_;
00076
00077 Time output_time_base_;
00078 unsigned output_line_;
00079 ofstream output_;
00080
00081 public:
00082 TestShortMultipleInLongDelay (int sid,
00083 string const& type) :
00084 sid_ (sid),
00085 QUESTION_MAGIC_BYTE_ (0),
00086 ANSWER_MAGIC_BYTE_ (1),
00087 waiting_ (false),
00088 round_number_ (0),
00089 round_uid_(),
00090 round_tx_ (Time::now()),
00091 answer_ (false),
00092 acc_max_arrival_delay_ (0),
00093 acc_avg_arrival_delay_ (0),
00094 acc_complete_delay_ (0),
00095 num_rounds_ (0),
00096 random_uid_ (boost::mt19937 (Time::now().toNSec()),
00097 boost::uniform_int<unsigned> (numeric_limits<unsigned>::min(), numeric_limits<unsigned>::max())),
00098 output_time_base_ (Time::now()) {
00099 if (0 != sid_) {
00100 return;
00101 }
00102
00103 waiting_ = true;
00104 round_number_++;
00105 round_uid_ = random_uid_();
00106 round_tx_ = Time::now();
00107 round_answers_.clear();
00108
00109 output_.open ( ("/tmp/TestShortMultipleInLongDelay_" + type + "_" + lexical_cast<string> (output_time_base_.sec) + ".csv").c_str());
00110 output_ << "\"Round Number\""
00111 << ";\"Handler Delay 1\""
00112 << ";\"Handler Delay 2\""
00113 << ";\"Handler Delay 3\""
00114 << ";\"Handler Delay 4\""
00115 << ";\"Callback Delay\""
00116 << endl;
00117 output_line_ = 1;
00118 }
00119
00120
00121
00122 ~TestShortMultipleInLongDelay() {
00123 unsigned l = output_line_;
00124 output_ << ";;;" << endl;
00125 output_ << "\"Average Handler Delay:\";=AVERAGE(B2:E" << l << ")" << endl;
00126 output_ << "\"Average Callback Delay:\";=AVERAGE(F2:F" << l << ")" << endl;
00127 }
00128
00129
00130
00131 void
00132 timer () {
00133 if (0 != sid_) {
00134 return;
00135 }
00136
00137 boost::lock_guard<boost::mutex> _ (mutex_);
00138
00139 if (waiting_) {
00140 Duration age = Time::now() - round_tx_;
00141 if (age > Duration (1, 0)) {
00142 ROS_WARN_STREAM_THROTTLE (1, "Last round (" << round_number_ << ") was created " << age << " seconds ago, still waiting...");
00143 }
00144 return;
00145 }
00146 }
00147
00148
00149
00150 void
00151 long_marshall (vector<uint8_t> & buffer) {
00152 boost::lock_guard<boost::mutex> _ (mutex_);
00153
00154 if (answer_) {
00155 std_msgs::UInt8 magic_msg;
00156 magic_msg.data = ANSWER_MAGIC_BYTE_;
00157 serialize_append (buffer, magic_msg);
00158
00159 std_msgs::UInt32 number_msg;
00160 number_msg.data = answer_number_;
00161 serialize_append (buffer, number_msg);
00162
00163 std_msgs::UInt32 uid_msg;
00164 uid_msg.data = answer_uid_;
00165 serialize_append (buffer, uid_msg);
00166
00167 std_msgs::UInt8 sid_msg;
00168 sid_msg.data = sid_;
00169 serialize_append (buffer, sid_msg);
00170
00171 std_msgs::Time time_msg;
00172 time_msg.data = answer_time_;
00173 serialize_append (buffer, time_msg);
00174
00175 answer_ = false;
00176 return;
00177 }
00178
00179 if ( (0 == sid_)
00180 && (! waiting_)) {
00181 waiting_ = true;
00182 round_number_++;
00183 round_uid_ = random_uid_();
00184 round_tx_ = Time::now();
00185 round_answers_.clear();
00186
00187
00188 return;
00189 }
00190
00191 if (! waiting_) {
00192 return;
00193 }
00194
00195 std_msgs::UInt8 magic_msg;
00196 magic_msg.data = QUESTION_MAGIC_BYTE_;
00197 serialize_append (buffer, magic_msg);
00198
00199 std_msgs::UInt32 number_msg;
00200 number_msg.data = round_number_;
00201 serialize_append (buffer, number_msg);
00202
00203 std_msgs::UInt32 uid_msg;
00204 uid_msg.data = round_uid_;
00205 serialize_append (buffer, uid_msg);
00206 }
00207
00208
00209
00210 void
00211 long_unmarshall (socrob::multicast::id_type,
00212 vector<uint8_t> & buffer) {
00213 size_t offset = 0;
00214
00215 std_msgs::UInt8 magic_msg;
00216 offset += deserialize (magic_msg, buffer, offset);
00217
00218 if (magic_msg.data == 0) {
00219 std_msgs::UInt32 number_msg;
00220 offset += deserialize (number_msg, buffer, offset);
00221 std_msgs::UInt32 uid_msg;
00222 offset += deserialize (uid_msg, buffer, offset);
00223
00224 boost::lock_guard<boost::mutex> _ (mutex_);
00225
00226 answer_ = true;
00227 answer_number_ = number_msg.data;
00228 answer_uid_ = uid_msg.data;
00229 answer_time_ = Time::now();
00230 }
00231 else if (magic_msg.data == 1) {
00232 if (0 != sid_) {
00233 return;
00234 }
00235
00236 boost::lock_guard<boost::mutex> _ (mutex_);
00237
00238 if (! waiting_) {
00239 ROS_WARN_STREAM ("Received package while short rounds not active");
00240 return;
00241 }
00242
00243 std_msgs::UInt32 number_msg;
00244 offset += deserialize (number_msg, buffer, offset);
00245 std_msgs::UInt32 uid_msg;
00246 offset += deserialize (uid_msg, buffer, offset);
00247 std_msgs::UInt8 sid_msg;
00248 offset += deserialize (sid_msg, buffer, offset);
00249 std_msgs::Time arrival_time_msg;
00250 offset += deserialize (arrival_time_msg, buffer, offset);
00251
00252 unsigned sent_number = number_msg.data;
00253 unsigned sent_uid = uid_msg.data;
00254 id_type sid = sid_msg.data;
00255
00256 if (sid != 1 && sid != 2 && sid != 3 && sid != 4) {
00257 ROS_FATAL_STREAM ("Received answer from wrong agent while testing short rounds multiple.");
00258 abort();
00259 }
00260 if (sent_number != round_number_) {
00261 ROS_WARN ("Received answer wrong round number while testing short rounds single.");
00262 return;
00263 }
00264 if (sent_uid != round_uid_) {
00265 ROS_WARN ("Received answer with right number but wrong UID while testing short rounds single.");
00266 return;
00267 }
00268
00269 if (0 == round_answers_.count (sid)) {
00270 round_answers_[sid] = arrival_time_msg.data;
00271 }
00272
00273 if (round_answers_.size() == 4) {
00274 all_answers ();
00275 waiting_ = false;
00276 }
00277 }
00278 else {
00279 ROS_FATAL_STREAM ("Received package with wrong magic byte.");
00280 abort();
00281 }
00282 }
00283
00284
00285
00286 private:
00287 void
00288 all_answers () {
00289 Time now = Time::now();
00290
00291 long double avg_arrival_delay = 0;
00292 long double max_arrival_delay = 0;
00293
00294
00295 ++ (output_line_);
00296 output_ << round_number_;
00297
00298 typedef map<id_type, Time>::value_type tmp_t;
00299 foreach (tmp_t const & answer_pair, round_answers_) {
00300 Time const& ans_arrival_time = answer_pair.second;
00301
00302 Duration arrival_delay = ans_arrival_time - round_tx_;
00303
00304 output_ << ";" << arrival_delay;
00305
00306 long double arrival_delay_ld = (long double) arrival_delay.sec + 1e-9 * (long double) arrival_delay.nsec;
00307 avg_arrival_delay += arrival_delay_ld / 4;
00308 max_arrival_delay = max (max_arrival_delay, arrival_delay_ld);
00309 }
00310
00311 Duration complete_delay = now - round_tx_;
00312
00313 output_ << ";" << complete_delay << endl;
00314
00315 ROS_INFO_STREAM ("Short round " << round_number_ << " to {1,2,3,4}: q. took " << avg_arrival_delay << " avg s and " << max_arrival_delay << " max s to arrive at dest, and " << complete_delay << " seconds from start to callback.");
00316
00317 acc_avg_arrival_delay_ += avg_arrival_delay;
00318 acc_max_arrival_delay_ += max_arrival_delay;
00319 acc_complete_delay_ += (long double) complete_delay.sec + 1e-9 * (long double) complete_delay.nsec;
00320 num_rounds_++;
00321 }
00322
00323
00324
00325 public:
00326 void
00327 statistics() {
00328 if (0 != sid_) {
00329 return;
00330 }
00331
00332 acc_avg_arrival_delay_ /= num_rounds_;
00333 acc_max_arrival_delay_ /= num_rounds_;
00334 acc_complete_delay_ /= num_rounds_;
00335
00336 cout << "Final results at " << sid_ << " for short multiple: handler avg delay: " << lexical_cast<string> (acc_avg_arrival_delay_) << ", handler avg of max delay: " << lexical_cast<string> (acc_max_arrival_delay_) << ", callback delay: " << lexical_cast<string> (acc_complete_delay_) << "." << endl;
00337 }
00338 };
00339
00340 #endif