ins_handler.cpp
Go to the documentation of this file.
1 //
3 // Copyright (c) 2020 NovAtel Inc.
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 //
24 
26 
27 #include <ros/ros.h>
28 
29 
31 
32 
34 
35 #include "sensor_msgs/Imu.h"
36 #include "novatel_oem7_msgs/CORRIMU.h"
37 #include "novatel_oem7_msgs/IMURATECORRIMU.h"
38 #include "novatel_oem7_msgs/INSSTDEV.h"
39 #include "novatel_oem7_msgs/INSCONFIG.h"
40 #include "novatel_oem7_msgs/INSPVA.h"
41 #include "novatel_oem7_msgs/INSPVAX.h"
42 
43 #include <boost/scoped_ptr.hpp>
44 #include <oem7_ros_publisher.hpp>
45 
46 #include <math.h>
47 #include <map>
48 
49 namespace
50 {
51  typedef unsigned int imu_type_t;
52  typedef int imu_rate_t;
53 
54  const imu_type_t IMU_TYPE_UNKNOWN = 0;
55 }
56 
57 
58 
59 namespace novatel_oem7_driver
60 {
61  /***
62  * Converts degrees to Radians
63  *
64  * @return radians
65  */
66  inline double degreesToRadians(double degrees)
67  {
68  return degrees * M_PI / 180.0;
69  }
70 
71  const double DATA_NOT_AVAILABLE = -1.0;
72 
74  {
76 
82 
86 
87  int imu_rate_;
88  std::string frame_id_;
89 
90  typedef std::map<std::string, std::string> imu_config_map_t;
91  imu_config_map_t imu_config_map;
92 
93 
94  void getImuParam(imu_type_t imu_type, const std::string& name, std::string& param)
95  {
96  std::string ns = ros::this_node::getNamespace();
97  std::string param_name = ns + "/supported_imus/" + std::to_string(imu_type) + "/" + name;
98  if(!nh_.getParam(param_name, param))
99  {
100  ROS_FATAL_STREAM("INS: IMU type= " << imu_type << " is not supported.");
101  }
102  }
103 
104  int getImuRate(imu_type_t imu_type)
105  {
106  std::string rate;
107  getImuParam(imu_type, "rate", rate);
108 
109  return std::stoi(rate);
110  }
111 
112  void getImuDescription(imu_type_t imu_type, std::string& desc)
113  {
114  getImuParam(imu_type, "name", desc);
115  }
116 
117 
118  void processInsConfigMsg(Oem7RawMessageIf::ConstPtr msg)
119  {
121  MakeROSMessage(msg, insconfig);
122  insconfig_pub_.publish(insconfig);
123 
124  if(imu_rate_ == 0)
125  {
126  std::string imu_desc;
127  getImuDescription(insconfig->imu_type, imu_desc);
128 
129  imu_rate_ = getImuRate(insconfig->imu_type);
130 
131  ROS_LOG_STREAM(imu_rate_ == 0 ? ::ros::console::levels::Error :
134  "IMU: '" << imu_desc << "', rate= " << imu_rate_);
135  }
136  }
137 
138  void publishInsPVAXMsg(Oem7RawMessageIf::ConstPtr msg)
139  {
141  MakeROSMessage(msg, inspvax);
142 
143  inspvax_pub_.publish(inspvax);
144  }
145 
146  void publishCorrImuMsg(Oem7RawMessageIf::ConstPtr msg)
147  {
148  MakeROSMessage(msg, corrimu_);
149  corrimu_pub_.publish(corrimu_);
150  }
151 
152 
154  {
155  if(!imu_pub_.isEnabled())
156  {
157  return;
158  }
159 
160  boost::shared_ptr<sensor_msgs::Imu> imu(new sensor_msgs::Imu);
161 
162  if(inspva_)
163  {
164  tf2::Quaternion tf_orientation;
165  tf_orientation.setRPY(
166  degreesToRadians(inspva_->roll),
167  -degreesToRadians(inspva_->pitch),
168  -degreesToRadians(inspva_->azimuth));
169  imu->orientation = tf2::toMsg(tf_orientation);
170  }
171  else
172  {
173  ROS_WARN_THROTTLE(10, "INSPVA not available; 'Imu' message not generated.");
174  return;
175  }
176 
177  if(insstdev_)
178  {
179  imu->orientation_covariance[0] = std::pow(insstdev_->pitch_stdev, 2);
180  imu->orientation_covariance[4] = std::pow(insstdev_->roll_stdev, 2);
181  imu->orientation_covariance[8] = std::pow(insstdev_->azimuth_stdev, 2);
182  }
183 
184  if(corrimu_ && imu_rate_ > 0)
185  {
186  imu->angular_velocity.x = corrimu_->pitch_rate * imu_rate_;
187  imu->angular_velocity.y = corrimu_->roll_rate * imu_rate_;
188  imu->angular_velocity.z = corrimu_->yaw_rate * imu_rate_;
189 
190  imu->linear_acceleration.x = corrimu_->lateral_acc * imu_rate_;
191  imu->linear_acceleration.y = corrimu_->longitudinal_acc * imu_rate_;
192  imu->linear_acceleration.z = corrimu_->vertical_acc * imu_rate_;
193 
194 
195  imu->angular_velocity_covariance[0] = 1e-3;
196  imu->angular_velocity_covariance[4] = 1e-3;
197  imu->angular_velocity_covariance[8] = 1e-3;
198 
199 
200  imu->linear_acceleration_covariance[0] = 1e-3;
201  imu->linear_acceleration_covariance[4] = 1e-3;
202  imu->linear_acceleration_covariance[8] = 1e-3;
203  }
204  else
205  {
206  imu->angular_velocity_covariance[0] = DATA_NOT_AVAILABLE;
207  imu->linear_acceleration_covariance[0] = DATA_NOT_AVAILABLE;
208  }
209 
210  imu_pub_.publish(imu);
211  }
212 
213  void publishInsStDevMsg(Oem7RawMessageIf::ConstPtr msg)
214  {
215  MakeROSMessage(msg, insstdev_);
216  insstdev_pub_.publish(insstdev_);
217  }
218 
219 
220  public:
222  imu_rate_(0)
223  {
224  }
225 
227  {
228  }
229 
231  {
232  nh_ = nh;
233 
234  imu_pub_.setup<sensor_msgs::Imu>( "IMU", nh);
235  corrimu_pub_.setup< novatel_oem7_msgs::CORRIMU>( "CORRIMU", nh);
236  insstdev_pub_.setup< novatel_oem7_msgs::INSSTDEV>( "INSSTDEV", nh);
237  inspvax_pub_.setup< novatel_oem7_msgs::INSPVAX>( "INSPVAX", nh);
238  insconfig_pub_.setup<novatel_oem7_msgs::INSCONFIG>("INSCONFIG", nh);
239 
240  nh.getParam("imu_rate", imu_rate_); // User rate override
241  if(imu_rate_ > 0)
242  {
243  ROS_INFO_STREAM("INS: IMU rate overriden to " << imu_rate_);
244  }
245  }
246 
247  const std::vector<int>& getMessageIds()
248  {
249  static const std::vector<int> MSG_IDS(
250  {
257  }
258  );
259  return MSG_IDS;
260  }
261 
262  void handleMsg(Oem7RawMessageIf::ConstPtr msg)
263  {
264  ROS_DEBUG_STREAM("INS < [id= " << msg->getMessageId() << "]");
265 
266  if(msg->getMessageId()== INSPVAS_OEM7_MSGID)
267  {
268  MakeROSMessage(msg, inspva_); // Cache
269  }
270  else if(msg->getMessageId() == INSSTDEV_OEM7_MSGID)
271  {
272  publishInsStDevMsg(msg);
273  }
274  else if(msg->getMessageId() == CORRIMUS_OEM7_MSGID ||
275  msg->getMessageId() == IMURATECORRIMUS_OEM7_MSGID)
276  {
277  publishCorrImuMsg(msg);
278 
279  publishImuMsg();
280  }
281  else if(msg->getMessageId() == INSCONFIG_OEM7_MSGID)
282  {
283  processInsConfigMsg(msg);
284  }
285  else if(msg->getMessageId() == INSPVAX_OEM7_MSGID)
286  {
287  publishInsPVAXMsg(msg);
288  }
289  else
290  {
291  assert(false);
292  }
293  }
294  };
295 
296 }
297 
boost::shared_ptr< novatel_oem7_msgs::INSSTDEV > insstdev_
Definition: ins_handler.cpp:85
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
void handleMsg(Oem7RawMessageIf::ConstPtr msg)
void publishCorrImuMsg(Oem7RawMessageIf::ConstPtr msg)
double degreesToRadians(double degrees)
void publishInsPVAXMsg(Oem7RawMessageIf::ConstPtr msg)
#define ROS_LOG_STREAM(level, name, args)
#define ROS_WARN_THROTTLE(rate,...)
boost::shared_ptr< novatel_oem7_msgs::CORRIMU > corrimu_
Definition: ins_handler.cpp:84
const int INSCONFIG_OEM7_MSGID
const int INSPVAX_OEM7_MSGID
std::map< std::string, std::string > imu_config_map_t
Definition: ins_handler.cpp:90
boost::shared_ptr< novatel_oem7_msgs::INSPVA > inspva_
Definition: ins_handler.cpp:83
ROSCPP_DECL const std::string & getNamespace()
#define ROS_FATAL_STREAM(args)
const int INSPVAS_OEM7_MSGID
void getImuParam(imu_type_t imu_type, const std::string &name, std::string &param)
Definition: ins_handler.cpp:94
const std::vector< int > & getMessageIds()
int getImuRate(imu_type_t imu_type)
void publish(boost::shared_ptr< M > &msg)
#define ROS_DEBUG_STREAM(args)
B toMsg(const A &a)
PLUGINLIB_EXPORT_CLASS(novatel_oem7_driver::Oem7ConfigNodelet, nodelet::Nodelet)
void processInsConfigMsg(Oem7RawMessageIf::ConstPtr msg)
void initialize(ros::NodeHandle &nh)
const int IMURATECORRIMUS_OEM7_MSGID
void setup(const std::string &name, ros::NodeHandle &nh)
#define ROS_INFO_STREAM(args)
void MakeROSMessage(const Oem7RawMessageIf::ConstPtr &msg, boost::shared_ptr< T > &rosmsg)
const double DATA_NOT_AVAILABLE
Used to initialized unpopulated fields.
Definition: ins_handler.cpp:71
bool getParam(const std::string &key, std::string &s) const
void publishInsStDevMsg(Oem7RawMessageIf::ConstPtr msg)
const int INSSTDEV_OEM7_MSGID
void getImuDescription(imu_type_t imu_type, std::string &desc)
const int CORRIMUS_OEM7_MSGID
#define ROSCONSOLE_DEFAULT_NAME


novatel_oem7_driver
Author(s):
autogenerated on Tue Mar 9 2021 03:48:00