firmware_message_converter.cpp
Go to the documentation of this file.
1 #include <cmath>
2 #include <cstdlib>
3 #include <fstream>
4 
5 #include "ros/ros.h"
6 #include "yaml-cpp/yaml.h"
7 
8 #include "geometry_msgs/Vector3.h"
9 #include "nav_msgs/Odometry.h"
10 #include "sensor_msgs/Imu.h"
11 #include "sensor_msgs/JointState.h"
12 #include "std_srvs/Trigger.h"
13 
14 #include "leo_msgs/Imu.h"
15 #include "leo_msgs/WheelOdom.h"
16 #include "leo_msgs/WheelOdomMecanum.h"
17 #include "leo_msgs/WheelStates.h"
18 
19 #include "leo_msgs/SetImuCalibration.h"
20 
21 constexpr double PI = 3.141592653;
22 
25 static bool joint_states_advertised = false;
26 
29 static bool wheel_odom_advertised = false;
30 
31 static bool wheel_odom_mecanum_advertised = false;
33 
36 static bool imu_advertised = false;
37 
40 static geometry_msgs::Point odom_merged_position;
41 static double odom_merged_yaw;
42 static bool odom_merged_advertised = false;
43 static double velocity_linear_x = 0;
44 static double velocity_linear_y = 0;
45 static double velocity_angular_z = 0;
48 
50 
51 std::string robot_frame_id = "base_link";
52 std::string odom_frame_id = "odom";
53 std::string imu_frame_id = "imu";
54 std::vector<std::string> wheel_joint_names = {
55  "wheel_FL_joint", "wheel_RL_joint", "wheel_FR_joint", "wheel_RR_joint"};
56 std::vector<double> wheel_odom_twist_covariance_diagonal = {0.0001, 0.0, 0.0,
57  0.0, 0.0, 0.001};
59  0.0001, 0.0001, 0.0, 0.0, 0.0, 0.001};
60 
62  0.000001, 0.000001, 0.00001};
63 std::vector<double> imu_linear_acceleration_covariance_diagonal = {0.001, 0.001,
64  0.001};
65 std::string tf_frame_prefix = "";
66 
67 std::vector<float> imu_calibration_bias = {0.0, 0.0, 0.0};
68 std::string calib_file_path = "";
69 
71  pnh.getParam("robot_frame_id", robot_frame_id);
72  pnh.getParam("odom_frame_id", odom_frame_id);
73  pnh.getParam("imu_frame_id", imu_frame_id);
74  pnh.getParam("wheel_joint_names", wheel_joint_names);
75  pnh.getParam("wheel_odom_twist_covariance_diagonal",
77  pnh.getParam("wheel_odom_mecanum_twist_covariance_diagonal",
79  pnh.getParam("imu_angular_velocity_covariance_diagonal",
81  pnh.getParam("imu_linear_acceleration_covariance_diagonal",
83  pnh.getParam("tf_frame_prefix", tf_frame_prefix);
84 
88 }
89 
90 void wheel_states_callback(const leo_msgs::WheelStatesPtr& msg) {
91  sensor_msgs::JointState joint_states;
92  joint_states.header.stamp = msg->stamp;
93  joint_states.name = wheel_joint_names;
94  joint_states.position =
95  std::vector<double>(msg->position.begin(), msg->position.end());
96  joint_states.velocity =
97  std::vector<double>(msg->velocity.begin(), msg->velocity.end());
98  joint_states.effort =
99  std::vector<double>(msg->torque.begin(), msg->torque.end());
100 
101  joint_states_pub.publish(joint_states);
102 }
103 
104 void wheel_odom_callback(const leo_msgs::WheelOdomPtr& msg) {
105  nav_msgs::Odometry wheel_odom;
106  wheel_odom.header.frame_id = odom_frame_id;
107  wheel_odom.child_frame_id = robot_frame_id;
108  wheel_odom.header.stamp = msg->stamp;
109  wheel_odom.twist.twist.linear.x = msg->velocity_lin;
110  wheel_odom.twist.twist.angular.z = msg->velocity_ang;
111  wheel_odom.pose.pose.position.x = msg->pose_x;
112  wheel_odom.pose.pose.position.y = msg->pose_y;
113  wheel_odom.pose.pose.orientation.z = std::sin(msg->pose_yaw * 0.5F);
114  wheel_odom.pose.pose.orientation.w = std::cos(msg->pose_yaw * 0.5F);
115 
116  velocity_linear_x = msg->velocity_lin;
117 
118  for (int i = 0; i < 6; i++)
119  wheel_odom.twist.covariance[i * 7] =
121 
122  wheel_odom_pub.publish(wheel_odom);
123 }
124 
125 void imu_callback(const leo_msgs::ImuPtr& msg) {
126  sensor_msgs::Imu imu;
127  imu.header.frame_id = imu_frame_id;
128  imu.header.stamp = msg->stamp;
129  imu.angular_velocity.x = msg->gyro_x + imu_calibration_bias[0];
130  imu.angular_velocity.y = msg->gyro_y + imu_calibration_bias[1];
131  imu.angular_velocity.z = msg->gyro_z + imu_calibration_bias[2];
132  imu.linear_acceleration.x = msg->accel_x;
133  imu.linear_acceleration.y = msg->accel_y;
134  imu.linear_acceleration.z = msg->accel_z;
135 
136  velocity_angular_z = imu.angular_velocity.z;
137 
138  for (int i = 0; i < 3; i++) {
139  imu.angular_velocity_covariance[i * 4] =
141  imu.linear_acceleration_covariance[i * 4] =
143  }
144 
145  imu_pub.publish(imu);
146 }
147 
148 void mecanum_odom_callback(const leo_msgs::WheelOdomMecanumPtr& msg) {
149  nav_msgs::Odometry wheel_odom;
150  wheel_odom.header.frame_id = odom_frame_id;
151  wheel_odom.child_frame_id = robot_frame_id;
152  wheel_odom.header.stamp = msg->stamp;
153  wheel_odom.twist.twist.linear.x = msg->velocity_lin_x;
154  wheel_odom.twist.twist.linear.y = msg->velocity_lin_y;
155  wheel_odom.twist.twist.angular.z = msg->velocity_ang;
156  wheel_odom.pose.pose.position.x = msg->pose_x;
157  wheel_odom.pose.pose.position.y = msg->pose_y;
158  wheel_odom.pose.pose.orientation.z = std::sin(msg->pose_yaw * 0.5F);
159  wheel_odom.pose.pose.orientation.w = std::cos(msg->pose_yaw * 0.5F);
160 
161  velocity_linear_x = msg->velocity_lin_x;
162  velocity_linear_y = msg->velocity_lin_y;
163 
164  for (int i = 0; i < 6; i++)
165  wheel_odom.twist.covariance[i * 7] =
167 
168  wheel_odom_pub.publish(wheel_odom);
169 }
170 
172  nav_msgs::Odometry merged_odom;
173  merged_odom.header.frame_id = odom_frame_id;
174  merged_odom.child_frame_id = robot_frame_id;
175  merged_odom.header.stamp = ros::Time::now();
176  merged_odom.twist.twist.linear.x = velocity_linear_x;
177  merged_odom.twist.twist.linear.y = velocity_linear_y;
178  merged_odom.twist.twist.angular.z = velocity_angular_z;
179 
180  const double move_x = velocity_linear_x * std::cos(odom_merged_yaw) -
182  const double move_y = velocity_linear_x * std::sin(odom_merged_yaw) +
184 
185  odom_merged_position.x += move_x * 0.01;
186  odom_merged_position.y += move_y * 0.01;
187 
189 
190  if (odom_merged_yaw > 2.0 * PI)
191  odom_merged_yaw -= 2.0 * PI;
192  else if (odom_merged_yaw < 0.0)
193  odom_merged_yaw += 2.0 * PI;
194 
195  merged_odom.pose.pose.position.x = odom_merged_position.x;
196  merged_odom.pose.pose.position.y = odom_merged_position.y;
197  merged_odom.pose.pose.orientation.z = std::sin(odom_merged_yaw * 0.5);
198  merged_odom.pose.pose.orientation.w = std::cos(odom_merged_yaw * 0.5);
199 
200  std::vector<double>* merged_covariance;
201 
204  else
205  merged_covariance = &wheel_odom_twist_covariance_diagonal;
206 
207  for (int i = 0; i < 5; i++)
208  merged_odom.twist.covariance[i * 7] = (*merged_covariance)[i];
209  merged_odom.twist.covariance[35] =
211 
212  odom_merged_pub.publish(merged_odom);
213 }
214 
216  YAML::Node node;
217  try {
218  node = YAML::LoadFile(calib_file_path);
219 
220  if (node["gyro_bias_x"])
221  imu_calibration_bias[0] = node["gyro_bias_x"].as<float>();
222 
223  if (node["gyro_bias_y"])
224  imu_calibration_bias[1] = node["gyro_bias_y"].as<float>();
225 
226  if (node["gyro_bias_z"])
227  imu_calibration_bias[2] = node["gyro_bias_z"].as<float>();
228 
229  } catch (YAML::BadFile& e) {
230  std::cerr << "Calibration file doesn't exist.\n";
231  std::cerr << "Creating calibration file with default gyrometer bias.\n";
232 
233  node["gyro_bias_x"] = imu_calibration_bias[0];
234  node["gyro_bias_y"] = imu_calibration_bias[1];
235  node["gyro_bias_z"] = imu_calibration_bias[2];
236 
237  std::ofstream fout(calib_file_path);
238  fout << node;
239  }
240 }
241 
242 std::string get_calib_path() {
243  std::string ros_home;
244  char* ros_home_env;
245  if (ros_home_env = std::getenv("ROS_HOME")) {
246  ros_home = ros_home_env;
247  } else if (ros_home_env = std::getenv("HOME")) {
248  ros_home = ros_home_env;
249  ros_home += "/.ros";
250  }
251 
252  return ros_home + "/imu_calibration.yaml";
253 }
254 
255 bool set_imu_calibration_callback(leo_msgs::SetImuCalibrationRequest& req,
256  leo_msgs::SetImuCalibrationResponse& res) {
257  ROS_INFO("SetImuCalibration request for: [ %f, %f, %f]", req.gyro_bias_x,
258  req.gyro_bias_y, req.gyro_bias_z);
259 
260  YAML::Node node = YAML::LoadFile(calib_file_path);
261  node["gyro_bias_x"] = imu_calibration_bias[0] = req.gyro_bias_x;
262  node["gyro_bias_y"] = imu_calibration_bias[1] = req.gyro_bias_y;
263  node["gyro_bias_z"] = imu_calibration_bias[2] = req.gyro_bias_z;
264  std::ofstream fout(calib_file_path);
265  fout << node;
266 
267  res.success = true;
268  return true;
269 }
270 
271 bool reset_odometry_callback(std_srvs::TriggerRequest& req,
272  std_srvs::TriggerResponse& res) {
273  odom_merged_position.x = 0.0;
274  odom_merged_position.y = 0.0;
275  odom_merged_yaw = 0.0;
276  if (odom_reset_client.call(req, res)) {
277  res.success = true;
278  return true;
279  } else {
280  res.success = false;
281  return false;
282  }
283 }
284 
285 int main(int argc, char** argv) {
286  ros::init(argc, argv, "firmware_message_converter");
287 
288  ros::NodeHandle nh;
289  ros::NodeHandle pnh("~");
290 
291  load_parameters(pnh);
293  load_yaml_bias();
294 
295  ros::AsyncSpinner spinner(4);
296  spinner.start();
297 
298  const std::string wheel_states_topic =
299  ros::names::resolve("firmware/wheel_states");
300  const std::string wheel_odom_topic =
301  ros::names::resolve("firmware/wheel_odom");
302  const std::string wheel_odom_mecanum_topic =
303  ros::names::resolve("firmware/wheel_odom_mecanum");
304  const std::string imu_topic = ros::names::resolve("firmware/imu");
305 
307  nh.advertiseService("set_imu_calibration", set_imu_calibration_callback);
309  nh.serviceClient<std_srvs::Trigger>("firmware/reset_odometry");
311  nh.advertiseService("reset_odometry", &reset_odometry_callback);
312 
313  ros::Rate rate(2);
314  while (ros::ok()) {
315  // Shutdown inactive topics
317  ROS_INFO(
318  "firmware/wheel_states topic no longer has any publishers. "
319  "Shutting down joint_states publisher.");
322  joint_states_advertised = false;
323  }
325  ROS_INFO(
326  "firmware/wheel_odom topic no longer has any publishers. "
327  "Shutting down wheel_odom_with_covariance and odometry_merged "
328  "publishers.");
333  wheel_odom_advertised = false;
334  odom_merged_advertised = false;
335  }
338  ROS_INFO(
339  "firmware/wheel_odom_mecanum topic no longer has any publishers. "
340  "Shutting down wheel_odom_with_covariance and odometry_merged "
341  "publishers.");
347  odom_merged_advertised = false;
348  }
349  if (imu_advertised && imu_sub.getNumPublishers() == 0) {
350  ROS_INFO(
351  "firmware/imu topic no longer has any publishers. "
352  "Shutting down imu/data_raw and odometry_merged publishers.");
353  imu_sub.shutdown();
354  imu_pub.shutdown();
357  imu_advertised = false;
358  odom_merged_advertised = false;
359  }
360 
361  rate.sleep();
362 
363  // Scan topics
365  ros::master::getTopics(topics);
366 
367  for (auto& topic : topics) {
368  if (!joint_states_advertised && topic.name == wheel_states_topic) {
369  ROS_INFO(
370  "Detected firmware/wheel_states topic advertised. "
371  "Advertising joint_states topic.");
373  nh.advertise<sensor_msgs::JointState>("joint_states", 10);
375  nh.subscribe("firmware/wheel_states", 5, wheel_states_callback);
377  }
378  if (!wheel_odom_advertised && topic.name == wheel_odom_topic) {
379  ROS_INFO(
380  "Detected firmware/wheel_odom topic advertised. "
381  "Advertising wheel_odom_with_covariance topic.");
383  nh.advertise<nav_msgs::Odometry>("wheel_odom_with_covariance", 10);
385  nh.subscribe("firmware/wheel_odom", 5, wheel_odom_callback);
386  wheel_odom_advertised = true;
387  }
389  topic.name == wheel_odom_mecanum_topic) {
390  ROS_INFO(
391  "Detected firmware/wheel_odom_mecanum topic advertised. "
392  "Advertising wheel_odom_with_covariance topic.");
394  nh.advertise<nav_msgs::Odometry>("wheel_odom_with_covariance", 10);
395  wheel_odom_mecanum_sub = nh.subscribe("firmware/wheel_odom_mecanum", 5,
398  }
399  if (!imu_advertised && topic.name == imu_topic) {
400  ROS_INFO(
401  "Detected firmware/imu topic advertised. "
402  "Advertising imu/data_raw topic.");
403  imu_pub = nh.advertise<sensor_msgs::Imu>("imu/data_raw", 10);
404  imu_sub = nh.subscribe("firmware/imu", 5, imu_callback);
405  imu_advertised = true;
406  }
409  ROS_INFO(
410  "Both firmware/imu and (firmware/wheel_odom or "
411  "firmware/wheel_odom_mecanum) topics are advertised. "
412  "Advertising odometry_merged topic.");
414  nh.advertise<nav_msgs::Odometry>("odometry_merged", 10);
417  odom_merged_advertised = true;
418  }
419  }
420 
421  rate.sleep();
422  }
423 }
wheel_states_sub
static ros::Subscriber wheel_states_sub
Definition: firmware_message_converter.cpp:23
ros::Publisher
main
int main(int argc, char **argv)
Definition: firmware_message_converter.cpp:285
odom_merged_pub
static ros::Publisher odom_merged_pub
Definition: firmware_message_converter.cpp:38
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
robot_frame_id
std::string robot_frame_id
Definition: firmware_message_converter.cpp:51
ros::AsyncSpinner::start
void start()
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
imu_callback
void imu_callback(const leo_msgs::ImuPtr &msg)
Definition: firmware_message_converter.cpp:125
ros.h
ros::Timer::stop
void stop()
ros::AsyncSpinner
ros::NodeHandle::serviceClient
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
imu_angular_velocity_covariance_diagonal
std::vector< double > imu_angular_velocity_covariance_diagonal
Definition: firmware_message_converter.cpp:61
ros::NodeHandle::advertiseService
ServiceServer advertiseService(AdvertiseServiceOptions &ops)
calib_file_path
std::string calib_file_path
Definition: firmware_message_converter.cpp:68
ros::Subscriber::shutdown
void shutdown()
wheel_odom_mecanum_twist_covariance_diagonal
std::vector< double > wheel_odom_mecanum_twist_covariance_diagonal
Definition: firmware_message_converter.cpp:58
joint_states_pub
static ros::Publisher joint_states_pub
Definition: firmware_message_converter.cpp:24
wheel_odom_pub
static ros::Publisher wheel_odom_pub
Definition: firmware_message_converter.cpp:28
set_imu_calibration_callback
bool set_imu_calibration_callback(leo_msgs::SetImuCalibrationRequest &req, leo_msgs::SetImuCalibrationResponse &res)
Definition: firmware_message_converter.cpp:255
ros::master::getTopics
ROSCPP_DECL bool getTopics(V_TopicInfo &topics)
wheel_joint_names
std::vector< std::string > wheel_joint_names
Definition: firmware_message_converter.cpp:54
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
ros::ok
ROSCPP_DECL bool ok()
ros::names::resolve
ROSCPP_DECL std::string resolve(const std::string &name, bool remap=true)
ros::Subscriber::getNumPublishers
uint32_t getNumPublishers() const
ros::ServiceServer
wheel_states_callback
void wheel_states_callback(const leo_msgs::WheelStatesPtr &msg)
Definition: firmware_message_converter.cpp:90
odom_reset_client
static ros::ServiceClient odom_reset_client
Definition: firmware_message_converter.cpp:46
imu_advertised
static bool imu_advertised
Definition: firmware_message_converter.cpp:36
ros::Publisher::shutdown
void shutdown()
reset_odometry_service
static ros::ServiceServer reset_odometry_service
Definition: firmware_message_converter.cpp:47
ros::master::V_TopicInfo
std::vector< TopicInfo > V_TopicInfo
odom_frame_id
std::string odom_frame_id
Definition: firmware_message_converter.cpp:52
imu_frame_id
std::string imu_frame_id
Definition: firmware_message_converter.cpp:53
velocity_angular_z
static double velocity_angular_z
Definition: firmware_message_converter.cpp:45
imu_linear_acceleration_covariance_diagonal
std::vector< double > imu_linear_acceleration_covariance_diagonal
Definition: firmware_message_converter.cpp:63
load_parameters
void load_parameters(ros::NodeHandle &pnh)
Definition: firmware_message_converter.cpp:70
reset_odometry_callback
bool reset_odometry_callback(std_srvs::TriggerRequest &req, std_srvs::TriggerResponse &res)
Definition: firmware_message_converter.cpp:271
odom_merged_yaw
static double odom_merged_yaw
Definition: firmware_message_converter.cpp:41
ros::ServiceClient
odom_merged_timer
static ros::Timer odom_merged_timer
Definition: firmware_message_converter.cpp:39
odom_merged_advertised
static bool odom_merged_advertised
Definition: firmware_message_converter.cpp:42
wheel_odom_mecanum_advertised
static bool wheel_odom_mecanum_advertised
Definition: firmware_message_converter.cpp:31
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
ros::TimerEvent
ros::Rate::sleep
bool sleep()
tf_frame_prefix
std::string tf_frame_prefix
Definition: firmware_message_converter.cpp:65
mecanum_odom_callback
void mecanum_odom_callback(const leo_msgs::WheelOdomMecanumPtr &msg)
Definition: firmware_message_converter.cpp:148
wheel_odom_advertised
static bool wheel_odom_advertised
Definition: firmware_message_converter.cpp:29
imu_sub
static ros::Subscriber imu_sub
Definition: firmware_message_converter.cpp:34
wheel_odom_sub
static ros::Subscriber wheel_odom_sub
Definition: firmware_message_converter.cpp:27
ros::ServiceClient::call
bool call(const MReq &req, MRes &resp, const std::string &service_md5sum)
odom_merged_position
static geometry_msgs::Point odom_merged_position
Definition: firmware_message_converter.cpp:40
ros::Rate
merge_odometry_callback
void merge_odometry_callback(const ros::TimerEvent &events)
Definition: firmware_message_converter.cpp:171
wheel_odom_mecanum_sub
static ros::Subscriber wheel_odom_mecanum_sub
Definition: firmware_message_converter.cpp:32
set_imu_calibration_service
ros::ServiceServer set_imu_calibration_service
Definition: firmware_message_converter.cpp:49
wheel_odom_callback
void wheel_odom_callback(const leo_msgs::WheelOdomPtr &msg)
Definition: firmware_message_converter.cpp:104
imu_pub
static ros::Publisher imu_pub
Definition: firmware_message_converter.cpp:35
get_calib_path
std::string get_calib_path()
Definition: firmware_message_converter.cpp:242
ROS_INFO
#define ROS_INFO(...)
ros::NodeHandle::createTimer
Timer createTimer(Duration period, const TimerCallback &callback, bool oneshot=false, bool autostart=true) const
joint_states_advertised
static bool joint_states_advertised
Definition: firmware_message_converter.cpp:25
velocity_linear_y
static double velocity_linear_y
Definition: firmware_message_converter.cpp:44
ros::Duration
ros::Timer
load_yaml_bias
void load_yaml_bias()
Definition: firmware_message_converter.cpp:215
imu_calibration_bias
std::vector< float > imu_calibration_bias
Definition: firmware_message_converter.cpp:67
wheel_odom_twist_covariance_diagonal
std::vector< double > wheel_odom_twist_covariance_diagonal
Definition: firmware_message_converter.cpp:56
PI
constexpr double PI
Definition: firmware_message_converter.cpp:21
velocity_linear_x
static double velocity_linear_x
Definition: firmware_message_converter.cpp:43
ros::NodeHandle
ros::Subscriber
ros::Time::now
static Time now()


leo_fw
Author(s): Błażej Sowa , Aleksander Szymański
autogenerated on Sat Jul 6 2024 03:05:11