00001 #ifndef OBJECTCONTACTTURNAROUNDDETECTORBASE_H
00002 #define OBJECTCONTACTTURNAROUNDDETECTORBASE_H
00003
00004 #include "../TorqueFilter/IIRFilter.h"
00005 #include <boost/shared_ptr.hpp>
00006 #include <iostream>
00007 #include <cmath>
00008 #include "hrpsys/util/Hrpsys.h"
00009 #include <hrpUtil/Eigen3d.h>
00010
00011 class ObjectContactTurnaroundDetectorBase
00012 {
00013 public:
00014 typedef enum {MODE_IDLE, MODE_STARTED, MODE_DETECTED, MODE_MAX_TIME, MODE_OTHER_DETECTED} process_mode;
00015 typedef enum {TOTAL_FORCE, TOTAL_MOMENT, TOTAL_MOMENT2, GENERALIZED_WRENCH} detector_total_wrench;
00016 private:
00017 boost::shared_ptr<FirstOrderLowPassFilter<double> > wrench_filter;
00018 boost::shared_ptr<FirstOrderLowPassFilter<double> > dwrench_filter;
00019 boost::shared_ptr<FirstOrderLowPassFilter<double> > friction_coeff_wrench_filter;
00020 boost::shared_ptr<FirstOrderLowPassFilter<hrp::dvector6> > resultant_wrench_filter;
00021 boost::shared_ptr<FirstOrderLowPassFilter<hrp::dvector6> > resultant_dwrench_filter;
00022 hrp::Vector3 axis, moment_center;
00023 std::vector<hrp::dvector6> constraint_conversion_matrix1, constraint_conversion_matrix2;
00024 hrp::dvector6 filtered_resultant_wrench_with_hold;
00025 double dt;
00026 double detect_ratio_thre, start_ratio_thre, forgetting_ratio_thre, max_time, current_time;
00027
00028
00029
00030
00031 size_t detect_count_thre, start_count_thre, other_detect_count_thre;
00032 detector_total_wrench dtw;
00033 std::string print_str;
00034 bool is_filter_reset, is_hold_values, is_other_constraint_detected;
00035
00036 std::vector<double> ref_dwrench, raw_wrench, filtered_wrench_with_hold, filtered_friction_coeff_wrench_with_hold, phi1, phi2, dphi1;
00037 std::vector<process_mode> pmode;
00038 std::vector<size_t> count;
00039 public:
00040 ObjectContactTurnaroundDetectorBase (const double _dt) : axis(-1*hrp::Vector3::UnitZ()), moment_center(hrp::Vector3::Zero()),
00041 constraint_conversion_matrix1(std::vector<hrp::dvector6>(1, hrp::dvector6::Zero())), constraint_conversion_matrix2(std::vector<hrp::dvector6>(1, hrp::dvector6::Zero())), filtered_resultant_wrench_with_hold(hrp::dvector6::Zero()),
00042 dt(_dt), detect_ratio_thre(0.01), start_ratio_thre(0.5), forgetting_ratio_thre(1e3),
00043 max_time(0.0), current_time(0.0),
00044 detect_count_thre(5), start_count_thre(5), other_detect_count_thre(round(detect_count_thre*1.5)), dtw(TOTAL_FORCE),
00045 is_filter_reset(false), is_hold_values(false), is_other_constraint_detected(false),
00046 ref_dwrench(std::vector<double>(1, 0.0)), raw_wrench(std::vector<double>(1, 0.0)), filtered_wrench_with_hold(std::vector<double>(1, 0.0)), filtered_friction_coeff_wrench_with_hold(std::vector<double>(1, 0.0)),
00047 phi1(std::vector<double>(1, 0.0)), phi2(std::vector<double>(1, 0.0)), dphi1(std::vector<double>(1, 0.0)),
00048 pmode(std::vector<process_mode>(1, MODE_MAX_TIME)), count(std::vector<size_t>(1))
00049
00050 {
00051 double default_cutoff_freq = 1;
00052 wrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<double> >(new FirstOrderLowPassFilter<double>(default_cutoff_freq, _dt, 0));
00053 dwrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<double> >(new FirstOrderLowPassFilter<double>(default_cutoff_freq, _dt, 0));
00054 friction_coeff_wrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<double> >(new FirstOrderLowPassFilter<double>(default_cutoff_freq, _dt, 0));
00055 resultant_wrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<hrp::dvector6> >(new FirstOrderLowPassFilter<hrp::dvector6>(default_cutoff_freq, _dt, hrp::dvector6::Zero()));
00056 resultant_dwrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<hrp::dvector6> >(new FirstOrderLowPassFilter<hrp::dvector6>(default_cutoff_freq, _dt, hrp::dvector6::Zero()));
00057 };
00058 ~ObjectContactTurnaroundDetectorBase () {};
00059 void startDetection (const double _ref_diff_wrench, const double _max_time)
00060 {
00061 if (ref_dwrench.size() != 1) ref_dwrench.resize(1);
00062 resizeVariablesForGeneralizedWrench(1);
00063
00064 ref_dwrench[0] = _ref_diff_wrench/_max_time;
00065 max_time = _max_time;
00066 startDetectionForGeneralizedWrench();
00067 };
00068 void startDetectionForGeneralizedWrench ()
00069 {
00070 for (size_t i = 0; i < count.size(); i++) {
00071 count[i] = 0;
00072 pmode[i] = MODE_IDLE;
00073 }
00074 current_time = 0;
00075 is_filter_reset = true;
00076 is_other_constraint_detected = false;
00077 std::cerr << "[" << print_str << "] Start Object Turnaround Detection (";
00078 std::cerr << "ref_dwrench = [";
00079 for (size_t i = 0; i < ref_dwrench.size(); i++) std::cerr << ref_dwrench[i] << ", ";
00080 std::cerr << "], detect_thre = [";
00081 for (size_t i = 0; i < ref_dwrench.size(); i++) std::cerr << ref_dwrench[i] * detect_ratio_thre << ", ";
00082 std::cerr << "], start_thre = [";
00083 for (size_t i = 0; i < ref_dwrench.size(); i++) std::cerr << ref_dwrench[i] * start_ratio_thre << ", ";
00084 std::cerr << "]), max_time = " << max_time << "[s]" << std::endl;
00085 };
00086 void resizeVariablesForGeneralizedWrench (size_t generalized_wrench_dim)
00087 {
00088 phi1.resize(generalized_wrench_dim);
00089 phi2.resize(generalized_wrench_dim);
00090 dphi1.resize(generalized_wrench_dim);
00091 filtered_wrench_with_hold.resize(generalized_wrench_dim);
00092 filtered_friction_coeff_wrench_with_hold.resize(generalized_wrench_dim);
00093 raw_wrench.resize(generalized_wrench_dim);
00094 count.resize(generalized_wrench_dim);
00095 pmode.resize(generalized_wrench_dim);
00096 for (size_t i = 0; i < generalized_wrench_dim; i++) {
00097 count[i] = 0;
00098 pmode[i] = MODE_MAX_TIME;
00099 }
00100 };
00101 void calcTotalForceMoment (hrp::Vector3& total_force, hrp::Vector3& total_moment1, hrp::Vector3& total_moment2,
00102 const std::vector<hrp::Vector3>& forces, const std::vector<hrp::Vector3>& moments, const std::vector<hrp::Vector3>& hposv)
00103 {
00104
00105 total_force = total_moment1 = total_moment2 = hrp::Vector3::Zero();
00106 for (size_t i = 0; i < forces.size(); i++) {
00107 total_force += forces[i];
00108 total_moment1 += hposv[i].cross(forces[i]);
00109 total_moment2 += moments[i];
00110 }
00111 };
00112 bool checkDetection (const std::vector<hrp::Vector3>& forces,
00113 const std::vector<hrp::Vector3>& moments,
00114 const std::vector<hrp::Vector3>& hposv)
00115 {
00116
00117
00118
00119
00120
00121 hrp::Vector3 total_force, total_moment1, total_moment2;
00122 calcTotalForceMoment(total_force, total_moment1, total_moment2, forces, moments, hposv);
00123
00124 bool ret = false;
00125 switch(dtw) {
00126 case TOTAL_FORCE:
00127 {
00128 ret = checkDetection(axis.dot(total_force), total_force(2));
00129 break;
00130 }
00131 case TOTAL_MOMENT:
00132 {
00133
00134 ret = checkDetection(axis.dot(total_moment1 - moment_center.cross(total_force)), 0.0);
00135 }
00136 break;
00137 case TOTAL_MOMENT2:
00138 {
00139
00140 ret = checkDetection(axis.dot(total_moment1 + total_moment2 - moment_center.cross(total_force)), 0.0);
00141 }
00142 break;
00143 case GENERALIZED_WRENCH:
00144 {
00145 hrp::dvector6 resultant_OR_wrench;
00146 for (size_t i = 0; i < 3; i++) {
00147 resultant_OR_wrench(i) = total_force(i);
00148 resultant_OR_wrench(i+3) = total_moment1(i) + total_moment2(i);
00149 }
00150 ret = checkDetection(resultant_OR_wrench);
00151 };
00152 break;
00153 default:
00154 break;
00155 };
00156 return ret;
00157 };
00158 bool checkDetection (const double raw_wrench_value, const double raw_friction_coeff_wrench_value)
00159 {
00160 if (is_filter_reset) {
00161 std::cerr << "[" << print_str << "] Object Turnaround Detection Reset Values. (raw_wrench_value = " << raw_wrench_value << ", raw_friction_coeff_wrench_value = " << raw_friction_coeff_wrench_value << ")" << std::endl;
00162 wrench_filter->reset(raw_wrench_value);
00163 dwrench_filter->reset(0);
00164 friction_coeff_wrench_filter->reset(raw_friction_coeff_wrench_value);
00165 filtered_wrench_with_hold[0] = wrench_filter->getCurrentValue();
00166 filtered_friction_coeff_wrench_with_hold[0] = friction_coeff_wrench_filter->getCurrentValue();
00167 is_filter_reset = false;
00168 }
00169 raw_wrench[0] = raw_wrench_value;
00170 double prev_filtered_wrench = wrench_filter->getCurrentValue();
00171 double filtered_wrench = wrench_filter->passFilter(raw_wrench_value);
00172 double filtered_dwrench = dwrench_filter->passFilter((filtered_wrench-prev_filtered_wrench)/dt);
00173 friction_coeff_wrench_filter->passFilter(raw_friction_coeff_wrench_value);
00174
00175 if ( !(is_hold_values && isDetected()) ) {
00176 filtered_wrench_with_hold[0] = wrench_filter->getCurrentValue();
00177 filtered_friction_coeff_wrench_with_hold[0] = friction_coeff_wrench_filter->getCurrentValue();
00178 }
00179
00180 phi1[0] = wrench_filter->getCurrentValue();
00181 phi2[0] = friction_coeff_wrench_filter->getCurrentValue();
00182 dphi1[0] = dwrench_filter->getCurrentValue();
00183 return updateProcessModeFromDwrench(std::vector<double>(1, filtered_dwrench));
00184 };
00185 bool checkDetection (const hrp::dvector6& raw_resultant_wrench_value)
00186 {
00187 if (is_filter_reset) {
00188 std::cerr << "[" << print_str << "] Object Turnaround Detection Reset Values. (raw_resultant_wrench_value = " << raw_resultant_wrench_value.format(Eigen::IOFormat(Eigen::StreamPrecision, 0, ", ", ", ", "", "", "[", "]")) << ")" << std::endl;
00189 resultant_wrench_filter->reset(raw_resultant_wrench_value);
00190 resultant_dwrench_filter->reset(hrp::dvector6::Zero());
00191 }
00192 hrp::dvector6 prev_filtered_resultant_wrench = resultant_wrench_filter->getCurrentValue();
00193 hrp::dvector6 filtered_resultant_wrench = resultant_wrench_filter->passFilter(raw_resultant_wrench_value);
00194 hrp::dvector6 filtered_resultant_dwrench = resultant_dwrench_filter->passFilter((filtered_resultant_wrench - prev_filtered_resultant_wrench)/dt);
00195 calcPhiValueFromConstraintConversionMatrix(phi1, constraint_conversion_matrix1, filtered_resultant_wrench);
00196 calcPhiValueFromConstraintConversionMatrix(phi2, constraint_conversion_matrix2, filtered_resultant_wrench);
00197 calcPhiValueFromConstraintConversionMatrix(dphi1, constraint_conversion_matrix1, filtered_resultant_dwrench);
00198 if (is_filter_reset) {
00199 filtered_wrench_with_hold = phi1;
00200 filtered_friction_coeff_wrench_with_hold = phi2;
00201 filtered_resultant_wrench_with_hold = filtered_resultant_wrench;
00202 is_filter_reset = false;
00203 }
00204
00205 if ( !(is_hold_values && isDetected()) ) {
00206 filtered_wrench_with_hold = phi1;
00207 filtered_friction_coeff_wrench_with_hold = phi2;
00208 filtered_resultant_wrench_with_hold = filtered_resultant_wrench;
00209 }
00210
00211 calcPhiValueFromConstraintConversionMatrix(raw_wrench, constraint_conversion_matrix1, raw_resultant_wrench_value);
00212
00213 return updateProcessModeFromDwrench(dphi1);
00214 };
00215 void calcPhiValueFromConstraintConversionMatrix (std::vector<double>& phi, const std::vector<hrp::dvector6>& ccm, const hrp::dvector6& res_wrench)
00216 {
00217 for (size_t i = 0; i < ccm.size(); i++) phi[i] = ccm[i].dot(res_wrench);
00218 };
00219 bool updateProcessModeFromDwrench (const std::vector<double>& tmp_dwrench)
00220 {
00221
00222
00223
00224 for (size_t i = 0; i < ref_dwrench.size(); i++) {
00225 if (!is_other_constraint_detected) {
00226 switch (pmode[i]) {
00227 case MODE_IDLE:
00228 if ( (ref_dwrench[i] > 0.0) ? (tmp_dwrench[i] > ref_dwrench[i]*start_ratio_thre) : (tmp_dwrench[i] < ref_dwrench[i]*start_ratio_thre) ) {
00229 count[i]++;
00230 if (count[i] > start_count_thre) {
00231 pmode[i] = MODE_STARTED;
00232 count[i] = 0;
00233 std::cerr << "[" << print_str << "] Object Turnaround Detection Started [idx=" << i << "]. (time = " << current_time << "[s], " << start_count_thre*dt << "[s] after the first start detection)" << std::endl;
00234 }
00235 } else {
00236
00237 }
00238 break;
00239 case MODE_STARTED:
00240 if ( (ref_dwrench[i] > 0.0) ? (tmp_dwrench[i] < ref_dwrench[i]*detect_ratio_thre) : (tmp_dwrench[i] > ref_dwrench[i]*detect_ratio_thre) ) {
00241 count[i]++;
00242 if (count[i] > detect_count_thre) {
00243 pmode[i] = MODE_DETECTED;
00244 count[i] = 0;
00245 std::cerr << "[" << print_str << "] Object Turnaround Detected [idx=" << i << "]. (time = " << current_time << "[s], " << detect_count_thre*dt << "[s] after the first detection)" << std::endl;
00246 }
00247 } else {
00248 if ( ((ref_dwrench[i] > 0.0) ? (tmp_dwrench[i] > ref_dwrench[i]*forgetting_ratio_thre) : (tmp_dwrench[i] < ref_dwrench[i]*forgetting_ratio_thre)) &&
00249 (count[i] > 0) ) {
00250 count[i]--;
00251 }
00252 }
00253 break;
00254 case MODE_DETECTED:
00255 {
00256 count[i]++;
00257 if (count[i] > other_detect_count_thre) {
00258 is_other_constraint_detected = true;
00259 std::cerr << "[" << print_str << "] Object Turnaround Other Detected Time Limit [idx=" << i << "]. (time = " << current_time << "[s], " << other_detect_count_thre*dt << "[s] after the first detection)" << std::endl;
00260 }
00261 }
00262 break;
00263 case MODE_MAX_TIME:
00264 break;
00265 default:
00266 break;
00267 }
00268 if (max_time <= current_time && (pmode[i] != MODE_DETECTED)) {
00269 if (pmode[i] != MODE_MAX_TIME) std::cerr << "[" << print_str << "] Object Turnaround Detection max time reached. [idx=" << i << "]" << std::endl;
00270 pmode[i] = MODE_MAX_TIME;
00271 }
00272 } else {
00273 if (pmode[i] != MODE_DETECTED) pmode[i] = MODE_OTHER_DETECTED;
00274 }
00275 }
00276 current_time += dt;
00277 return isDetected();
00278 };
00279 bool isDetected (const size_t idx) const { return (pmode[idx] == MODE_DETECTED); };
00280 bool isDetected () const
00281 {
00282 for (size_t i = 0; i < pmode.size(); i++) {
00283 if (isDetected(i)) return true;
00284 }
00285 return false;
00286 };
00287 void printParams () const
00288 {
00289 std::string tmpstr;
00290 switch (dtw) {
00291 case TOTAL_FORCE:
00292 tmpstr = "TOTAL_FORCE";break;
00293 case TOTAL_MOMENT:
00294 tmpstr = "TOTAL_MOMENT";break;
00295 case TOTAL_MOMENT2:
00296 tmpstr = "TOTAL_MOMENT2";break;
00297 case GENERALIZED_WRENCH:
00298 tmpstr = "GENERALIZED_WRENCH";break;
00299 default:
00300 tmpstr = "";break;
00301 }
00302 std::cerr << "[" << print_str << "] ObjectContactTurnaroundDetectorBase params (" << tmpstr << ")" << std::endl;
00303 std::cerr << "[" << print_str << "] wrench_cutoff_freq = " << wrench_filter->getCutOffFreq() << "[Hz], dwrench_cutoff_freq = " << dwrench_filter->getCutOffFreq() << "[Hz], friction_coeff_wrench_freq = " << friction_coeff_wrench_filter->getCutOffFreq()
00304 << "[Hz], resultant_wrench_cutoff_freq = " << resultant_wrench_filter->getCutOffFreq() << "[Hz], resultant_dwrench_cutoff_freq = " << resultant_dwrench_filter->getCutOffFreq() << "[Hz]" << std::endl;
00305 std::cerr << "[" << print_str << "] detect_ratio_thre = " << detect_ratio_thre << ", start_ratio_thre = " << start_ratio_thre << ", forgetting_ratio_thre = " << forgetting_ratio_thre
00306 << ", start_time_thre = " << start_count_thre*dt << "[s], detect_time_thre = " << detect_count_thre*dt << "[s], other_detect_time_thre = " << other_detect_count_thre*dt << std::endl;
00307 std::cerr << "[" << print_str << "] axis = [" << axis(0) << ", " << axis(1) << ", " << axis(2)
00308 << "], moment_center = " << moment_center(0) << ", " << moment_center(1) << ", " << moment_center(2) << "][m]" << std::endl;
00309 std::cerr << "[" << print_str << "] constraint_conversion_matrix1 = [";
00310 for (size_t i = 0; i < constraint_conversion_matrix1.size(); i++) {
00311 std::cerr << constraint_conversion_matrix1[i].format(Eigen::IOFormat(Eigen::StreamPrecision, 0, ", ", ", ", "", "", "[", "]"));
00312 }
00313 std::cerr << "], constraint_conversion_matrix2 = [";
00314 for (size_t i = 0; i < constraint_conversion_matrix2.size(); i++) {
00315 std::cerr << constraint_conversion_matrix2[i].format(Eigen::IOFormat(Eigen::StreamPrecision, 0, ", ", ", ", "", "", "[", "]"));
00316 }
00317 std::cerr << "]" << std::endl;
00318 std::cerr << "[" << print_str << "] is_hold_values = " << (is_hold_values?"true":"false") << std::endl;
00319 std::cerr << "[" << print_str << "] ref_dwrench = [";
00320 for (size_t i = 0; i < ref_dwrench.size(); i++) std::cerr << ref_dwrench[i] << ", ";
00321 std::cerr << "], max_time = " << max_time << "[s]" << std::endl;
00322 };
00323
00324 void setPrintStr (const std::string& str) { print_str = str; };
00325 void setWrenchCutoffFreq (const double a)
00326 {
00327
00328 wrench_filter->setCutOffFreq(a);
00329 friction_coeff_wrench_filter->setCutOffFreq(a);
00330 resultant_wrench_filter->setCutOffFreq(a);
00331 };
00332 void setDwrenchCutoffFreq (const double a)
00333 {
00334
00335 dwrench_filter->setCutOffFreq(a);
00336 resultant_dwrench_filter->setCutOffFreq(a);
00337 };
00338
00339
00340
00341 void setDetectRatioThre (const double a) { detect_ratio_thre = a; };
00342 void setStartRatioThre (const double a) { start_ratio_thre = a; };
00343 void setDetectTimeThre (const double a) { detect_count_thre = round(a/dt); };
00344 void setStartTimeThre (const double a) { start_count_thre = round(a/dt); };
00345 void setOtherDetectTimeThre (const double a) { other_detect_count_thre = round(a/dt); };
00346 void setForgettingRatioThre (const double a) { forgetting_ratio_thre = a; };
00347 void setAxis (const hrp::Vector3& a) { axis = a; };
00348 void setMomentCenter (const hrp::Vector3& a) { moment_center = a; };
00349 void setConstraintConversionMatricesRefDwrench (const std::vector<hrp::dvector6>& ccm1, const std::vector<hrp::dvector6>& ccm2, const std::vector<double>& refdw)
00350 {
00351 constraint_conversion_matrix1 = ccm1;
00352 constraint_conversion_matrix2 = ccm2;
00353 ref_dwrench = refdw;
00354 resizeVariablesForGeneralizedWrench(constraint_conversion_matrix1.size());
00355 };
00356 void setDetectorTotalWrench (const detector_total_wrench _dtw)
00357 {
00358 if (_dtw != dtw) {
00359 is_filter_reset = true;
00360 }
00361 dtw = _dtw;
00362 };
00363 void setIsHoldValues (const bool a) { is_hold_values = a; };
00364 void setMaxTime (const double a) { max_time = a; };
00365
00366 double getWrenchCutoffFreq () const { return wrench_filter->getCutOffFreq(); };
00367 double getDwrenchCutoffFreq () const { return dwrench_filter->getCutOffFreq(); };
00368
00369 double getDetectRatioThre () const { return detect_ratio_thre; };
00370 double getStartRatioThre () const { return start_ratio_thre; };
00371 double getDetectTimeThre () const { return detect_count_thre*dt; };
00372 double getStartTimeThre () const { return start_count_thre*dt; };
00373 double getOtherDetectTimeThre () const { return other_detect_count_thre*dt; };
00374 double getForgettingRatioThre () const { return forgetting_ratio_thre; };
00375 hrp::Vector3 getAxis () const { return axis; };
00376 hrp::Vector3 getMomentCenter () const { return moment_center; };
00377 void getConstraintConversionMatricesRefDwrench (std::vector<hrp::dvector6>& ccm1, std::vector<hrp::dvector6>& ccm2, std::vector<double>& refdw) const
00378 {
00379 ccm1 = constraint_conversion_matrix1;
00380 ccm2 = constraint_conversion_matrix2;
00381 refdw = ref_dwrench;
00382 };
00383 detector_total_wrench getDetectorTotalWrench () const { return dtw; };
00384 process_mode getMode (const size_t idx) const { return pmode[idx]; };
00385 size_t getDetectGeneralizedWrenchDim () const { return pmode.size(); };
00386 hrp::dvector getDataForLogger () const
00387 {
00388 size_t data_size = 5;
00389 hrp::dvector ret(pmode.size()*data_size);
00390 for (size_t i = 0; i < pmode.size(); i++) {
00391 size_t tmpoff = i*data_size;
00392 ret(tmpoff) = static_cast<double>(getMode(i));
00393 ret(1+tmpoff) = raw_wrench[i];
00394 ret(2+tmpoff) = phi1[i];
00395 ret(3+tmpoff) = dphi1[i];
00396 ret(4+tmpoff) = phi2[i];
00397 }
00398 return ret;
00399 };
00400 bool getIsHoldValues () const { return is_hold_values; };
00401 double getMaxTime () const { return max_time; };
00402
00403 std::vector<double> getFilteredWrenchWithHold () const { return filtered_wrench_with_hold; };
00404 std::vector<double> getFilteredFrictionCoeffWrenchWithHold () const { return filtered_friction_coeff_wrench_with_hold; };
00405 hrp::dvector6 getFilteredResultantWrenchWithHold () const { return filtered_resultant_wrench_with_hold; };
00406 };
00407 #endif // OBJECTCONTACTTURNAROUNDDETECTORBASE_H