from_fix.cpp
Go to the documentation of this file.
00001 
00046 #include "ros/ros.h"
00047 #include "sensor_msgs/NavSatFix.h"
00048 #include "nav_msgs/Odometry.h"
00049 
00050 #include <boost/bind.hpp>
00051 
00052 extern "C" {
00053   // The backend of this node is an included C library called libswiftnav.
00054   #include "coord_system.h"
00055 }
00056 
00057 #define TO_RADIANS (M_PI/180)
00058 #define TO_DEGREES (180/M_PI)
00059 
00060 void initialize_datum(double datum_ecef[3],
00061                       const sensor_msgs::NavSatFixConstPtr fix_ptr,
00062                       const ros::Publisher& pub_datum)
00063 {
00064   ros::NodeHandle n("~");
00065   sensor_msgs::NavSatFix datum_msg(*fix_ptr);
00066 
00067   // Local ENU coordinates are with respect to a plane which is 
00068   // perpendicular to a particular lat/lon. This logic decides 
00069   // whether to use a specific passed-in point (typical for 
00070   // repeated tests in a locality) or just an arbitrary starting
00071   // point (more ad-hoc type scenarios).
00072   if (n.hasParam("datum_latitude") &&
00073       n.hasParam("datum_longitude") && 
00074       n.hasParam("datum_altitude")) {
00075     n.getParam("datum_latitude", datum_msg.latitude);  
00076     n.getParam("datum_longitude", datum_msg.longitude);  
00077     n.getParam("datum_altitude", datum_msg.altitude);  
00078     ROS_INFO("Using datum provided by node parameters.");
00079   } else {
00080     ROS_INFO("Using initial position fix as datum.");
00081   }
00082   pub_datum.publish(datum_msg);
00083 
00084   // The datum point is stored as an ECEF, for mathematical reasons.
00085   // We convert it here, using the appropriate function from
00086   // libswiftnav.
00087   double llh[3] = { datum_msg.latitude * TO_RADIANS,
00088                     datum_msg.longitude * TO_RADIANS,
00089                     datum_msg.altitude };
00090   wgsllh2ecef(llh, datum_ecef);
00091 }
00092 
00093 
00094 static void handle_fix(const sensor_msgs::NavSatFixConstPtr fix_ptr,
00095                        const ros::Publisher& pub_enu,
00096                        const ros::Publisher& pub_datum)
00097 {
00098   static double ecef_datum[3];
00099   static bool have_datum = false;
00100 
00101   if (!have_datum) {
00102     initialize_datum(ecef_datum, fix_ptr, pub_datum);
00103     have_datum = true;
00104   }
00105 
00106   // Prepare the appropriate input vector to convert the input latlon
00107   // to an ECEF triplet.
00108   double llh[3] = { fix_ptr->latitude * TO_RADIANS,
00109                     fix_ptr->longitude * TO_RADIANS,
00110                     fix_ptr->altitude };
00111   double ecef[3];
00112   wgsllh2ecef(llh, ecef);
00113   
00114   // ECEF triplet is converted to north-east-down (NED), by combining it
00115   // with the ECEF-formatted datum point.
00116   double ned[3];
00117   wgsecef2ned_d(ecef, ecef_datum, ned);
00118 
00119   nav_msgs::Odometry odom_msg;
00120   odom_msg.header.stamp = fix_ptr->header.stamp;
00121   odom_msg.pose.pose.position.x = ned[1];
00122   odom_msg.pose.pose.position.y = ned[0];
00123   odom_msg.pose.pose.position.z = -ned[2];
00124 
00125   // We only need to populate the diagonals of the covariance matrix; the
00126   // rest initialize to zero automatically, which is correct as the
00127   // dimensions of the state are independent.
00128   odom_msg.pose.covariance[0] = fix_ptr->position_covariance[0];
00129   odom_msg.pose.covariance[7] = fix_ptr->position_covariance[4];
00130   odom_msg.pose.covariance[14] = fix_ptr->position_covariance[8];
00131   
00132   // Do not use/trust orientation dimensions from GPS.
00133   odom_msg.pose.covariance[21] = 1e6;
00134   odom_msg.pose.covariance[28] = 1e6;
00135   odom_msg.pose.covariance[35] = 1e6;
00136 
00137   // Orientation of GPS is pointing upward (as far as we know).
00138   odom_msg.pose.pose.orientation.w = 1;
00139 
00140   pub_enu.publish(odom_msg); 
00141 }
00142 
00143 
00144 int main(int argc, char **argv)
00145 {
00146   ros::init(argc, argv, "from_fix");
00147   ros::NodeHandle n;
00148 
00149   // Initialize publishers, and pass them into the handler for 
00150   // the subscriber.
00151   ros::Publisher pub_enu = n.advertise<nav_msgs::Odometry>("enu", 5);
00152   ros::Publisher pub_datum = n.advertise<sensor_msgs::NavSatFix>("enu_datum", 5, true);
00153   ros::Subscriber sub = n.subscribe<sensor_msgs::NavSatFix>("fix", 5, 
00154       boost::bind(handle_fix, _1, pub_enu, pub_datum));
00155 
00156   ros::spin();
00157   return 0;
00158 }
00159 


enu
Author(s): Mike Purvis
autogenerated on Fri Jan 3 2014 11:21:07