localizer.cpp
Go to the documentation of this file.
00001 
00009 #include <youbot_overhead_localization/localizer.h>
00010 
00011 localizer::localizer()
00012 {
00013   std::string odomTopicName;
00014 
00015   odometryInitialized = false;
00016   pose.x = 0;
00017   pose.y = 0;
00018   pose.theta = 0;
00019 
00020   P[0] = .5;
00021   P[1] = .5;
00022   P[2] = .5;
00023 
00024   Q[0] = Q_X;
00025   Q[1] = Q_Y;
00026   Q[2] = Q_T;
00027 
00028   R[0] = R_X;
00029   R[1] = R_Y;
00030   R[2] = R_T;
00031 
00032   n.getParam("/base_localizer/odomTopic", odomTopicName);
00033 
00034   //subscriber, publisher, and service initialization
00035   baseOdometrySubscriber = n.subscribe(odomTopicName, 0, &localizer::baseOdometryCallback, this);
00036   positionFromCameraSubscriber = n.subscribe("/image_calibration/position_from_camera", 1,
00037                                              &localizer::positionFromCameraCallback, this);
00038   baseLocalizationPublisher = n.advertise<youbot_overhead_localization::Pose2d>("base_localizer/pose_2d", 1);
00039   coordConversionClient = n.serviceClient<youbot_overhead_vision::CoordConversion>("coord_conversion");
00040 }
00041 
00042 void localizer::baseOdometryCallback(const nav_msgs::Odometry& odometry)
00043 {
00044   if (!odometryInitialized)
00045   {
00046     lastReceivedOdometry = odometry;
00047     odometryInitialized = true;
00048   }
00049   else
00050   {
00051     float u[3]; //change in odometry
00052     float B[3][3]; //transformation matrix
00053     double timePassed = (odometry.header.stamp - lastReceivedOdometry.header.stamp).toSec();
00054 
00055     u[0] = odometry.twist.twist.linear.x * timePassed;
00056     u[1] = odometry.twist.twist.linear.y * timePassed;
00057     u[2] = odometry.twist.twist.angular.z * timePassed;
00058 
00059     B[0][0] = cos(pose.theta);
00060     B[0][1] = sin(pose.theta);
00061     B[0][2] = 0.0;
00062     B[1][0] = -sin(pose.theta);
00063     B[1][1] = cos(pose.theta);
00064     B[1][2] = 0.0;
00065     B[2][0] = 0.0;
00066     B[2][1] = 0.0;
00067     B[2][2] = 1.0;
00068 
00069     //Kalman Filter Time Update Equations
00070     //Update position based on odometry
00071     pose.x += u[0] * B[0][0] + u[1] * B[1][0] + u[2] * B[2][0];
00072     pose.y += u[0] * B[0][1] + u[1] * B[1][1] + u[2] * B[2][1];
00073     pose.theta += u[0] * B[0][2] + u[1] * B[1][2] + u[2] * B[2][2];
00074 
00075     //Correct angle
00076     pose.theta = convertAngle(pose.theta);
00077 
00078     //Update error covariance
00079     P[0] += Q[0];
00080     P[1] += Q[1];
00081     P[2] += Q[2];
00082 
00083     baseLocalizationPublisher.publish(pose);
00084 
00085     lastReceivedOdometry = odometry;
00086   }
00087 }
00088 
00089 void localizer::positionFromCameraCallback(const youbot_overhead_vision::PositionFromCamera& newPos)
00090 {
00091   float y[3]; //measurement vector
00092   float J[3]; //Kalman gain
00093   float heading = (float)(newPos.heading);
00094   int posx = newPos.midpointX;
00095   int posy = newPos.midpointY;
00096 
00097   youbot_overhead_vision::CoordConversion srv;
00098   srv.request.x = posx;
00099   srv.request.y = posy;
00100   srv.request.type = 1; //convert from pixels to meters
00101   coordConversionClient.call(srv);
00102 
00103   y[0] = srv.response.xConverted - pose.x;
00104   y[1] = srv.response.yConverted - pose.y;
00105   y[2] = convertAngle(heading - pose.theta);
00106 
00107   //Kalman Filter Measurement Update Equations
00108   //Calculate Kalman Gain
00109   J[0] = P[0] * (1.0 / (P[0] + R[0]));
00110   J[1] = P[1] * (1.0 / (P[1] + R[1]));
00111   J[2] = P[2] * (1.0 / (P[2] + R[2]));
00112 
00113   //Calculate new position using Kalman Gain
00114   pose.x = pose.x + J[0] * y[0];
00115   pose.y = pose.y + J[1] * y[1];
00116   pose.theta = convertAngle(pose.theta + J[2] * y[2]);
00117 
00118   //Calculate updated error covariance matrix
00119   P[0] = (1.0 - J[0]) * P[0];
00120   P[1] = (1.0 - J[1]) * P[1];
00121   P[2] = (1.0 - J[2]) * P[2];
00122 
00123   baseLocalizationPublisher.publish(pose);
00124 }
00125 
00126 float localizer::convertAngle(float theta)
00127 {
00128   while (theta > PI)
00129   {
00130     theta -= 2 * PI;
00131   }
00132   while (theta < -PI)
00133   {
00134     theta += 2 * PI;
00135   }
00136 
00137   return theta;
00138 }
00139 
00143 int main(int argc, char **argv)
00144 {
00145   ros::init(argc, argv, "base_localizer");
00146 
00147   localizer baseLocalizer;
00148 
00149   ros::spin();
00150 
00151   return 0;
00152 }
00153 


youbot_overhead_localization
Author(s): David Kent
autogenerated on Thu Jan 2 2014 12:14:20