from_fix.cpp
Go to the documentation of this file.
00001 
00037 #include <boost/bind.hpp>
00038 #include <string>
00039 
00040 #include "ros/ros.h"
00041 #include "sensor_msgs/NavSatFix.h"
00042 #include "nav_msgs/Odometry.h"
00043 #include "enu/ToENU.h"
00044 #include "enu/enu.h"  // ROS wrapper for conversion functions
00045 
00046 
00047 void initialize_datum(const sensor_msgs::NavSatFix& fix,
00048                       const ros::Publisher& pub_datum,
00049                       sensor_msgs::NavSatFix* datum_ptr) {
00050   ros::NodeHandle pnh("~");
00051 
00052   // Local ENU coordinates are with respect to a plane which is
00053   // perpendicular to a particular lat/lon. This logic decides
00054   // whether to use a specific passed-in point (typical for
00055   // repeated tests in a locality) or just an arbitrary starting
00056   // point (more ad-hoc type scenarios).
00057   if (pnh.hasParam("datum_latitude") &&
00058       pnh.hasParam("datum_longitude") &&
00059       pnh.hasParam("datum_altitude")) {
00060     pnh.getParam("datum_latitude", datum_ptr->latitude);
00061     pnh.getParam("datum_longitude", datum_ptr->longitude);
00062     pnh.getParam("datum_altitude", datum_ptr->altitude);
00063     ROS_INFO("Using datum provided by node parameters.");
00064   } else {
00065     datum_ptr->latitude = fix.latitude;
00066     datum_ptr->longitude = fix.longitude;
00067     datum_ptr->altitude = fix.altitude;
00068     ROS_INFO("Using initial position fix as datum.");
00069   }
00070   pub_datum.publish(*datum_ptr);
00071 }
00072 
00073 
00074 static void handle_fix(const sensor_msgs::NavSatFixConstPtr fix_ptr,
00075                        const ros::Publisher& pub_odom,
00076                        const ros::Publisher& pub_datum,
00077                        const std::string& output_tf_frame,
00078                        const double invalid_covariance_value,
00079                        const double scale_covariance,
00080                        const double lock_altitude) {
00081   static sensor_msgs::NavSatFix datum;
00082   static bool have_datum = false;
00083 
00084   if (!have_datum) {
00085     initialize_datum(*fix_ptr, pub_datum, &datum);
00086     have_datum = true;
00087   }
00088 
00089   // Convert the input latlon into north-east-down (NED) via an ECEF
00090   // transformation and an ECEF-formatted datum point
00091   nav_msgs::Odometry odom;
00092   enu::fix_to_point(*fix_ptr, datum, &odom.pose.pose.position);
00093   if (lock_altitude!=-1) 
00094     odom.pose.pose.position.z = lock_altitude;
00095 
00096   odom.header.stamp = fix_ptr->header.stamp;
00097   odom.header.frame_id = output_tf_frame;  // Name of output tf frame
00098   odom.child_frame_id = fix_ptr->header.frame_id;  // Antenna location
00099 
00100   //Initialize orientation to zero (GPS orientation is N/A)
00101   odom.pose.pose.orientation.x = 0;
00102   odom.pose.pose.orientation.y = 0;
00103   odom.pose.pose.orientation.z = 0;
00104   odom.pose.pose.orientation.w = 1;
00105 
00106   // We only need to populate the diagonals of the covariance matrix; the
00107   // rest initialize to zero automatically, which is correct as the
00108   // dimensions of the state are independent.
00109   odom.pose.covariance[0] = fix_ptr->position_covariance[0]*scale_covariance;
00110   odom.pose.covariance[7] = fix_ptr->position_covariance[4]*scale_covariance;
00111   odom.pose.covariance[14] = fix_ptr->position_covariance[8]*scale_covariance;
00112 
00113   // Do not use orientation dimensions from GPS.
00114   // (-1 is an invalid covariance and standard ROS practice to set as invalid.)
00115   odom.pose.covariance[21] = invalid_covariance_value;
00116   odom.pose.covariance[28] = invalid_covariance_value;
00117   odom.pose.covariance[35] = invalid_covariance_value;
00118 
00119   pub_odom.publish(odom);
00120 }
00121 
00122 bool toENUService(const enu::ToENU::Request& req, enu::ToENU::Response& resp) {
00123   enu::fix_to_point(req.llh, req.datum, &(resp.enu));
00124   return true;
00125 }
00126 
00127 int main(int argc, char **argv) {
00128   ros::init(argc, argv, "from_fix");
00129   ros::NodeHandle n;
00130   ros::NodeHandle pnh("~");
00131 
00132   std::string output_tf_frame;
00133   pnh.param<std::string>("output_frame_id", output_tf_frame, "map");
00134   double invalid_covariance_value;
00135   double scale_covariance;
00136   double lock_altitude;
00137   pnh.param<double>("invalid_covariance_value", invalid_covariance_value, -1.0);  // -1 is ROS convention.  1e6 is robot_pose_ekf convention
00138   pnh.param<double>("scale_covariance", scale_covariance,1.0);
00139   pnh.param<double>("lock_altitude", lock_altitude, -1.0); //if -1 then use ENU altitude, otherwise lock the altitude at the provided value
00140 
00141   // Initialize publishers, and pass them into the handler for
00142   // the subscriber.
00143   ros::Publisher pub_odom = n.advertise<nav_msgs::Odometry>("enu", 5);
00144   ros::Publisher pub_datum = n.advertise<sensor_msgs::NavSatFix>("enu_datum", 5, true);
00145   ros::Subscriber sub = n.subscribe<sensor_msgs::NavSatFix>("fix", 5,
00146       boost::bind(handle_fix, _1, pub_odom, pub_datum, output_tf_frame, invalid_covariance_value,scale_covariance, lock_altitude));
00147   ros::ServiceServer srv = n.advertiseService<enu::ToENU::Request, enu::ToENU::Response> ("ToENU", toENUService);
00148 
00149   ros::spin();
00150   return 0;
00151 }
00152 


enu
Author(s): Mike Purvis , Ryan Gariepy
autogenerated on Fri Aug 28 2015 10:37:27