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} process_mode;
00015 typedef enum {TOTAL_FORCE, TOTAL_MOMENT, TOTAL_MOMENT2} 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 hrp::Vector3 axis, moment_center;
00021 double prev_wrench, dt;
00022 double detect_ratio_thre, start_ratio_thre, ref_dwrench, max_time, current_time, current_wrench;
00023 size_t count;
00024
00025
00026
00027 size_t detect_count_thre, start_count_thre;
00028 process_mode pmode;
00029 detector_total_wrench dtw;
00030 std::string print_str;
00031 bool is_dwr_changed;
00032 public:
00033 ObjectContactTurnaroundDetectorBase (const double _dt) : axis(-1*hrp::Vector3::UnitZ()), moment_center(hrp::Vector3::Zero()), prev_wrench(0.0), dt(_dt), detect_ratio_thre(0.01), start_ratio_thre(0.5),
00034 count(0), detect_count_thre(5), start_count_thre(5), pmode(MODE_IDLE), dtw(TOTAL_FORCE), is_dwr_changed(false)
00035 {
00036 double default_cutoff_freq = 1;
00037 wrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<double> >(new FirstOrderLowPassFilter<double>(default_cutoff_freq, _dt, 0));
00038 dwrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<double> >(new FirstOrderLowPassFilter<double>(default_cutoff_freq, _dt, 0));
00039 friction_coeff_wrench_filter = boost::shared_ptr<FirstOrderLowPassFilter<double> >(new FirstOrderLowPassFilter<double>(default_cutoff_freq, _dt, 0));
00040 };
00041 ~ObjectContactTurnaroundDetectorBase () {};
00042 void startDetection (const double _ref_diff_wrench, const double _max_time)
00043 {
00044 ref_dwrench = _ref_diff_wrench/_max_time;
00045 max_time = _max_time;
00046 current_time = 0;
00047 count = 0;
00048 std::cerr << "[" << print_str << "] Start Object Turnaround Detection (ref_dwrench = " << ref_dwrench
00049 << ", detect_thre = " << detect_ratio_thre * ref_dwrench << ", start_thre = " << start_ratio_thre * ref_dwrench << "), max_time = " << max_time << "[s]" << std::endl;
00050 pmode = MODE_IDLE;
00051 };
00052 hrp::Vector3 calcTotalForce (const std::vector<hrp::Vector3>& forces)
00053 {
00054 hrp::Vector3 tmpv = hrp::Vector3::Zero();
00055 for (size_t i = 0; i < forces.size(); i++) {
00056 tmpv += forces[i];
00057 }
00058 return tmpv;
00059 };
00060 hrp::Vector3 calcTotalMoment (const std::vector<hrp::Vector3>& forces, const std::vector<hrp::Vector3>& hposv)
00061 {
00062 hrp::Vector3 tmpv = hrp::Vector3::Zero();
00063 for (size_t i = 0; i < forces.size(); i++) {
00064 tmpv += (hposv[i]-moment_center).cross(forces[i]);
00065 }
00066 return tmpv;
00067 };
00068 hrp::Vector3 calcTotalMoment2 (const std::vector<hrp::Vector3>& forces, const std::vector<hrp::Vector3>& moments, const std::vector<hrp::Vector3>& hposv)
00069 {
00070 hrp::Vector3 tmpv = hrp::Vector3::Zero();
00071 for (size_t i = 0; i < forces.size(); i++) {
00072 tmpv += (hposv[i]-moment_center).cross(forces[i]) + moments[i];
00073 }
00074 return tmpv;
00075 };
00076 bool checkDetection (const std::vector<hrp::Vector3>& forces,
00077 const std::vector<hrp::Vector3>& moments,
00078 const std::vector<hrp::Vector3>& hposv)
00079 {
00080 switch(dtw) {
00081 case TOTAL_FORCE:
00082 {
00083 hrp::Vector3 total_force = calcTotalForce(forces);
00084 checkDetection(axis.dot(total_force), total_force(2));
00085 break;
00086 }
00087 case TOTAL_MOMENT:
00088 {
00089 hrp::Vector3 total_moment = calcTotalMoment(forces, hposv);
00090 checkDetection(axis.dot(total_moment), 0.0);
00091 }
00092 break;
00093 case TOTAL_MOMENT2:
00094 {
00095 hrp::Vector3 total_moment = calcTotalMoment2(forces, moments, hposv);
00096 checkDetection(axis.dot(total_moment), 0.0);
00097 }
00098 break;
00099 default:
00100 break;
00101 };
00102 };
00103 bool checkDetection (const double wrench_value, const double friction_coeff_wrench_value)
00104 {
00105 if (is_dwr_changed) {
00106 wrench_filter->reset(wrench_value);
00107 dwrench_filter->reset(0);
00108 friction_coeff_wrench_filter->reset(friction_coeff_wrench_value);
00109 is_dwr_changed = false;
00110 }
00111 current_wrench = wrench_value;
00112 double tmp_wr = wrench_filter->passFilter(wrench_value);
00113 double tmp_dwr = dwrench_filter->passFilter((tmp_wr-prev_wrench)/dt);
00114 friction_coeff_wrench_filter->passFilter(friction_coeff_wrench_value);
00115 prev_wrench = tmp_wr;
00116 switch (pmode) {
00117 case MODE_IDLE:
00118 if (tmp_dwr > ref_dwrench*start_ratio_thre) {
00119 count++;
00120 if (count > start_count_thre) {
00121 pmode = MODE_STARTED;
00122 count = 0;
00123 std::cerr << "[" << print_str << "] Object Turnaround Detection Started. (" << start_count_thre*dt << "[s] after the first start detection)" << std::endl;
00124 }
00125 } else {
00126
00127 }
00128 break;
00129 case MODE_STARTED:
00130 if (tmp_dwr < ref_dwrench*detect_ratio_thre) {
00131 count++;
00132 if (count > detect_count_thre) {
00133 pmode = MODE_DETECTED;
00134 std::cerr << "[" << print_str << "] Object Turnaround Detected (time = " << current_time << "[s], " << detect_count_thre*dt << "[s] after the first detection)" << std::endl;
00135 }
00136 } else {
00137
00138 }
00139
00140 break;
00141 case MODE_DETECTED:
00142 break;
00143 case MODE_MAX_TIME:
00144 break;
00145 default:
00146 break;
00147 }
00148 if (max_time <= current_time && (pmode != MODE_DETECTED)) {
00149 if (pmode != MODE_MAX_TIME) std::cerr << "[" << print_str << "] Object Turnaround Detection max time reached." << std::endl;
00150 pmode = MODE_MAX_TIME;
00151 }
00152 current_time += dt;
00153 return isDetected();
00154 };
00155 bool isDetected () const { return (pmode == MODE_DETECTED); };
00156 process_mode getMode () const { return pmode; };
00157 void printParams () const
00158 {
00159 std::cerr << "[" << print_str << "] ObjectContactTurnaroundDetectorBase params (" << (dtw==TOTAL_FORCE?"TOTAL_FORCE": (dtw==TOTAL_MOMENT?"TOTAL_MOMENT":"TOTAL_MOMENT2") ) << ")" << std::endl;
00160 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() << "[Hz]" << std::endl;
00161 std::cerr << "[" << print_str << "] detect_ratio_thre = " << detect_ratio_thre << ", start_ratio_thre = " << start_ratio_thre
00162 << ", start_time_thre = " << start_count_thre*dt << "[s], detect_time_thre = " << detect_count_thre*dt << "[s]" << std::endl;
00163 std::cerr << "[" << print_str << "] axis = [" << axis(0) << ", " << axis(1) << ", " << axis(2)
00164 << "], moment_center = " << moment_center(0) << ", " << moment_center(1) << ", " << moment_center(2) << "][m]" << std::endl;
00165 };
00166 void setPrintStr (const std::string& str) { print_str = str; };
00167 void setWrenchCutoffFreq (const double a) { wrench_filter->setCutOffFreq(a); };
00168 void setDwrenchCutoffFreq (const double a) { dwrench_filter->setCutOffFreq(a); };
00169 void setFrictionCoeffWrenchCutoffFreq (const double a) { friction_coeff_wrench_filter->setCutOffFreq(a); };
00170 void setDetectRatioThre (const double a) { detect_ratio_thre = a; };
00171 void setStartRatioThre (const double a) { start_ratio_thre = a; };
00172 void setDetectTimeThre (const double a) { detect_count_thre = round(a/dt); };
00173 void setStartTimeThre (const double a) { start_count_thre = round(a/dt); };
00174 void setAxis (const hrp::Vector3& a) { axis = a; };
00175 void setMomentCenter (const hrp::Vector3& a) { moment_center = a; };
00176 void setDetectorTotalWrench (const detector_total_wrench _dtw)
00177 {
00178 if (_dtw != dtw) {
00179 is_dwr_changed = true;
00180 }
00181 dtw = _dtw;
00182 };
00183 double getWrenchCutoffFreq () const { return wrench_filter->getCutOffFreq(); };
00184 double getDwrenchCutoffFreq () const { return dwrench_filter->getCutOffFreq(); };
00185 double getFrictionCoeffWrenchCutoffFreq () const { return friction_coeff_wrench_filter->getCutOffFreq(); };
00186 double getDetectRatioThre () const { return detect_ratio_thre; };
00187 double getStartRatioThre () const { return start_ratio_thre; };
00188 double getDetectTimeThre () const { return detect_count_thre*dt; };
00189 double getStartTimeThre () const { return start_count_thre*dt; };
00190 hrp::Vector3 getAxis () const { return axis; };
00191 hrp::Vector3 getMomentCenter () const { return moment_center; };
00192 detector_total_wrench getDetectorTotalWrench () const { return dtw; };
00193 double getFilteredWrench () const { return wrench_filter->getCurrentValue(); };
00194 double getFilteredDwrench () const { return dwrench_filter->getCurrentValue(); };
00195 double getFilteredFrictionCoeffWrench () const { return friction_coeff_wrench_filter->getCurrentValue(); };
00196 double getRawWrench () const { return current_wrench; };
00197 };
00198 #endif // OBJECTCONTACTTURNAROUNDDETECTORBASE_H