led_flash_test.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 * 
00004 *  Copyright (c) 2008, Willow Garage, Inc.
00005 *  All rights reserved.
00006 * 
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 * 
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 * 
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
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     // Open the output file.
00070 
00071     // Get names for waveform generator.
00072   
00073     sleep(5); // Otherwise the others aren't ready. Plus let some frames go by...
00074 
00075     node_handle_.param("led_controller", led_set_waveform_, (std::string) "led_controller");    
00076     led_set_waveform_ += "/set_waveform";
00077 
00078     // Initialize waveform generators.
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     // Subscribe to image stream.
00092     img_sub_ = node_handle_.subscribe("image", 10, &LedFlashTest::image_cb, this);
00093   
00094     // Other parameters.
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     // Compute image intensity.
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     // Control logic
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     // If we are done, check the results and quit.
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       // double thresh = (max_i + min_i) / 2;
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       //ROS_INFO("high: %f low: %f frame: %i size: %i", thresh_high; thresh_low, );
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           //ROS_INFO("Frame %i, state %i at %f, does not match a rule.", i, intensities_[i] > thresh, delta);
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 }


qualification
Author(s): Kevin Watts (watts@willowgarage.com), Josh Faust (jfaust@willowgarage.com)
autogenerated on Sat Dec 28 2013 17:57:34