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
00036 #include "pr2_transmission_check/transmission_check.h"
00037 #include <limits>
00038 #include "angles/angles.h"
00039
00040 #include <boost/accumulators/statistics/max.hpp>
00041 #include <boost/accumulators/statistics/min.hpp>
00042
00043 using namespace pr2_transmission_check;
00044 using namespace std;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #define GRACE_HITS 5
00057
00058
00059 TransmissionListener::TransmissionListener() :
00060 joint_name_(""),
00061 actuator_name_(""),
00062 deadband_(0.1),
00063 has_wrap_(false),
00064 has_up_(false),
00065 has_down_(false),
00066 status_(true),
00067 last_trans_status_(true),
00068 error_cnt_(0),
00069 num_errors_(0),
00070 num_hits_(0),
00071 num_errors_since_reset_(0),
00072 rx_cnt_(0),
00073 last_rising_(0.0),
00074 last_falling_(0.0),
00075 last_bad_reading_(0.0),
00076 last_position_(0.0),
00077 is_calibrated_(false),
00078 has_updated_(false)
00079 { }
00080
00081 bool TransmissionListener::initUrdf(const boost::shared_ptr<urdf::Joint> jnt, const string &actuator_name)
00082 {
00083 joint_name_ = jnt->name;
00084 actuator_name_ = actuator_name;
00085
00086 if (!jnt->calibration)
00087 {
00088 ROS_DEBUG("Joint \"%s\" does not support calibration.", joint_name_.c_str());
00089 return false;
00090 }
00091
00092 has_up_ = (bool) jnt->calibration->rising;
00093 has_down_ = (bool) jnt->calibration->falling;
00094
00095 if (has_up_)
00096 up_ref_ = *(jnt->calibration->rising);
00097
00098 if (has_down_)
00099 down_ref_ = *(jnt->calibration->falling);
00100
00101 if (jnt->type == urdf::Joint::CONTINUOUS)
00102 {
00103 has_wrap_ = true;
00104
00105 if (has_up_ && !has_down_)
00106 down_ref_ = up_ref_ + M_PI;
00107 if (!has_up_ && has_down_)
00108 up_ref_ = down_ref_ + M_PI;
00109
00110 up_ref_ = angles::normalize_angle(up_ref_);
00111 down_ref_ = angles::normalize_angle(down_ref_);
00112
00113 has_up_ = true;
00114 has_down_ = true;
00115 }
00116
00117 return true;
00118 }
00119
00120
00121
00122 bool TransmissionListener::update(const pr2_mechanism_msgs::MechanismStatistics::ConstPtr& mechMsg)
00123 {
00124 const pr2_mechanism_msgs::JointStatistics *js = NULL;
00125 const pr2_mechanism_msgs::ActuatorStatistics *as = NULL;
00126
00127 for (uint i = 0; i < mechMsg->joint_statistics.size(); ++i)
00128 {
00129 if (mechMsg->joint_statistics[i].name == joint_name_)
00130 js = &mechMsg->joint_statistics[i];
00131 }
00132
00133 if (!js)
00134 {
00135 ROS_ERROR_ONCE("Unable to find joint state for joint \"%s\".", joint_name_.c_str());
00136 return false;
00137 }
00138
00139 if (!js->is_calibrated)
00140 return true;
00141
00142
00143 for (uint i = 0; i < mechMsg->actuator_statistics.size(); ++i)
00144 {
00145 if (mechMsg->actuator_statistics[i].name == actuator_name_)
00146 as = &mechMsg->actuator_statistics[i];
00147 }
00148
00149 if (!as)
00150 {
00151 ROS_ERROR_ONCE("Unable to find actuator state for actuator \"%s\".", actuator_name_.c_str());
00152 return false;
00153 }
00154
00155 rx_cnt_++;
00156 last_rising_ = as->last_calibration_rising_edge;
00157 last_falling_ = as->last_calibration_falling_edge;
00158 last_cal_reading_ = as->calibration_reading;
00159 last_position_ = js->position;
00160 is_calibrated_ = js->is_calibrated;
00161 position_obs_(last_position_);
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 bool rv = checkFlag(js, as);
00173
00174 last_trans_status_ = rv;
00175 if (!rv)
00176 {
00177 num_hits_++;
00178 last_bad_reading_ = last_position_;
00179 error_cnt_++;
00180 }
00181 else
00182 error_cnt_ = 0;
00183
00184 if (error_cnt_ > GRACE_HITS)
00185 {
00186 num_errors_++;
00187 num_errors_since_reset_++;
00188 status_ = false;
00189 }
00190
00191 has_updated_ = true;
00192 return true;
00193 }
00194
00195 bool TransmissionListener::checkBounds(const pr2_mechanism_msgs::JointStatistics *js) const
00196 {
00197 ROS_ASSERT_MSG(js->name == joint_name_, "Joint name didn't match!");
00198
00199
00200 if (!js->is_calibrated)
00201 {
00202 ROS_ERROR_ONCE("Joint \"%s\" isn't calibrated. Unable to check bounds for joint.", joint_name_.c_str());
00203 return false;
00204 }
00205
00206 return js->position < max_ && js->position > min_;
00207 }
00208
00209 bool TransmissionListener::checkFlag(const pr2_mechanism_msgs::JointStatistics *js,
00210 const pr2_mechanism_msgs::ActuatorStatistics *as) const
00211 {
00212 ROS_ASSERT_MSG(js->name == joint_name_, "Joint name didn't match!");
00213 ROS_ASSERT_MSG(as->name == actuator_name_, "Actuator name didn't match!");
00214
00215 float jnt_position = js->position;
00216
00217 if (!has_up_ && !has_down_)
00218 {
00219 ROS_ERROR("Neither up or down reference specified for joint \"%s\". Unable to check transmission.",
00220 joint_name_.c_str());
00221 return false;
00222 }
00223
00224
00225 if (has_wrap_)
00226 jnt_position = angles::normalize_angle(jnt_position);
00227
00228
00229 if (has_up_)
00230 {
00231 if (abs(jnt_position - up_ref_) < deadband_)
00232 return true;
00233 }
00234 if (has_down_)
00235 {
00236 if (abs(jnt_position - down_ref_) < deadband_)
00237 return true;
00238 }
00239
00240
00241 if (has_up_ && has_down_ && has_wrap_)
00242 {
00243 if (abs(( 2 * M_PI - jnt_position) - up_ref_) < deadband_)
00244 return true;
00245 if (abs((- 2 * M_PI + jnt_position) - up_ref_) < deadband_)
00246 return true;
00247 if (abs(( 2 * M_PI - jnt_position) - down_ref_) < deadband_)
00248 return true;
00249 if (abs((- 2 * M_PI + jnt_position) - down_ref_) < deadband_)
00250 return true;
00251 }
00252
00253 if (has_up_ && has_down_)
00254 {
00255 if (up_ref_ > down_ref_)
00256 {
00257 if (jnt_position < down_ref_ && as->calibration_reading)
00258 return true;
00259 else if (jnt_position > down_ref_ && jnt_position < up_ref_ && !as->calibration_reading)
00260 return true;
00261 else if (jnt_position > up_ref_ && as->calibration_reading)
00262 return true;
00263 else
00264 {
00265 ROS_WARN_THROTTLE(1, "Broken transmission reading for \"%s\". Position: %f (wrapped), cal reading: %d. Up ref: %f, Down ref: %f", joint_name_.c_str(), jnt_position, as->calibration_reading, up_ref_, down_ref_);
00266 return false;
00267 }
00268 }
00269 else
00270 {
00271 if (jnt_position < up_ref_ && !as->calibration_reading)
00272 return true;
00273 else if (jnt_position > up_ref_ && jnt_position < down_ref_ && as->calibration_reading)
00274 return true;
00275 else if (jnt_position > down_ref_ && !as->calibration_reading)
00276 return true;
00277 else
00278 {
00279 ROS_WARN_THROTTLE(1, "Broken transmission reading for \"%s\". Position: %f (wrapped), cal reading: %d. Up ref: %f, Down ref: %f", joint_name_.c_str(), jnt_position, as->calibration_reading, up_ref_, down_ref_);
00280 return false;
00281 }
00282 }
00283 }
00284 else if (has_up_)
00285 {
00286 if (jnt_position > up_ref_ && as->calibration_reading)
00287 return true;
00288 else if (jnt_position < up_ref_ && !as->calibration_reading)
00289 return true;
00290 else
00291 {
00292 ROS_WARN_THROTTLE(1, "Broken transmission reading for \"%s\". Position: %f (wrapped), cal reading: %d. Up ref: %f, Down ref: %f", joint_name_.c_str(), jnt_position, as->calibration_reading, up_ref_, down_ref_);
00293 return false;
00294 }
00295 }
00296
00297 else
00298 {
00299 if (jnt_position > down_ref_ && !as->calibration_reading)
00300 return true;
00301 else if (jnt_position < down_ref_ && as->calibration_reading)
00302 return true;
00303 else
00304 {
00305 ROS_WARN_THROTTLE(1, "Broken transmission reading for \"%s\". Position: %f (wrapped), cal reading: %d. Up ref: %f, Down ref: %f", joint_name_.c_str(), jnt_position, as->calibration_reading, up_ref_, down_ref_);
00306 return false;
00307 }
00308 }
00309
00310 ROS_ASSERT_MSG(false, "No case handled for transmission checker!");
00311 return false;
00312 }
00313
00314 boost::shared_ptr<diagnostic_updater::DiagnosticStatusWrapper> TransmissionListener::toDiagStat() const
00315 {
00316 boost::shared_ptr<diagnostic_updater::DiagnosticStatusWrapper> stat(new diagnostic_updater::DiagnosticStatusWrapper);
00317
00318 stat->name = "Transmission (" + joint_name_ + ")";
00319
00320 if (!has_updated_)
00321 stat->mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "No Updates");
00322
00323 if (!status_)
00324 stat->mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR, "Broken Transmission");
00325
00326 stat->add("Transmission Status", status_ ? "OK" : "Broken");
00327 stat->add("Current Reading", last_trans_status_ ? "OK" : "Broken");
00328
00329 stat->add("Joint", joint_name_);
00330 stat->add("Actuator", actuator_name_);
00331 if (has_up_)
00332 stat->add("Up Position", up_ref_);
00333 else
00334 stat->add("Up Position", "N/A");
00335
00336 if (has_down_)
00337 stat->add("Down Position", down_ref_);
00338 else
00339 stat->add("Down Position", "N/A");
00340
00341 stat->add("Wrapped", has_wrap_ ? "True" : "False");
00342
00343
00344
00345
00346 stat->add("Mech State RX Count", rx_cnt_);
00347 stat->add("Is Calibrated", is_calibrated_ ? "True" : "False");
00348 stat->add("Calibration Reading", last_cal_reading_);
00349 stat->add("Joint Position", last_position_);
00350 stat->add("Total Errors", num_errors_);
00351 stat->add("Errors Since Reset", num_errors_since_reset_);
00352 stat->add("Total Bad Readings", num_hits_);
00353 float max_obs_val = boost::accumulators::max( position_obs_ );
00354 float min_obs_val = boost::accumulators::min( position_obs_ );
00355 stat->add("Max Obs. Position", max_obs_val );
00356 stat->add("Min Obs. Position", min_obs_val );
00357
00358 stat->add("Last Rising Edge", last_rising_);
00359 stat->add("Last Falling Edge", last_falling_);
00360 stat->add("Last Bad Reading", last_bad_reading_);
00361
00362
00363 return stat;
00364 }
00365