00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "ros/node_handle.h"
00036 #include "sensor_msgs/Image.h"
00037 #include "cv_bridge/CvBridge.h"
00038 #include <stdio.h>
00039 #include <signal.h>
00040 #include <ethercat_trigger_controllers/SetWaveform.h>
00041 #include <ethercat_trigger_controllers/trigger_controller.h>
00042 #include <algorithm>
00043 #include <pr2_self_test_msgs/TestResult.h>
00044 #include <boost/format.hpp>
00045
00046 class LedFlashTest
00047 {
00048 private:
00049 sensor_msgs::CvBridge img_bridge_;
00050 std::string window_name_;
00051 ros::NodeHandle &node_handle_;
00052 ros::NodeHandle private_node_handle_;
00053 double rate_;
00054 std::string led_set_waveform_;
00055 controller::trigger_configuration led_config_;
00056 ethercat_trigger_controllers::SetWaveform::Response dummy_resp_;
00057 std::vector<double> intensities_;
00058 std::vector<double> led_time_;
00059 std::vector<double> exp_time_;
00060 int frame_;
00061 int skip_frames_;
00062 int keep_frames_;
00063 int tolerance_;
00064 ros::Subscriber img_sub_;
00065
00066 public:
00067 LedFlashTest(ros::NodeHandle &n) : node_handle_(n), private_node_handle_("~")
00068 {
00069
00070
00071
00072
00073 sleep(5);
00074
00075 node_handle_.param("led_controller", led_set_waveform_, (std::string) "led_controller");
00076 led_set_waveform_ += "/set_waveform";
00077
00078
00079
00080 private_node_handle_.param("rate", rate_, 0.);
00081
00082 led_config_.running = 1;
00083 led_config_.rep_rate = rate_;
00084 led_config_.phase = 0;
00085 led_config_.active_low = 1;
00086 led_config_.pulsed = 1;
00087 led_config_.duty_cycle = .5;
00088
00089 SetWaveform(led_set_waveform_, led_config_);
00090
00091
00092 img_sub_ = node_handle_.subscribe("image", 10, &LedFlashTest::image_cb, this);
00093
00094
00095 private_node_handle_.param("skip", skip_frames_, 10);
00096 private_node_handle_.param("frames", keep_frames_, 100);
00097 frame_ = 0;
00098 }
00099
00100 ~LedFlashTest()
00101 {
00102 }
00103
00104 void SetWaveform(std::string s, ethercat_trigger_controllers::SetWaveform::Request req)
00105 {
00106 ROS_DEBUG("Calling \"%s\"", s.c_str());
00107 if (!ros::service::call(s, req, dummy_resp_))
00108 {
00109 ROS_FATAL("Error calling \"%s\"", s.c_str());
00110 node_handle_.shutdown();
00111 }
00112 }
00113
00114 void image_cb(const sensor_msgs::Image::ConstPtr &img_msg)
00115 {
00116 frame_++;
00117 if (frame_ <= skip_frames_)
00118 return;
00119
00120
00121
00122 boost::const_pointer_cast<sensor_msgs::Image>(img_msg)->encoding = "mono8";
00123 img_bridge_.fromImage(*img_msg);
00124 CvScalar mean = cvAvg(img_bridge_.toIpl());
00125 double intensity = mean.val[0];
00126
00127
00128
00129 double exp_time = img_msg->header.stamp.toSec();
00130 exp_time_.push_back(exp_time);
00131 led_time_.push_back(controller::TriggerController::getTickStartTimeSec(exp_time, led_config_));
00132 intensities_.push_back(intensity);
00133
00134
00135 if (frame_ == skip_frames_ + keep_frames_)
00136 {
00137 double max_i = *std::max_element(intensities_.begin(), intensities_.end());
00138 double min_i = *std::min_element(intensities_.begin(), intensities_.end());
00139
00140 double thresh_high = (2 * max_i + min_i) / 3;
00141 double thresh_low = (max_i + 2 * min_i) / 3;
00142 double max_high, min_high, max_low, min_low;
00143 private_node_handle_.param("max_high", max_high, 0.);
00144 private_node_handle_.param("min_high", min_high, 0.);
00145 private_node_handle_.param("max_low", max_low, 0.);
00146 private_node_handle_.param("min_low", min_low, 0.);
00147 private_node_handle_.param("tolerance", tolerance_, 0);
00148
00149
00150
00151 std::string report = str(boost::format("<p>Maximum intensity: %i</p><p>Minimum intensity: %i</p>")%max_i%min_i);
00152 int fail = 0;
00153 int nomatch = 0;
00154 for (int i = 0; i < keep_frames_; i++)
00155 {
00156 double delta = led_time_[i] - exp_time_[i];
00157
00158 int matched = 0;
00159 if (delta <= max_high && delta >= min_high)
00160 {
00161 matched = 1;
00162 if (intensities_[i] <= thresh_high)
00163 {
00164 ROS_ERROR("Frame %i: Not high intensity at %f, between %f and %f.", i, delta, min_high, max_high);
00165 fail++;
00166 report += str(boost::format("<p>Frame %i: Not high intensity at %f, between %f and %f.</p>")%i%delta%min_high%max_high);
00167 }
00168 }
00169 if (delta <= max_low && delta >= min_low)
00170 {
00171 matched = -1;
00172 if (intensities_[i] >= thresh_low)
00173 {
00174 ROS_ERROR("Frame %i: Not low intensity at %f between %f and %f.", i, delta, min_low, max_low);
00175 fail++;
00176 report += str(boost::format("<p>Frame %i: Not low intensity at %f, between %f and %f.</p>")%i%delta%min_low%max_low);
00177 }
00178 }
00179
00180 if (!matched)
00181 {
00182 nomatch++;
00183
00184 }
00185
00186 ROS_DEBUG("Plot: delta: %f intensity: %f desired: %i", delta, intensities_[i], matched);
00187 }
00188
00189 if (nomatch > keep_frames_ / 3)
00190 {
00191 ROS_ERROR("More than a third of the frames did not match a rule.");
00192 report += "<p>More than a third of the frames did not match a rule.</p>";
00193 }
00194
00195 pr2_self_test_msgs::TestResult::Request result;
00196 result.html_result = report;
00197 if (fail > tolerance_)
00198 {
00199 ROS_INFO("LED test failed.");
00200 result.text_summary = "Test failed.";
00201 result.result = pr2_self_test_msgs::TestResult::Request::RESULT_FAIL;
00202 }
00203 else
00204 {
00205 ROS_INFO("LED test passed.");
00206 result.text_summary = "Test passed.";
00207 result.result = pr2_self_test_msgs::TestResult::Request::RESULT_PASS;
00208 }
00209
00210 pr2_self_test_msgs::TestResult::Response dummy_response;
00211 if (!ros::service::call("test_result", result, dummy_response))
00212 {
00213 ROS_ERROR("Error sending test result message.");
00214 }
00215
00216 node_handle_.shutdown();
00217 }
00218 }
00219 };
00220
00221 int main(int argc, char **argv)
00222 {
00223 ros::init(argc, argv, "timestamp_test");
00224 ros::NodeHandle n;
00225 LedFlashTest tt(n);
00226 ros::spin();
00227
00228 return 0;
00229 }