Go to the documentation of this file.00001
00012 #include <carl_phidgets/orientation_filter.h>
00013
00014 OrientationFilter::OrientationFilter()
00015 {
00016
00017 jointStates.name.push_back("base_footprint_base_link_pitch_joint");
00018 jointStates.name.push_back("base_footprint_base_link_roll_joint");
00019 jointStates.name.push_back("left_rear_strut_link_left_rear_strut_top_link_joint");
00020 jointStates.name.push_back("right_rear_strut_link_right_rear_strut_top_link_joint");
00021 jointStates.position.resize(4);
00022 jointStates.velocity.resize(4);
00023 jointStates.effort.resize(4);
00024
00025 baseOrientationInitialized = false;
00026 output = false;
00027
00028
00029 frameJointStatePublisher = n.advertise<sensor_msgs::JointState>("frame_joint_states", 1);
00030 baseImuSubscriber = n.subscribe<sensor_msgs::Imu>("imu_base/data_raw", 1, &OrientationFilter::baseImuCallback, this);
00031 topImuSubscriber = n.subscribe<sensor_msgs::Imu>("imu_top/data_raw", 1, &OrientationFilter::topImuCallback, this);
00032
00033
00034 prevUpdateTimeTop = ros::Time::now();
00035 prevUpdateTime = ros::Time::now();
00036 PPrevTop = 0;
00037 PPrev[0] = 0;
00038 PPrev[1] = 0;
00039 }
00040
00041 void OrientationFilter::topImuCallback(const sensor_msgs::Imu::ConstPtr& data)
00042 {
00043 if (!baseOrientationInitialized)
00044 {
00045 if (!output)
00046 {
00047 ROS_INFO("Waiting for base orientation to be initialized before calculating frame pitch...");
00048 output = true;
00049 }
00050 return;
00051 }
00052
00053
00054
00055 float w = data->angular_velocity.y;
00056
00057
00058 float Q = data->angular_velocity_covariance[4];
00059
00060
00061 float x = data->linear_acceleration.x;
00062 float y = data->linear_acceleration.y;
00063 float z = data->linear_acceleration.z;
00064 float a = atan2(x, z) + jointStates.position[0];
00065
00066
00067 float R = 100*data->linear_acceleration_covariance[4];
00068
00069
00070
00071 float thetaPrev = jointStates.position[3];
00072
00073
00074 float deltaT = (ros::Time::now() - prevUpdateTimeTop).toSec();
00075
00076 prevUpdateTimeTop = ros::Time::now();
00077
00078
00079 float thetaPredicted = thetaPrev + w*deltaT;
00080 float P = PPrevTop + Q;
00081
00082 float J = P/(P + R);
00083
00084 float pitch;
00085 if (fabs(G - sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2))) < .05)
00086 pitch = thetaPredicted + J*(a - thetaPredicted);
00087 else
00088 pitch = thetaPredicted;
00089
00090 PPrevTop = (1 - J)*P;
00091
00092
00093
00094
00095
00096
00097
00098 jointStates.position[2] = -pitch;
00099 jointStates.position[3] = pitch;
00100 frameJointStatePublisher.publish(jointStates);
00101 }
00102
00103 void OrientationFilter::baseImuCallback(const sensor_msgs::Imu::ConstPtr& data)
00104 {
00105
00106
00107 float w[2];
00108 w[0] = -data->angular_velocity.x;
00109 w[1] = data->angular_velocity.y;
00110
00111
00112 float Q[2];
00113 Q[0] = data->angular_velocity_covariance[0];
00114 Q[1] = data->angular_velocity_covariance[4];
00115
00116
00117 float x = -data->linear_acceleration.x;
00118 float y = data->linear_acceleration.y;
00119 float z = -data->linear_acceleration.z;
00120 float a[2];
00121 a[0] = atan2(y, z);
00122 a[1] = atan2(x, z);
00123
00124
00125 float R[2];
00126 R[0] = 100*data->linear_acceleration_covariance[0];
00127 R[1] = 100*data->linear_acceleration_covariance[4];
00128
00129
00130
00131 float thetaPrev[2];
00132 thetaPrev[0] = jointStates.position[0];
00133 thetaPrev[1] = jointStates.position[1];
00134
00135
00136 float deltaT = (ros::Time::now() - prevUpdateTime).toSec();
00137
00138 prevUpdateTime = ros::Time::now();
00139
00140
00141 float thetaPredicted[2];
00142 float P[2];
00143 float J[2];
00144 thetaPredicted[0] = thetaPrev[0] + w[0]*deltaT;
00145 thetaPredicted[1] = thetaPrev[1] + w[1]*deltaT;
00146 P[0] = PPrev[0] + Q[0];
00147 P[1] = PPrev[1] + Q[1];
00148 J[0] = P[0]/(P[0] + R[0]);
00149 J[1] = P[1]/(P[1] + R[1]);
00150
00151
00152 if (fabs(G - sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2))) < .05)
00153 {
00154 jointStates.position[0] = thetaPredicted[0] + J[0]*(a[0] - thetaPredicted[0]);
00155 jointStates.position[1] = thetaPredicted[1] + J[1]*(a[1] - thetaPredicted[1]);
00156 }
00157 else
00158 {
00159 jointStates.position[0] = thetaPredicted[0];
00160 jointStates.position[1] = thetaPredicted[1];
00161 }
00162
00163 PPrev[0] = (1 - J[0])*P[0];
00164 PPrev[1] = (1 - J[1])*P[1];
00165
00166
00167
00168
00169
00170
00171
00172 frameJointStatePublisher.publish(jointStates);
00173
00174 if (!baseOrientationInitialized)
00175 {
00176 ROS_INFO("Base orientation initialized!");
00177 baseOrientationInitialized = true;
00178 }
00179 }
00180
00181 int main(int argc, char **argv)
00182 {
00183
00184 ros::init(argc, argv, "orientation_filter");
00185
00186
00187 OrientationFilter of;
00188
00189 ros::spin();
00190
00191 return EXIT_SUCCESS;
00192 }