heading_listener.cpp
Go to the documentation of this file.
1 
8  #include <ros/ros.h>
9  #include <std_msgs/String.h>
10  #include <std_msgs/UInt32.h>
11  #include <std_msgs/Float32.h>
12  #include <std_msgs/Float64.h>
13  #include <tf/transform_datatypes.h>
14  #include <sensor_msgs/Imu.h>
15  #include <piksi_rtk_msgs/BaselineHeading.h>
16 
17  # define M_PI 3.14159265358979323846 /* pi */
18  # define sensor_yaw_deviation 0.002882263
19 
21  {
22  public:
23  HeadingListenerNode(const ros::NodeHandle &node_handle, const ros::NodeHandle &private_node_handle)
24  : _nh(node_handle), _pnh(private_node_handle)
25  {
26  this->init();
27  }
28  ~HeadingListenerNode() = default;
29 
30  void init();
31  void cb_heading_ned2enu(const piksi_rtk_msgs::BaselineHeading::ConstPtr& msg);
32  void cb_imu_vru2enu(const sensor_msgs::Imu::ConstPtr& msg);
33 
34  // Initialize variables
35  // imu message
36  sensor_msgs::Imu _imu;
37  // reset values for imu
38  bool _heading_new = false;
39  double _heading0 = 0.0;
40  double _imu0 = 0.0;
41  // Offset angle between the heading frame and the imu frame
42  double _yaw_hi = 180.0;
43  std::string _mounting_type = "rover";
44 
45  // public ros node handle
47  // private ros node handle
49  // Subscribers and publishers
54 
56 
57  };
58 
60  {
61  // Sleeping 10 sec. to wait for good heading values
62  ros::Duration(10).sleep();
63 
64  _sub_heading_ned = _nh.subscribe("/piksi_attitude/baseline_heading", 1000, &HeadingListenerNode::cb_heading_ned2enu, this);
65  _pub_heading_enu = _nh.advertise<sensor_msgs::Imu>("/heading", 1);
66  _pub_heading_enu_deg = _nh.advertise<std_msgs::Float32>("/heading_deg", 1);
67 
68 
69  _sub_imu_vru = _nh.subscribe("/mti/sensor/imu", 1000, &HeadingListenerNode::cb_imu_vru2enu, this);
70  _pub_imu_enu = _nh.advertise<sensor_msgs::Imu>("/imu", 1);
71 
72  _imu.orientation_covariance[0] = (1 * M_PI/180.0)*(1 * M_PI/180.0);
73  _imu.orientation_covariance[4] = _imu.orientation_covariance[0];
74  _imu.orientation_covariance[8] = (9 * M_PI/180.0)*(9 * M_PI/180.0);
75  _imu.angular_velocity_covariance[0] = (0.25 * M_PI/180.0)*(0.25 * M_PI/180.0);
76  _imu.angular_velocity_covariance[4] = _imu.angular_velocity_covariance[0];
77  _imu.angular_velocity_covariance[8] = _imu.angular_velocity_covariance[0];
78  _imu.linear_acceleration_covariance[0] = 0.0004;
79  _imu.linear_acceleration_covariance[4] = _imu.linear_acceleration_covariance[0];
80  _imu.linear_acceleration_covariance[8] = _imu.linear_acceleration_covariance[0];
81 
82  _nh.getParam("mount_type", _mounting_type);
83 
84  }
85 
86  void HeadingListenerNode::cb_heading_ned2enu(const piksi_rtk_msgs::BaselineHeading::ConstPtr& msg)
87  {
88  // Variables
89  std_msgs::UInt32 heading;
90  std_msgs::Float32 heading_deg, heading_radians;
91  sensor_msgs::Imu heading_rtk;
92 
93  // Get heading data (standard heading [mdeg])
94  heading.data = msg->heading;
95 
96  // Transform to ENU
97  heading_deg.data = (float)heading.data/1000;
98  heading_deg.data = 360 - heading_deg.data; // Orientation increasing Counter clockwise
99  heading_deg.data = heading_deg.data + 90; // 0° pointing East
100 
101  //Correct heading for rover configuration
102  if(_mounting_type == "rover"){
103  heading_deg.data = heading_deg.data - 180; // 0° pointing East
104  }
105 
106  if (heading_deg.data > 360.0)
107  heading_deg.data = heading_deg.data - 360.0;
108  heading_radians.data = heading_deg.data * M_PI/180.0;
109 
110  // Save heading in degrees
111  _heading_new = true;
112  _heading0 = heading_deg.data;
113 
114  // Debug heading readings
115  ROS_DEBUG("Heading : [%d] deg ENU: [%f] rad ENU: [%f]", heading.data, heading_deg.data, heading_radians.data);
116  //Publish heading in degrees
117  _pub_heading_enu_deg.publish(heading_deg);
118 
119  // Create imu msg from heading RTK
120  heading_rtk.header.stamp = msg->header.stamp;
121  heading_rtk.header.frame_id = "gps_receiver";
122  heading_rtk.orientation = tf::createQuaternionMsgFromYaw(heading_radians.data); // Create this quaternion from yaw (in radians)
123  // Calculated standard deviation for the sensor
124  double standard_deviation = sensor_yaw_deviation * M_PI/180.0;
125  heading_rtk.orientation_covariance[8] = standard_deviation*standard_deviation; //Update sensor covariance about z axe
126  heading_rtk.linear_acceleration.x = 0;
127  heading_rtk.linear_acceleration.y = 0;
128  heading_rtk.linear_acceleration.z = 0;
129  heading_rtk.linear_acceleration_covariance[0] = -1;
130  heading_rtk.angular_velocity.x = 0;
131  heading_rtk.angular_velocity.y = 0;
132  heading_rtk.angular_velocity.z = 0;
133  heading_rtk.angular_velocity_covariance[0] = -1;
134 
135  // Update last message stamp
136  _pub_heading_enu.publish(heading_rtk);
137  }
138 
139  void HeadingListenerNode::cb_imu_vru2enu(const sensor_msgs::Imu::ConstPtr& msg)
140  {
141  // Get message
142  _imu.header = msg->header;
143  _imu.angular_velocity = msg->angular_velocity;
144  _imu.linear_acceleration = msg->linear_acceleration;
145 
146  // Get imu yaw in degrees [0,360)
148  double roll, pitch, yaw;
149  tf::quaternionMsgToTF(msg->orientation, quat);
150  tf::Matrix3x3(quat).getRPY(roll, pitch, yaw);
151  yaw = yaw < 0 ? (yaw * 180.0 / M_PI)+360 : (yaw * 180.0 / M_PI);
152 
153  // Set reference if needed
154  if (_heading_new)
155  {
156  _imu0 = yaw;
157  _heading_new = false;
158  }
159 
160  // Compute corrected orientation
161  double yaw_delta = (yaw - _imu0);
162  if (yaw_delta > 180) { yaw_delta = yaw - 360 - _imu0; } // Shortest path difference
163  if (yaw_delta < -180) { yaw_delta = yaw + 360 - _imu0; }
164  yaw = _heading0 + _yaw_hi + yaw_delta;
165  while (yaw > 360) { yaw -= 360; } // yaw between [0, 360)
166  while (yaw < 0) { yaw += 360; }
167  yaw *= M_PI/180.0;
168  _imu.orientation = tf::createQuaternionMsgFromRollPitchYaw(roll, pitch, yaw);
169 
170  // Publish corrected imu message
172  }
173 
174  int main(int argc, char **argv)
175  {
176  ros::init(argc, argv, "heading_listener");
177  ros::NodeHandle nh;
178  ros::NodeHandle nh_private("~");
179  HeadingListenerNode node(nh, nh_private);
180  ros::spin();
181 
182  return 0;
183  }
msg
HeadingListenerNode(const ros::NodeHandle &node_handle, const ros::NodeHandle &private_node_handle)
#define sensor_yaw_deviation
#define M_PI
ros::Subscriber _sub_imu_vru
ros::Publisher _pub_heading_enu_deg
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void cb_imu_vru2enu(const sensor_msgs::Imu::ConstPtr &msg)
ROSCPP_DECL void spin(Spinner &spinner)
static void quaternionMsgToTF(const geometry_msgs::Quaternion &msg, Quaternion &bt)
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
~HeadingListenerNode()=default
ros::Publisher _pub_imu_enu
ros::Publisher _pub_heading_enu
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
sensor_msgs::Imu _imu
int main(int argc, char **argv)
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
bool getParam(const std::string &key, std::string &s) const
static geometry_msgs::Quaternion createQuaternionMsgFromRollPitchYaw(double roll, double pitch, double yaw)
ros::NodeHandle _pnh
ros::Subscriber _sub_heading_ned
void cb_heading_ned2enu(const piksi_rtk_msgs::BaselineHeading::ConstPtr &msg)
#define ROS_DEBUG(...)


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