set_initial_state_filter.cpp
Go to the documentation of this file.
1 
8  #include <ros/ros.h>
9  #include <std_msgs/Float64.h>
10  #include <geometry_msgs/Vector3.h>
12  #include <tf/transform_datatypes.h>
15  #include <nav_msgs/Odometry.h>
16  #include <sensor_msgs/Imu.h>
17  #include <sensor_msgs/NavSatFix.h>
18  #include <Eigen/Dense>
19  #include <string>
20  #include <iostream>
21  #include <fstream>
24  #include <tf2_ros/buffer.h>
26  #include "ros/package.h"
27 
29  {
30  public:
31  SetInitialStateFilter(const ros::NodeHandle &node_handle, const ros::NodeHandle &private_node_handle)
32  : nh_(node_handle), pnh_(private_node_handle)
33  {
34  this->init();
35  }
36  ~SetInitialStateFilter() = default;
37 
38  void init();
39  void headingCb(const sensor_msgs::ImuConstPtr& imu_msg);
40  void gpsCallback(const sensor_msgs::NavSatFixConstPtr& msg);
41  nav_msgs::Odometry utmToMap(const tf2::Transform& utm_pose, const ros::Time &transform_time) const;
42  void gpsToRobotPose(const tf2::Transform &gps_odom_pose, tf2::Transform &robot_odom_pose, const ros::Time &transform_time);
43 
44  // Initialize Variables
45  int gps_count_{0};
46  int N_gps_{1};
48  int N_heading_{1};
49  bool zero_altitude_{false};
50  bool rtk_fix_ {false};
51  std::string base_link_frame_id_{"scouting_wrt_ground_link"};
52  std::string world_frame_id_{"odom"};
53  std::string gps_frame_id_{""};
54  std::string path_;
55  Eigen::MatrixXd utm_covariance_;
62  sensor_msgs::NavSatFix gps_msg_avg_;
63  sensor_msgs::Imu imu_msg_avg_;
64 
65  // public and private ros node handle
68 
69  // Subscribers and publishers
72  };
73 
75  {
76  ROS_INFO("Numb GPS: %d", N_gps_);
77  ROS_INFO("Numb heading: %d", N_heading_);
78  ROS_INFO("Loading params...");
79  // Load params
80  nh_.getParam("/navsat_transform/zero_altitude", zero_altitude_);
81  nh_.getParam("/localization_init/N_gps", N_gps_);
82  nh_.getParam("/localization_init/N_heading", N_heading_);
83 
84  sub_heading_ = nh_.subscribe("/heading", 1000, &SetInitialStateFilter::headingCb, this);
85  sub_gps_ = nh_.subscribe("/piksi_receiver/navsatfix_best_fix",1000, &SetInitialStateFilter::gpsCallback, this);
86  ROS_INFO("Numb GPS: %d", N_gps_);
87  ROS_INFO("Numb heading: %d", N_heading_);
88  path_ = ros::package::getPath("earth_rover_localization")+"/cfg/initial_state.yaml";
89  ROS_INFO("Path: %s", path_.c_str());
90  }
91 
92  void SetInitialStateFilter::headingCb(const sensor_msgs::ImuConstPtr& imu_msg)
93  {
94  // Only average heading when we have rtk fix gps (heading comes from fps)
95  if (rtk_fix_){
96  heading_count_ ++;
97  if (heading_count_==1){
98  imu_msg_avg_ = *imu_msg;
99  }
100  else{
101  imu_msg_avg_.orientation.x += imu_msg->orientation.x;
102  imu_msg_avg_.orientation.y += imu_msg->orientation.y;
103  imu_msg_avg_.orientation.z += imu_msg->orientation.z;
104  imu_msg_avg_.orientation.w += imu_msg->orientation.w;
105  imu_msg_avg_.header.stamp = imu_msg->header.stamp;
106  }
107  }
108  }
109 
110  void SetInitialStateFilter::gpsCallback(const sensor_msgs::NavSatFixConstPtr& gps_msg)
111  {
112  // Wait until we have RTK fix
113  if (gps_msg->status.status==2 && gps_msg->position_covariance[0]<=0.0049){
114  rtk_fix_ = true;
115  gps_count_ ++;
116  if (gps_count_==1){
117  gps_msg_avg_ = *gps_msg;
118  gps_frame_id_ = gps_msg->header.frame_id;
119  }
120  else{
121  gps_msg_avg_.latitude += gps_msg->latitude;
122  gps_msg_avg_.longitude += gps_msg->longitude;
123  gps_msg_avg_.altitude += gps_msg->altitude;
124  gps_msg_avg_.header.stamp = gps_msg->header.stamp;
125  }
126  }
127  else{
128  rtk_fix_ = false;
129  ROS_WARN("Waiting for RTK fix to initialize localization...");
130  }
131 
133  {
134  // Calculate GPS and IMU average values
135  gps_msg_avg_.latitude /= gps_count_;
136  gps_msg_avg_.longitude /= gps_count_;
137  gps_msg_avg_.altitude /= gps_count_;
138  imu_msg_avg_.orientation.x /= heading_count_;
139  imu_msg_avg_.orientation.y /= heading_count_;
140  imu_msg_avg_.orientation.z /= heading_count_;
141  imu_msg_avg_.orientation.w /= heading_count_;
142 
143  // Transform GPS LL data into UTM coordintes
144  double utm_x = 0.0;
145  double utm_y = 0.0;
146  double utm_z = 0.0;
147  std::string utm_zone_tmp;
148  RobotLocalization::NavsatConversions::LLtoUTM(gps_msg_avg_.latitude, gps_msg_avg_.longitude, utm_y, utm_x, utm_zone_tmp);
149  utm_pose_.setOrigin(tf2::Vector3(utm_x, utm_y, gps_msg_avg_.altitude));
150  utm_covariance_.setZero();
151 
152  // Transform UTM pose into map frame
153  nav_msgs::Odometry gps_odom;
154  gps_odom = utmToMap(utm_pose_, gps_msg_avg_.header.stamp);
155  tf2::Transform transformed_utm_gps;
156  tf2::fromMsg(gps_odom.pose.pose, transformed_utm_gps);
157 
158  // Want the pose of the vehicle origin, not the GPS
159  tf2::Transform transformed_utm_robot;
160  tf2::fromMsg(imu_msg_avg_.orientation, robot_orientation_); // get robot orientation tf from heading avg
161  gpsToRobotPose(transformed_utm_gps, transformed_utm_robot, gps_odom.header.stamp);
162 
163  // Write to yaml file initial state param
164  std::ofstream myfile;
165  nav_msgs::Odometry init_state{};
166  // Get quat orientation to tf in order to get RPY
168  tf2::toMsg(transformed_utm_robot, init_state.pose.pose);
169  double roll, pitch, yaw;
170  tf::Matrix3x3(robot_quat_).getRPY(roll, pitch, yaw);
171  myfile.open(path_);
172  myfile << "initial_state: [" << init_state.pose.pose.position.x << ", ";
173  myfile << init_state.pose.pose.position.y << ", ";
174  myfile << init_state.pose.pose.position.z << ",\n";
175  myfile << 0.0 << ", ";
176  myfile << 0.0 << ", ";
177  myfile << yaw << ", \n";
178  myfile << 0.0 << ", " << 0.0 << ", " << 0.0 << ", \n";
179  myfile << 0.0 << ", " << 0.0 << ", " << 0.0 << ", \n";
180  myfile << 0.0 << ", " << 0.0 << ", " << 0.0 << "]";
181 
182  myfile.close();
183  ROS_INFO("Loaded initial_state param into yaml file");
184  ros::shutdown();
185  }
186 
187  }
188 
189  nav_msgs::Odometry SetInitialStateFilter::utmToMap(const tf2::Transform& utm_pose, const ros::Time &transform_time) const
190  {
191  nav_msgs::Odometry gps_odom{};
192  tf2::Transform transformed_utm_gps{};
193 
194  tf2::Transform utm_world_transform_;
197  "utm",
198  transform_time,
199  ros::Duration(5),
200  utm_world_transform_);
201 
202  if (can_transform)
203  {
204  transformed_utm_gps.mult(utm_world_transform_, utm_pose);
205  transformed_utm_gps.setRotation(tf2::Quaternion::getIdentity());
206  }
207 
208  // Set header information stamp because we would like to know the robot's position at that timestamp
209  gps_odom.header.frame_id = world_frame_id_;
210 
211  // Now fill out the message. Set the orientation to the identity.
212  tf2::toMsg(transformed_utm_gps, gps_odom.pose.pose);
213  gps_odom.pose.pose.position.z = (zero_altitude_ ? 0.0 : gps_odom.pose.pose.position.z);
214 
215  return gps_odom;
216  }
217 
219  tf2::Transform &robot_odom_pose,
220  const ros::Time &transform_time)
221  {
222  tf2::Transform gps_offset_rotated;
226  transform_time,
228  gps_offset_rotated);
229 
230  if (can_transform)
231  {
232  gps_offset_rotated.setOrigin(tf2::quatRotate(robot_orientation_, gps_offset_rotated.getOrigin()));
233  gps_offset_rotated.setRotation(tf2::Quaternion::getIdentity());
234  robot_odom_pose = gps_offset_rotated.inverse() * gps_odom_pose;
235  }
236  }
237 
238  int main(int argc, char **argv)
239  {
240  ros::init(argc, argv, "set_initial_state_filter");
241  ros::NodeHandle nh;
242  ros::NodeHandle nh_private("~");
243  SetInitialStateFilter node(nh, nh_private);
244  ros::spin();
245 
246  return 0;
247  }
msg
static const Quaternion & getIdentity()
void headingCb(const sensor_msgs::ImuConstPtr &imu_msg)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
TF2SIMD_FORCE_INLINE void setRotation(const Quaternion &q)
sensor_msgs::NavSatFix gps_msg_avg_
tf2_ros::TransformListener tf_listener_
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
SetInitialStateFilter(const ros::NodeHandle &node_handle, const ros::NodeHandle &private_node_handle)
#define ROS_WARN(...)
ROSCPP_DECL void spin(Spinner &spinner)
void gpsToRobotPose(const tf2::Transform &gps_odom_pose, tf2::Transform &robot_odom_pose, const ros::Time &transform_time)
TF2SIMD_FORCE_INLINE Vector3 & getOrigin()
static void quaternionMsgToTF(const geometry_msgs::Quaternion &msg, Quaternion &bt)
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
#define ROS_INFO(...)
void fromMsg(const A &, B &b)
Transform inverse() const
static void LLtoUTM(const double Lat, const double Long, double &UTMNorthing, double &UTMEasting, std::string &UTMZone, double &gamma)
TF2SIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
ROSLIB_DECL std::string getPath(const std::string &package_name)
B toMsg(const A &a)
TF2SIMD_FORCE_INLINE Vector3 quatRotate(const Quaternion &rotation, const Vector3 &v)
bool getParam(const std::string &key, std::string &s) const
int main(int argc, char **argv)
void gpsCallback(const sensor_msgs::NavSatFixConstPtr &msg)
ROSCPP_DECL void shutdown()
bool lookupTransformSafe(const tf2_ros::Buffer &buffer, const std::string &targetFrame, const std::string &sourceFrame, const ros::Time &time, const ros::Duration &timeout, tf2::Transform &targetFrameTrans, const bool silent=false)
~SetInitialStateFilter()=default
nav_msgs::Odometry utmToMap(const tf2::Transform &utm_pose, const ros::Time &transform_time) const


earth_rover_localization
Author(s):
autogenerated on Wed Apr 28 2021 02:15:34