00001
00002
00003 #ifndef SIMU_ROBOT_POSE_ANALYSIS_HPP
00004 #define SIMU_ROBOT_POSE_ANALYSIS_HPP
00005
00006 #include "kernel/jafarException.hpp"
00007 #include "kernel/dataLog.hpp"
00008
00009 #include "jmath/jblas.hpp"
00010
00011 #include "slam/slamEkf.hpp"
00012
00013 #include "simu/robot.hpp"
00014
00015 namespace jafar {
00016 namespace simu {
00017
00018 class RobotPoseAnalysis : public jafar::kernel::DataLoggable {
00019
00020 public:
00021
00022 enum Type {XY, XYT, XYZ, XYZYPR};
00023
00024 private:
00025
00026 Type p_type;
00027
00028 std::size_t size() const {
00029 switch(p_type) {
00030 case XY:
00031 return 2;
00032 case XYT:
00033 case XYZ:
00034 return 3;
00035 case XYZYPR:
00036 return 6;
00037 }
00038 }
00039
00040 slam::SlamEkf const& p_slam;
00041 simu::Robot const& p_robot;
00042
00043 public:
00044
00045 RobotPoseAnalysis(jafar::slam::SlamEkf& slam,
00046 Robot const& robot,
00047 Type type = XYZYPR):
00048 p_type(type), p_slam(slam), p_robot(robot) {}
00049
00050 double computeNEES() const {
00051 using namespace ublas;
00052 try {
00053
00054 jblas::vec xf = p_robot.pose.getX() - p_slam.refPose(p_robot.robotId);
00055 if (xf(3) > M_PI)
00056 xf(3) -= 2*M_PI;
00057 if (xf(3) < -M_PI)
00058 xf(3) += 2*M_PI;
00059
00060 jblas::sym_mat xfCov = p_slam.refPoseCov(p_robot.robotId);
00061
00062 jblas::vec x(size());
00063 jblas::sym_mat xCov(size(), size());
00064
00065 switch(p_type) {
00066
00067 case XY:
00068 case XYZ:
00069 {
00070 range r(0,size());
00071 x.assign(project(xf,r));
00072 xCov.assign(project(xfCov,r,r));
00073 break;
00074 }
00075 case XYT:
00076 {
00077 x(0) = xf(0);
00078 x(1) = xf(1);
00079 x(2) = xf(3);
00080 range r(0,2);
00081 project(xCov,r,r).assign(project(xfCov,r,r));
00082 xCov(0,2) = xfCov(0,3);
00083 xCov(1,2) = xfCov(1,3);
00084 xCov(2,2) = xfCov(3,3);
00085 break;
00086 }
00087 case XYZYPR:
00088 {
00089 x.assign(xf);
00090 xCov.assign(xfCov);
00091 break;
00092 }
00093
00094 }
00095
00096 jblas::mat xCovInv(xCov);
00097 JFR_TRACE_BEGIN;
00098 jmath::ublasExtra::lu_inv(xCov, xCovInv);
00099 JFR_TRACE_END("RobotPoseAnalysis::computeNEES");
00100 return ublas::inner_prod(x, ublas::prod(xCovInv, x));
00101 }
00102 catch(std::exception const& e) {
00103 JFR_WARNING("cannot compute NEES, returning 0");
00104 return 0.0;
00105 }
00106 }
00107
00108 jblas::vec computeErrors() const {
00109 using namespace jblas;
00110 using namespace ublas;
00111 vec err(size());
00112
00113 switch(p_type) {
00114 case XYT:
00115 err(0) = p_robot.pose.getX()(0) - p_slam.refPose(p_robot.robotId)(0);
00116 err(1) = p_robot.pose.getX()(1) - p_slam.refPose(p_robot.robotId)(1);
00117 err(2) = p_robot.pose.getX()(3) - p_slam.refPose(p_robot.robotId)(3);
00118 break;
00119 case XYZYPR:
00120 err.assign(p_robot.pose.getX() - p_slam.refPose(p_robot.robotId));
00121 break;
00122 default:
00123 JFR_RUN_TIME("not implemented yet");
00124 }
00125
00126 for (std::size_t i = 0 ; i < err.size() ; ++i) {
00127 err(i) = fabs(err(i));
00128 }
00129 return err;
00130 }
00131
00132 protected:
00133
00134 void writeLogHeader(kernel::DataLogger& log) const {
00135 log.writeComment("simu: RobotPoseAnalysis");
00136 log.writeLegend("robot pose NEES");
00137 switch(p_type) {
00138 case XYT:
00139 log.writeLegendTokens("err_x err_y err_yaw");
00140 break;
00141 case XYZYPR:
00142 log.writeLegendTokens("err_x err_y err_z err_yaw err_pitch err_roll");
00143 break;
00144 default:
00145 JFR_RUN_TIME("not implemented yet");
00146 }
00147 }
00148
00149 void writeLogData(kernel::DataLogger& log) const {
00150 log.writeData(computeNEES());
00151 log.writeDataVector(computeErrors());
00152 }
00153
00154 };
00155
00156 }
00157 }
00158
00159 #endif // SIMU_ROBOT_POSE_ANALYSIS_HPP