00001
00002
00003
00004
00005
00006
00007
00008 #include <StateEstimators/ViconImuStateEstimator.hpp>
00009 #include <tk_state/StateEstimatorController.hpp>
00010
00011 #include <telekyb_base/ROS.hpp>
00012
00013 #include <telekyb_msgs/TKState.h>
00014
00015
00016 PLUGINLIB_DECLARE_CLASS(tk_state, ViconImuStateEstimator, telekyb_state::ViconImuStateEstimator, TELEKYB_NAMESPACE::StateEstimator);
00017
00018 namespace telekyb_state {
00019
00020 ViconImuStateEstimatorOptions::ViconImuStateEstimatorOptions()
00021 : OptionContainer("ViconImuStateEstimator")
00022 {
00023 tViconSeTopicName = addOption<std::string>("tViconSeTopicName","TopicName of Vicon Sensor.","undef",true,true);
00024 tImuSeTopicName = addOption<std::string>("tImuSeTopicName","TopicName of Imu Sensor.","undef",true,true);
00025
00026 Eigen::Matrix3d m = Eigen::Matrix3d::Zero();
00027 m.diagonal() << 1.0,-1.0,-1.0;
00028 tViconToNEDMatrix = addOption<Eigen::Matrix3d>("tViconToNEDMatrix","ConversionMatrix from Vicon to NED", m, false, true);
00029
00030 tViconToNEDQuaternion = addOption<Eigen::Quaterniond>("tViconToNEDQuaternion","ConversionQuaternion from Vicon to NED", Eigen::Quaterniond(1.0,0.0,0.0,0.0), false, true);
00031
00032 tViconVelFilterFreq = addOption<double>("tViconVelFilterFreq",
00033 "Frequency of Velocity Filter (Initial)", 40.0, false, true);
00034 tViconSmoothVelFilterFreq = addOption<double>("tViconSmoothVelFilterFreq",
00035 "Frequency of Smooth Velocity Filter (Initial)", 10.0, false, true);
00036 tViconAngFilterFreq = addOption<double>("tViconAngFilterFreq",
00037 "Frequency of Angular Velocity Filter (Initial)", 30.0, false, true);
00038
00039 tViconSampleTime = addOption<double>("tViconSampleTime",
00040 "Sampling Time of Vicon System. Default is 120Hz", 0.008333333333, false, true);
00041
00042 tViconPublishSmoothVel = addOption<bool>("tViconPublishSmoothVel",
00043 "Publish TKState with smoothed Velocity", false, false, true);
00044
00045 timeStep = addOption<double>("timeStep","Time step for state publishing",4e-3,false,true);
00046
00047 tIntegrateLinVel = addOption<bool>("tIntegrateLinVel",
00048 "Integrate linear velocity when Vicon position is not available", false, false, false);
00049 tIntegrateAngVel = addOption<bool>("tIntegrateAngVel",
00050 "Integrate angular velocity when Vicon orientation is not available", false, false, false);
00051
00052 }
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 void ViconImuStateEstimator::initVelocityFilters()
00064 {
00065 IIRFiltDeriv isDerivative;
00066 for(int i=0;i<3;i++){
00067 velFilter[i] = new IIRFilter(
00068 isDerivative,
00069 2.0*M_PI*options.tViconVelFilterFreq->getValue(),
00070 1.0,
00071 options.tViconSampleTime->getValue());
00072 }
00073
00074 for(int i=0;i<3;i++){
00075 smoothVelFilter[i] = new IIRFilter(
00076 isDerivative,
00077 2.0*M_PI*options.tViconSmoothVelFilterFreq->getValue(),
00078 1.0,
00079 options.tViconSampleTime->getValue());
00080 }
00081 }
00082
00083 void ViconImuStateEstimator::initialize()
00084 {
00085
00086 nodeHandle = ROSModule::Instance().getMainNodeHandle();
00087
00088 initVelocityFilters();
00089
00090 spinning = true;
00091 thread = boost::thread(&ViconImuStateEstimator::spin, this);
00092 }
00093
00094 void ViconImuStateEstimator::spin()
00095 {
00096 while(spinning)
00097 {
00098 rtTimer.reset();
00099 publishState();
00100
00101 Time toSleep = Time(options.timeStep->getValue()) - rtTimer.getElapsed();
00102 if (toSleep>0) {
00103 toSleep.sleep();
00104 } else {
00105 ROS_WARN("State estimation was too slow!");
00106 }
00107 }
00108 }
00109
00110 void ViconImuStateEstimator::willBecomeActive()
00111 {
00112 viconSub = nodeHandle.subscribe<geometry_msgs::PoseWithCovarianceStamped>(
00113 options.tViconSeTopicName->getValue(),1, &ViconImuStateEstimator::viconCallback, this);
00114
00115 imuSub = nodeHandle.subscribe<sensor_msgs::Imu>(
00116 options.tImuSeTopicName->getValue(),1, &ViconImuStateEstimator::imuCallback, this);
00117
00118 if (options.tViconPublishSmoothVel->getValue()) {
00119 smoothVelPub = nodeHandle.advertise<telekyb_msgs::TKState>("SmoothedVelocity",1);
00120 }
00121
00122
00123
00124
00125
00126 }
00127
00128 void ViconImuStateEstimator::willBecomeInActive()
00129 {
00130 viconSub.shutdown();
00131 imuSub.shutdown();
00132 if (options.tViconPublishSmoothVel->getValue()) {
00133 smoothVelPub.shutdown();
00134 }
00135
00136 }
00137
00138 void ViconImuStateEstimator::destroy()
00139 {
00140 for(int i=0;i<3;i++){
00141 delete velFilter[i];
00142 delete smoothVelFilter[i];
00143 }
00144
00145 spinning = false;
00146 thread.join();
00147 }
00148
00149 std::string ViconImuStateEstimator::getName() const
00150 {
00151 return options.tViconSeTopicName->getValue();
00152 }
00153
00154 void ViconImuStateEstimator::viconCallback(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg)
00155 {
00156 Position3D posVicon(msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z);
00157 Quaternion quatVicon(msg->pose.pose.orientation.w, msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z);
00158
00159
00160 double output[3],outputMore[3];
00161 std::vector<double> input(1);
00162 input[0]=posNED(0);
00163 velFilter[0]->step(input, output[0]);
00164 smoothVelFilter[0]->step(input, outputMore[0]);
00165 input[0] = posNED(1);
00166 velFilter[1]->step(input, output[1]);
00167 smoothVelFilter[1]->step(input, outputMore[1]);
00168 input[0] = posNED(2);
00169 velFilter[2]->step(input, output[2]);
00170 smoothVelFilter[2]->step(input, outputMore[2]);
00171
00172 boost::mutex::scoped_lock scopedLock(viconMutex);
00173
00174 posNED = options.tViconToNEDQuaternion->getValue()*posVicon;
00175 velNED << output[0], output[1], output[2];
00176 smoothVelNED << outputMore[0], outputMore[1], outputMore[2];
00177 quatNED = options.tViconToNEDQuaternion->getValue()*quatVicon;
00178 scopedLock.unlock();
00179 }
00180
00181 void ViconImuStateEstimator::publishState()
00182 {
00183 TKState tStateMsg;
00184
00185
00186 boost::mutex::scoped_lock scopedLock(timeMutex);
00187 telekyb::Time elapsedTime = intTimer.getElapsed();
00188 intTimer.reset();
00189 intTime = intTime + elapsedTime;
00190 tStateMsg.time = intTime;
00191 scopedLock.unlock();
00192
00193
00194 boost::mutex::scoped_lock scopedViconLock(viconMutex);
00195
00196 if (options.tIntegrateLinVel->getValue()){
00197 posNED = posNED + velNED*elapsedTime.toDSec();
00198 }
00199 tStateMsg.position = posNED;
00200 tStateMsg.linVelocity = velNED;
00201
00202 boost::mutex::scoped_lock scopedImuLock(imuMutex);
00203
00204 if (options.tIntegrateAngVel->getValue()){
00205 double angVelSqNorm = angVelocityNED.squaredNorm();
00206 Eigen::Quaterniond deltaQuat;
00207 double deltaT = elapsedTime.toDSec();
00208 deltaQuat.w() = 1.0 - deltaT*deltaT*angVelSqNorm/8.0;
00209 deltaQuat.vec() = (.5*deltaT - deltaT*deltaT*deltaT*angVelSqNorm/24) * angVelocityNED;
00210 quatNED = quatNED*deltaQuat;
00211 }
00212 tStateMsg.orientation = quatNED;
00213 tStateMsg.angVelocity = angVelocityNED;
00214
00215 scopedImuLock.unlock();
00216
00217
00218 if (options.tViconPublishSmoothVel->getValue()) {
00219 telekyb_msgs::TKState smoothVelMsg;
00220 tStateMsg.toTKStateMsg(smoothVelMsg);
00221
00222 smoothVelMsg.twist.linear.x = smoothVelNED(0);
00223 smoothVelMsg.twist.linear.y = smoothVelNED(1);
00224 smoothVelMsg.twist.linear.z = smoothVelNED(2);
00225 smoothVelPub.publish(smoothVelMsg);
00226 }
00227
00228 scopedViconLock.unlock();
00229
00230 stateEstimatorController.activeStateCallBack(tStateMsg);
00231
00232
00233
00234
00235 }
00236
00237 void ViconImuStateEstimator::imuCallback(const sensor_msgs::Imu::ConstPtr& msg)
00238 {
00239 boost::mutex::scoped_lock scopedLock(imuMutex);
00240
00241 angVelocityNED(0) = msg->angular_velocity.x;
00242 angVelocityNED(1) = msg->angular_velocity.y;
00243 angVelocityNED(2) = msg->angular_velocity.z;
00244
00245 scopedLock.unlock();
00246 scopedLock = boost::mutex::scoped_lock(timeMutex);
00247
00248 intTime = Time(msg->header.stamp);
00249 intTimer.reset();
00250
00251 scopedLock.unlock();
00252
00253 }
00254
00255
00256 }