rosflight_io.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Daniel Koch and James Jackson, BYU MAGICC Lab.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * * Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
40 #include <string>
41 #include <stdint.h>
42 #include <eigen3/Eigen/Core>
43 #include <eigen3/Eigen/Dense>
44 #include <tf/tf.h>
45 
46 #include <rosflight/rosflight_io.h>
47 
48 namespace rosflight_io
49 {
51 {
53  attitude_sub_ = nh_.subscribe("attitude_correction", 1, &rosflightIO::attitudeCorrectionCallback, this);
54 
55  unsaved_params_pub_ = nh_.advertise<std_msgs::Bool>("unsaved_params", 1, true);
56  error_pub_ = nh_.advertise<rosflight_msgs::Error>("rosflight_errors",5,true); // A relatively large queue so all messages get through
57 
67 
68  ros::NodeHandle nh_private("~");
69 
70  if (nh_private.param<bool>("udp", false))
71  {
72  std::string bind_host = nh_private.param<std::string>("bind_host", "localhost");
73  uint16_t bind_port = (uint16_t) nh_private.param<int>("bind_port", 14520);
74  std::string remote_host = nh_private.param<std::string>("remote_host", bind_host);
75  uint16_t remote_port = (uint16_t) nh_private.param<int>("remote_port", 14525);
76 
77  ROS_INFO("Connecting over UDP to \"%s:%d\", from \"%s:%d\"", remote_host.c_str(), remote_port, bind_host.c_str(), bind_port);
78 
79  mavlink_comm_ = new mavrosflight::MavlinkUDP(bind_host, bind_port, remote_host, remote_port);
80  }
81  else
82  {
83  std::string port = nh_private.param<std::string>("port", "/dev/ttyUSB0");
84  int baud_rate = nh_private.param<int>("baud_rate", 921600);
85 
86  ROS_INFO("Connecting to serial port \"%s\", at %d baud", port.c_str(), baud_rate);
87 
88  mavlink_comm_ = new mavrosflight::MavlinkSerial(port, baud_rate);
89  }
90 
91  try
92  {
93  mavlink_comm_->open();
95  }
97  {
98  ROS_FATAL("%s", e.what());
99  ros::shutdown();
100  }
101 
104 
105  // request the param list
108 
109  // request version information
110  request_version();
112 
113  // initialize latched "unsaved parameters" message value
114  std_msgs::Bool unsaved_msg;
115  unsaved_msg.data = false;
116  unsaved_params_pub_.publish(unsaved_msg);
117 
118  // Set up a few other random things
119  frame_id_ = nh_private.param<std::string>("frame_id", "world");
120 
121  prev_status_.armed = false;
122  prev_status_.failsafe = false;
123  prev_status_.rc_override = false;
124  prev_status_.offboard = false;
127 
128  //Start the heartbeat
130 }
131 
133 {
134  delete mavrosflight_;
135  delete mavlink_comm_;
136 }
137 
138 void rosflightIO::handle_mavlink_message(const mavlink_message_t &msg)
139 {
140  switch (msg.msgid)
141  {
144  break;
146  handle_status_msg(msg);
147  break;
150  break;
153  break;
156  break;
159  break;
162  break;
165  break;
168  break;
171  break;
174  break;
177  break;
180  break;
183  break;
186  break;
189  break;
192  break;
194  handle_version_msg(msg);
195  break;
198  // silently ignore (handled elsewhere)
199  break;
202  break;
203  default:
204  ROS_DEBUG("rosflight_io: Got unhandled mavlink message ID %d", msg.msgid);
205  break;
206  }
207 }
208 
209 void rosflightIO::on_new_param_received(std::string name, double value)
210 {
211  ROS_DEBUG("Got parameter %s with value %g", name.c_str(), value);
212 }
213 
214 void rosflightIO::on_param_value_updated(std::string name, double value)
215 {
216  ROS_INFO("Parameter %s has new value %g", name.c_str(), value);
217 }
218 
219 void rosflightIO::on_params_saved_change(bool unsaved_changes)
220 {
221  std_msgs::Bool msg;
222  msg.data = unsaved_changes;
224 
225  if (unsaved_changes)
226  {
227  ROS_WARN_THROTTLE(1,"There are unsaved changes to onboard parameters");
228  }
229  else
230  {
231  ROS_INFO("Onboard parameters have been saved");
232  }
233 }
234 
235 void rosflightIO::handle_heartbeat_msg(const mavlink_message_t &msg)
236 {
237  ROS_INFO_ONCE("Got HEARTBEAT, connected.");
238 }
239 
240 void rosflightIO::handle_status_msg(const mavlink_message_t &msg)
241 {
242  mavlink_rosflight_status_t status_msg;
243  mavlink_msg_rosflight_status_decode(&msg, &status_msg);
244 
245  // armed state check
246  if (prev_status_.armed != status_msg.armed)
247  {
248  if (status_msg.armed)
249  ROS_WARN("Autopilot ARMED");
250  else
251  ROS_WARN("Autopilot DISARMED");
252  }
253 
254  // failsafe check
255  if (prev_status_.failsafe != status_msg.failsafe)
256  {
257  if (status_msg.failsafe)
258  ROS_ERROR("Autopilot FAILSAFE");
259  else
260  ROS_INFO("Autopilot FAILSAFE RECOVERED");
261  }
262 
263  // rc override check
264  if (prev_status_.rc_override != status_msg.rc_override)
265  {
266  if (status_msg.rc_override)
267  ROS_WARN("RC override active");
268  else
269  ROS_WARN("Returned to computer control");
270  }
271 
272  // offboard control check
273  if (prev_status_.offboard != status_msg.offboard)
274  {
275  if (status_msg.offboard)
276  ROS_WARN("Computer control active");
277  else
278  ROS_WARN("Computer control lost");
279  }
280 
281  // Print if got error code
282  if (prev_status_.error_code != status_msg.error_code)
283  {
291 
292  ROS_DEBUG("Autopilot ERROR 0x%02x", status_msg.error_code);
293  }
294 
295  // Print if change in control mode
296  if (prev_status_.control_mode != status_msg.control_mode)
297  {
298  std::string mode_string;
299  switch (status_msg.control_mode)
300  {
301  case MODE_PASS_THROUGH:
302  mode_string = "PASS_THROUGH";
303  break;
305  mode_string = "RATE";
306  break;
308  mode_string = "ANGLE";
309  break;
310  default:
311  mode_string = "UNKNOWN";
312  }
313  ROS_WARN_STREAM("Autopilot now in " << mode_string << " mode");
314  }
315 
316  prev_status_ = status_msg;
317 
318  // Build the status message and send it
319  rosflight_msgs::Status out_status;
320  out_status.header.stamp = ros::Time::now();
321  out_status.armed = status_msg.armed;
322  out_status.failsafe = status_msg.failsafe;
323  out_status.rc_override = status_msg.rc_override;
324  out_status.offboard = status_msg.offboard;
325  out_status.control_mode = status_msg.control_mode;
326  out_status.error_code = status_msg.error_code;
327  out_status.num_errors = status_msg.num_errors;
328  out_status.loop_time_us = status_msg.loop_time_us;
329  if (status_pub_.getTopic().empty())
330  {
331  status_pub_ = nh_.advertise<rosflight_msgs::Status>("status", 1);
332  }
333  status_pub_.publish(out_status);
334 }
335 
336 void rosflightIO::handle_command_ack_msg(const mavlink_message_t &msg)
337 {
340 
341  if (ack.success == ROSFLIGHT_CMD_SUCCESS)
342  {
343  ROS_DEBUG("MAVLink command %d Acknowledged", ack.command);
344  }
345  else
346  {
347  ROS_ERROR("MAVLink command %d Failed", ack.command);
348  }
349 }
350 
351 void rosflightIO::handle_statustext_msg(const mavlink_message_t &msg)
352 {
353  mavlink_statustext_t status;
354  mavlink_msg_statustext_decode(&msg, &status);
355 
356  // ensure null termination
358  memcpy(c_str, status.text, MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN);
360 
361  switch (status.severity)
362  {
364  case MAV_SEVERITY_ALERT:
366  case MAV_SEVERITY_ERROR:
367  ROS_ERROR("[Autopilot]: %s", c_str);
368  break;
370  ROS_WARN("[Autopilot]: %s", c_str);
371  break;
372  case MAV_SEVERITY_NOTICE:
373  case MAV_SEVERITY_INFO:
374  ROS_INFO("[Autopilot]: %s", c_str);
375  break;
376  case MAV_SEVERITY_DEBUG:
377  ROS_DEBUG("[Autopilot]: %s", c_str);
378  break;
379  }
380 }
381 
382 void rosflightIO::handle_attitude_quaternion_msg(const mavlink_message_t &msg)
383 {
386 
387  rosflight_msgs::Attitude attitude_msg;
388  attitude_msg.header.stamp = mavrosflight_->time.get_ros_time_ms(attitude.time_boot_ms);
389  attitude_msg.attitude.w = attitude.q1;
390  attitude_msg.attitude.x = attitude.q2;
391  attitude_msg.attitude.y = attitude.q3;
392  attitude_msg.attitude.z = attitude.q4;
393  attitude_msg.angular_velocity.x = attitude.rollspeed;
394  attitude_msg.angular_velocity.y = attitude.pitchspeed;
395  attitude_msg.angular_velocity.z = attitude.yawspeed;
396 
397  geometry_msgs::Vector3Stamped euler_msg;
398  euler_msg.header.stamp = attitude_msg.header.stamp;
399 
400  tf::Quaternion quat(attitude.q2, attitude.q3, attitude.q4, attitude.q1);
401  tf::Matrix3x3(quat).getEulerYPR(euler_msg.vector.z, euler_msg.vector.y, euler_msg.vector.x);
402 
403  // save off the quaternion for use with the IMU callback
405 
406  if (attitude_pub_.getTopic().empty())
407  {
408  attitude_pub_ = nh_.advertise<rosflight_msgs::Attitude>("attitude", 1);
409  }
410  if (euler_pub_.getTopic().empty())
411  {
412  euler_pub_ = nh_.advertise<geometry_msgs::Vector3Stamped>("attitude/euler", 1);
413  }
414  attitude_pub_.publish(attitude_msg);
415  euler_pub_.publish(euler_msg);
416 }
417 
418 void rosflightIO::handle_small_imu_msg(const mavlink_message_t &msg)
419 {
421  mavlink_msg_small_imu_decode(&msg, &imu);
422 
423  sensor_msgs::Imu imu_msg;
424  imu_msg.header.stamp = mavrosflight_->time.get_ros_time_us(imu.time_boot_us);
425  imu_msg.header.frame_id = frame_id_;
426  imu_msg.linear_acceleration.x = imu.xacc;
427  imu_msg.linear_acceleration.y = imu.yacc;
428  imu_msg.linear_acceleration.z = imu.zacc;
429  imu_msg.angular_velocity.x = imu.xgyro;
430  imu_msg.angular_velocity.y = imu.ygyro;
431  imu_msg.angular_velocity.z = imu.zgyro;
432  imu_msg.orientation = attitude_quat_;
433 
434  sensor_msgs::Temperature temp_msg;
435  temp_msg.header.stamp = imu_msg.header.stamp;
436  temp_msg.header.frame_id = frame_id_;
437  temp_msg.temperature = imu.temperature;
438 
439  if (imu_pub_.getTopic().empty())
440  {
441  imu_pub_ = nh_.advertise<sensor_msgs::Imu>("imu/data", 1);
442  }
443  imu_pub_.publish(imu_msg);
444 
445  if (imu_temp_pub_.getTopic().empty())
446  {
447  imu_temp_pub_ = nh_.advertise<sensor_msgs::Temperature>("imu/temperature", 1);
448  }
449  imu_temp_pub_.publish(temp_msg);
450 }
451 
452 void rosflightIO::handle_rosflight_output_raw_msg(const mavlink_message_t &msg)
453 {
456 
457  rosflight_msgs::OutputRaw out_msg;
458  out_msg.header.stamp = mavrosflight_->time.get_ros_time_us(servo.stamp);
459  for (int i = 0; i < 8; i++)
460  {
461  out_msg.values[i] = servo.values[i];
462  }
463 
464  if (output_raw_pub_.getTopic().empty())
465  {
466  output_raw_pub_ = nh_.advertise<rosflight_msgs::OutputRaw>("output_raw", 1);
467  }
468  output_raw_pub_.publish(out_msg);
469 }
470 
471 void rosflightIO::handle_rc_channels_raw_msg(const mavlink_message_t &msg)
472 {
475 
476  rosflight_msgs::RCRaw out_msg;
477  out_msg.header.stamp = mavrosflight_->time.get_ros_time_ms(rc.time_boot_ms);
478 
479  out_msg.values[0] = rc.chan1_raw;
480  out_msg.values[1] = rc.chan2_raw;
481  out_msg.values[2] = rc.chan3_raw;
482  out_msg.values[3] = rc.chan4_raw;
483  out_msg.values[4] = rc.chan5_raw;
484  out_msg.values[5] = rc.chan6_raw;
485  out_msg.values[6] = rc.chan7_raw;
486  out_msg.values[7] = rc.chan8_raw;
487 
488  if (rc_raw_pub_.getTopic().empty())
489  {
490  rc_raw_pub_ = nh_.advertise<rosflight_msgs::RCRaw>("rc_raw", 1);
491  }
492  rc_raw_pub_.publish(out_msg);
493 }
494 
495 void rosflightIO::handle_diff_pressure_msg(const mavlink_message_t &msg)
496 {
499 
500  rosflight_msgs::Airspeed airspeed_msg;
501  airspeed_msg.header.stamp = ros::Time::now();
502  airspeed_msg.velocity = diff.velocity;
503  airspeed_msg.differential_pressure = diff.diff_pressure;
504  airspeed_msg.temperature = diff.temperature;
505 
506  if(calibrate_airspeed_srv_.getService().empty())
507  {
509  }
510 
511  if (diff_pressure_pub_.getTopic().empty())
512  {
513  diff_pressure_pub_ = nh_.advertise<rosflight_msgs::Airspeed>("airspeed", 1);
514  }
515  diff_pressure_pub_.publish(airspeed_msg);
516 }
517 
518 void rosflightIO::handle_named_value_int_msg(const mavlink_message_t &msg)
519 {
522 
523  // ensure null termination of name
527  std::string name(c_name);
528 
529  if (named_value_int_pubs_.find(name) == named_value_int_pubs_.end())
530  {
531  ros::NodeHandle nh;
532  named_value_int_pubs_[name] = nh.advertise<std_msgs::Int32>("named_value/int/" + name, 1);
533  }
534 
535  std_msgs::Int32 out_msg;
536  out_msg.data = val.value;
537 
538  named_value_int_pubs_[name].publish(out_msg);
539 }
540 
541 void rosflightIO::handle_named_value_float_msg(const mavlink_message_t &msg)
542 {
545 
546  // ensure null termination of name
550  std::string name(c_name);
551 
552  if (named_value_float_pubs_.find(name) == named_value_float_pubs_.end())
553  {
554  ros::NodeHandle nh;
555  named_value_float_pubs_[name] = nh.advertise<std_msgs::Float32>("named_value/float/" + name, 1);
556  }
557 
558  std_msgs::Float32 out_msg;
559  out_msg.data = val.value;
560 
561  named_value_float_pubs_[name].publish(out_msg);
562 }
563 
564 void rosflightIO::handle_named_command_struct_msg(const mavlink_message_t &msg)
565 {
568 
569  // ensure null termination of name
571  memcpy(c_name, command.name, MAVLINK_MSG_NAMED_VALUE_FLOAT_FIELD_NAME_LEN);
573  std::string name(c_name);
574 
576  {
577  ros::NodeHandle nh;
578  named_command_struct_pubs_[name] = nh.advertise<rosflight_msgs::Command>("named_value/command_struct/" + name, 1);
579  }
580 
581  rosflight_msgs::Command command_msg;
582  if (command.type == MODE_PASS_THROUGH)
586  else if (command.type == MODE_ROLL_PITCH_YAWRATE_THROTTLE)
588  else if (command.type == MODE_ROLL_PITCH_YAWRATE_ALTITUDE)
590 
591  command_msg.ignore = command.ignore;
592  command_msg.x = command.x;
593  command_msg.y = command.y;
594  command_msg.z = command.z;
595  command_msg.F = command.F;
596  named_command_struct_pubs_[name].publish(command_msg);
597 }
598 
599 void rosflightIO::handle_small_baro_msg(const mavlink_message_t &msg)
600 {
602  mavlink_msg_small_baro_decode(&msg, &baro);
603 
604  rosflight_msgs::Barometer baro_msg;
605  baro_msg.header.stamp = ros::Time::now();
606  baro_msg.altitude = baro.altitude;
607  baro_msg.pressure = baro.pressure;
608  baro_msg.temperature = baro.temperature;
609 
610  // If we are getting barometer messages, then we should publish the barometer calibration service
611  if(calibrate_baro_srv_.getService().empty())
612  {
614  }
615 
616  if (baro_pub_.getTopic().empty())
617  {
618  baro_pub_ = nh_.advertise<rosflight_msgs::Barometer>("baro", 1);
619  }
620  baro_pub_.publish(baro_msg);
621 }
622 
623 void rosflightIO::handle_small_mag_msg(const mavlink_message_t &msg)
624 {
626  mavlink_msg_small_mag_decode(&msg, &mag);
627 
629  sensor_msgs::MagneticField mag_msg;
630  mag_msg.header.stamp = ros::Time::now();//mavrosflight_->time.get_ros_time_us(mag.time_boot_us);
631  mag_msg.header.frame_id = frame_id_;
632 
633  mag_msg.magnetic_field.x = mag.xmag;
634  mag_msg.magnetic_field.y = mag.ymag;
635  mag_msg.magnetic_field.z = mag.zmag;
636 
637  if (mag_pub_.getTopic().empty())
638  {
639  mag_pub_ = nh_.advertise<sensor_msgs::MagneticField>("magnetometer", 1);
640  }
641  mag_pub_.publish(mag_msg);
642 }
643 
644 void rosflightIO::handle_small_range_msg(const mavlink_message_t &msg)
645 {
646  mavlink_small_range_t range;
647  mavlink_msg_small_range_decode(&msg, &range);
648 
649  sensor_msgs::Range alt_msg;
650  alt_msg.header.stamp = ros::Time::now();
651  alt_msg.max_range = range.max_range;
652  alt_msg.min_range = range.min_range;
653  alt_msg.range = range.range;
654 
655  switch(range.type) {
657  alt_msg.radiation_type = sensor_msgs::Range::ULTRASOUND;
658  alt_msg.field_of_view = 1.0472; // approx 60 deg
659 
660  if (sonar_pub_.getTopic().empty())
661  {
662  sonar_pub_ = nh_.advertise<sensor_msgs::Range>("sonar", 1);
663  }
664  sonar_pub_.publish(alt_msg);
665  break;
667  alt_msg.radiation_type = sensor_msgs::Range::INFRARED;
668  alt_msg.field_of_view = .0349066; //approx 2 deg
669 
670  if (lidar_pub_.getTopic().empty())
671  {
672  lidar_pub_ = nh_.advertise<sensor_msgs::Range>("lidar", 1);
673  }
674  lidar_pub_.publish(alt_msg);
675  break;
676  default:
677  break;
678  }
679 
680 }
681 
682 void rosflightIO::handle_version_msg(const mavlink_message_t &msg)
683 {
685 
687  mavlink_msg_rosflight_version_decode(&msg, &version);
688 
689  std_msgs::String version_msg;
690  version_msg.data = version.version;
691 
692  if (version_pub_.getTopic().empty())
693  {
694  version_pub_ = nh_.advertise<std_msgs::String>("version", 1, true);
695  }
696  version_pub_.publish(version_msg);
697 
698  ROS_INFO("Firmware version: %s", version.version);
699 }
700 
701 void rosflightIO::handle_hard_error_msg(const mavlink_message_t &msg)
702 {
705  ROS_ERROR("Hard fault detected, with error code %u. The flight controller has rebooted.",error.error_code);
706  ROS_ERROR("Hard fault was at: 0x%x",error.pc);
707  if(error.doRearm)
708  {
709  ROS_ERROR("The firmware has rearmed itself.");
710  }
711  ROS_ERROR("The flight controller has rebooted %u time%s.", error.reset_count, error.reset_count>1?"s":"");
712  rosflight_msgs::Error error_msg;
713  error_msg.error_message = "A firmware error has caused the flight controller to reboot.";
714  error_msg.error_code = error.error_code;
715  error_msg.reset_count = error.reset_count;
716  error_msg.rearm = error.doRearm;
717  error_msg.pc = error.pc;
718  error_pub_.publish(error_msg);
719 }
720 
721 void rosflightIO::handle_rosflight_gnss_msg(const mavlink_message_t &msg) {
724 
726 
727  rosflight_msgs::GNSS gnss_msg;
728  gnss_msg.header.stamp = stamp;
729  gnss_msg.header.frame_id = "ECEF";
730  gnss_msg.fix = gnss.fix_type;
731  gnss_msg.time = ros::Time(gnss.time, gnss.nanos);
732  gnss_msg.position[0] = .01 * gnss.ecef_x; //.01 for conversion from cm to m
733  gnss_msg.position[1] = .01 * gnss.ecef_y;
734  gnss_msg.position[2] = .01 * gnss.ecef_z;
735  gnss_msg.horizontal_accuracy = gnss.h_acc;
736  gnss_msg.vertical_accuracy = gnss.v_acc;
737  gnss_msg.velocity[0] = .01 * gnss.ecef_v_x; //.01 for conversion from cm/s to m/s
738  gnss_msg.velocity[1] = .01 * gnss.ecef_v_y;
739  gnss_msg.velocity[2] = .01 * gnss.ecef_v_z;
740  gnss_msg.speed_accuracy = gnss.s_acc;
741  if (gnss_pub_.getTopic().empty()) {
742  gnss_pub_ = nh_.advertise<rosflight_msgs::GNSS>("gnss", 1);
743  }
744  gnss_pub_.publish(gnss_msg);
745 
746  sensor_msgs::NavSatFix navsat_fix;
747  navsat_fix.header.stamp = stamp;
748  navsat_fix.header.frame_id = "LLA";
749  navsat_fix.latitude = 1e-7 * gnss.lat; //1e-7 to convert from 100's of nanodegrees
750  navsat_fix.longitude = 1e-7 * gnss.lon; //1e-7 to convert from 100's of nanodegrees
751  navsat_fix.altitude = .001 * gnss.height; //.001 to convert from mm to m
752  navsat_fix.position_covariance[0] = gnss.h_acc * gnss.h_acc;
753  navsat_fix.position_covariance[4] = gnss.h_acc * gnss.h_acc;
754  navsat_fix.position_covariance[8] = gnss.v_acc * gnss.v_acc;
755  navsat_fix.position_covariance_type = sensor_msgs::NavSatFix::COVARIANCE_TYPE_DIAGONAL_KNOWN;
756  sensor_msgs::NavSatStatus navsat_status;
757  //3 or 4 from UBX corresponds to a fix. 0 means a fix to ROS, else -1 for no fix.
758  navsat_status.status = (gnss.fix_type == 3 || gnss.fix_type == 4) ? 0 : -1;
759  //The UBX is not configured to report which system is used, even though it supports them all
760  navsat_status.service = 1; //Report that only GPS was used, even though others may have been
761  navsat_fix.status = navsat_status;
762 
763  if (nav_sat_fix_pub_.getTopic().empty()) {
764  nav_sat_fix_pub_ = nh_.advertise<sensor_msgs::NavSatFix>("navsat_compat/fix",1);
765  }
766  nav_sat_fix_pub_.publish(navsat_fix);
767 
768  geometry_msgs::TwistStamped twist_stamped;
769  twist_stamped.header.stamp = stamp;
770  //GNSS does not provide angular data
771  twist_stamped.twist.angular.x = 0;
772  twist_stamped.twist.angular.y = 0;
773  twist_stamped.twist.angular.z = 0;
774 
775  twist_stamped.twist.linear.x = .001 * gnss.vel_n; //Convert from mm/s to m/s
776  twist_stamped.twist.linear.y = .001 * gnss.vel_e;
777  twist_stamped.twist.linear.z = .001 * gnss.vel_d;
778 
779  if (twist_stamped_pub_.getTopic().empty())
780  twist_stamped_pub_ = nh_.advertise<geometry_msgs::TwistStamped>("navsat_compat/vel",1);
781  twist_stamped_pub_.publish(twist_stamped);
782 
783  sensor_msgs::TimeReference time_ref;
784  time_ref.header.stamp = stamp;
785  time_ref.source = "GNSS";
786  time_ref.time_ref = ros::Time(gnss.time, gnss.nanos);
787 
788  if(time_reference_pub_.getTopic().empty())
789  time_reference_pub_ = nh_.advertise<geometry_msgs::TwistStamped>("navsat_compat/time_reference",1);
790 
791 }
792 
793 
794 void rosflightIO::handle_rosflight_gnss_raw_msg(const mavlink_message_t &msg) {
797 
798  rosflight_msgs::GNSSRaw msg_out;
799  msg_out.header.stamp = ros::Time::now();
800  msg_out.time_of_week = raw.time_of_week;
801  msg_out.year = raw.year;
802  msg_out.month = raw.month;
803  msg_out.day = raw.day;
804  msg_out.hour = raw.hour;
805  msg_out.min = raw.min;
806  msg_out.sec = raw.sec;
807  msg_out.valid = raw.valid;
808  msg_out.t_acc = raw.t_acc;
809  msg_out.nano = raw.nano;
810  msg_out.fix_type = raw.fix_type;
811  msg_out.num_sat = raw.num_sat;
812  msg_out.lon = raw.lon;
813  msg_out.lat = raw.lat;
814  msg_out.height = raw.height;
815  msg_out.height_msl = raw.height_msl;
816  msg_out.h_acc = raw.h_acc;
817  msg_out.v_acc = raw.v_acc;
818  msg_out.vel_n = raw.vel_n;
819  msg_out.vel_e = raw.vel_e;
820  msg_out.vel_d = raw.vel_d;
821  msg_out.g_speed = raw.g_speed;
822  msg_out.head_mot = raw.head_mot;
823  msg_out.s_acc = raw.s_acc;
824  msg_out.head_acc = raw.head_acc;
825  msg_out.p_dop = raw.p_dop;
826 
827  if (gnss_raw_pub_.getTopic().empty())
828  gnss_raw_pub_ = nh_.advertise<rosflight_msgs::GNSSRaw>("gps_raw", 1);
829  gnss_raw_pub_.publish(msg_out);
830 }
831 
832 void rosflightIO::commandCallback(rosflight_msgs::Command::ConstPtr msg)
833 {
836  OFFBOARD_CONTROL_IGNORE ignore = (OFFBOARD_CONTROL_IGNORE)msg->ignore;
837 
838  float x = msg->x;
839  float y = msg->y;
840  float z = msg->z;
841  float F = msg->F;
842 
843  switch (mode)
844  {
845  case MODE_PASS_THROUGH:
846  x = saturate(x, -1.0f, 1.0f);
847  y = saturate(y, -1.0f, 1.0f);
848  z = saturate(z, -1.0f, 1.0f);
849  F = saturate(F, 0.0f, 1.0f);
850  break;
853  F = saturate(F, 0.0f, 1.0f);
854  break;
856  break;
857  }
858 
859  mavlink_message_t mavlink_msg;
860  mavlink_msg_offboard_control_pack(1, 50, &mavlink_msg, mode, ignore, x, y, z, F);
861  mavrosflight_->comm.send_message(mavlink_msg);
862 }
863 
864 void rosflightIO::attitudeCorrectionCallback(geometry_msgs::Quaternion::ConstPtr msg)
865 {
866  mavlink_message_t mavlink_msg;
867  mavlink_msg_attitude_correction_pack(1, 50, &mavlink_msg, msg->w, msg->x, msg->y, msg->z);
868  mavrosflight_->comm.send_message(mavlink_msg);
869 }
870 
871 bool rosflightIO::paramGetSrvCallback(rosflight_msgs::ParamGet::Request &req, rosflight_msgs::ParamGet::Response &res)
872 {
873  res.exists = mavrosflight_->param.get_param_value(req.name, &res.value);
874  return true;
875 }
876 
877 bool rosflightIO::paramSetSrvCallback(rosflight_msgs::ParamSet::Request &req, rosflight_msgs::ParamSet::Response &res)
878 {
879  res.exists = mavrosflight_->param.set_param_value(req.name, req.value);
880  return true;
881 }
882 
883 bool rosflightIO::paramWriteSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
884 {
885  res.success = mavrosflight_->param.write_params();
886  if (!res.success)
887  {
888  res.message = "Request rejected: write already in progress";
889  }
890 
891  return true;
892 }
893 
894 bool rosflightIO::paramSaveToFileCallback(rosflight_msgs::ParamFile::Request &req, rosflight_msgs::ParamFile::Response &res)
895 {
896  res.success = mavrosflight_->param.save_to_file(req.filename);
897  return true;
898 }
899 
900 bool rosflightIO::paramLoadFromFileCallback(rosflight_msgs::ParamFile::Request &req, rosflight_msgs::ParamFile::Response &res)
901 {
902  res.success = mavrosflight_->param.load_from_file(req.filename);
903  return true;
904 }
905 
906 bool rosflightIO::calibrateImuBiasSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
907 {
908  mavlink_message_t msg;
911 
912  res.success = true;
913  return true;
914 }
915 
916 bool rosflightIO::calibrateRCTrimSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
917 {
918  mavlink_message_t msg;
921  res.success = true;
922  return true;
923 }
924 
926 {
928  {
929  param_timer_.stop();
930  ROS_INFO("Received all parameters");
931  }
932  else
933  {
935  ROS_ERROR("Received %d of %d parameters. Requesting missing parameters...",
937  }
938 }
939 
941 {
942  request_version();
943 }
944 
946 {
947  send_heartbeat();
948 }
949 
951 {
952  mavlink_message_t msg;
955 }
957 {
958  mavlink_message_t msg;
959  mavlink_msg_heartbeat_pack(1, 50, &msg, 0,0,0,0,0);
961 }
962 
963 void rosflightIO::check_error_code(uint8_t current, uint8_t previous, ROSFLIGHT_ERROR_CODE code, std::string name)
964 {
965  if ((current & code) != (previous & code))
966  {
967  if (current & code)
968  ROS_ERROR("Autopilot ERROR: %s", name.c_str());
969  else
970  ROS_INFO("Autopilot RECOVERED ERROR: %s", name.c_str());
971  }
972 }
973 
974 bool rosflightIO::calibrateAirspeedSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
975 {
976  mavlink_message_t msg;
979  res.success = true;
980  return true;
981 }
982 
983 bool rosflightIO::calibrateBaroSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
984 {
985  mavlink_message_t msg;
988  res.success = true;
989  return true;
990 }
991 
992 bool rosflightIO::rebootSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
993 {
994  mavlink_message_t msg;
997  res.success = true;
998  return true;
999 }
1000 
1001 bool rosflightIO::rebootToBootloaderSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
1002 {
1003  mavlink_message_t msg;
1006  res.success = true;
1007  return true;
1008 }
1009 
1010 } // namespace rosflight_io
void versionTimerCallback(const ros::TimerEvent &e)
void handle_small_mag_msg(const mavlink_message_t &msg)
bool save_to_file(std::string filename)
bool calibrateRCTrimSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
void register_param_listener(ParamListenerInterface *listener)
ros::Publisher twist_stamped_pub_
Definition: rosflight_io.h:177
#define ROS_FATAL(...)
void handle_diff_pressure_msg(const mavlink_message_t &msg)
ros::Publisher attitude_pub_
Definition: rosflight_io.h:180
ros::Publisher unsaved_params_pub_
Definition: rosflight_io.h:165
static constexpr float HEARTBEAT_PERIOD
Definition: rosflight_io.h:102
void handle_heartbeat_msg(const mavlink_message_t &msg)
ros::Publisher output_raw_pub_
Definition: rosflight_io.h:168
void publish(const boost::shared_ptr< M > &message) const
ros::ServiceServer calibrate_rc_srv_
Definition: rosflight_io.h:197
f
virtual const char * what() const
#define ROS_INFO_ONCE(...)
OFFBOARD_CONTROL_IGNORE
Definition: rosflight.h:99
virtual void handle_mavlink_message(const mavlink_message_t &msg)
The handler function for mavlink messages to be implemented by derived classes.
void handle_small_baro_msg(const mavlink_message_t &msg)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void getEulerYPR(tfScalar &yaw, tfScalar &pitch, tfScalar &roll, unsigned int solution_number=1) const
void handle_command_ack_msg(const mavlink_message_t &msg)
virtual void on_param_value_updated(std::string name, double value)
Called when an updated value is received for a parameter.
void handle_small_range_msg(const mavlink_message_t &msg)
void stop()
void check_error_code(uint8_t current, uint8_t previous, ROSFLIGHT_ERROR_CODE code, std::string name)
ros::Publisher baro_pub_
Definition: rosflight_io.h:172
virtual void on_params_saved_change(bool unsaved_changes)
Called when the status of whether there are unsaved parameters changes.
ros::ServiceServer reboot_srv_
Definition: rosflight_io.h:200
int bind_port
bool paramLoadFromFileCallback(rosflight_msgs::ParamFile::Request &req, rosflight_msgs::ParamFile::Response &res)
ros::Publisher nav_sat_fix_pub_
Definition: rosflight_io.h:176
void register_mavlink_listener(MavlinkListenerInterface *const listener)
Register a listener for mavlink messages.
geometry_msgs::Quaternion attitude_quat_
Definition: rosflight_io.h:207
void handle_attitude_quaternion_msg(const mavlink_message_t &msg)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void handle_statustext_msg(const mavlink_message_t &msg)
TFSIMD_FORCE_INLINE const tfScalar & y() const
void paramTimerCallback(const ros::TimerEvent &e)
#define ROS_WARN(...)
Describes an exception encountered while using the boost serial libraries.
bool calibrateBaroSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
void open()
Opens the port and begins communication.
void handle_status_msg(const mavlink_message_t &msg)
ros::Publisher status_pub_
Definition: rosflight_io.h:182
void handle_rosflight_output_raw_msg(const mavlink_message_t &msg)
mavrosflight::MavlinkComm * mavlink_comm_
Definition: rosflight_io.h:212
bool set_param_value(std::string name, double value)
void handle_named_value_int_msg(const mavlink_message_t &msg)
ros::Publisher lidar_pub_
Definition: rosflight_io.h:184
ros::Publisher sonar_pub_
Definition: rosflight_io.h:173
ros::Publisher time_reference_pub_
Definition: rosflight_io.h:178
void handle_small_imu_msg(const mavlink_message_t &msg)
ROSLIB_DECL std::string command(const std::string &cmd)
#define ROS_WARN_THROTTLE(period,...)
void handle_named_command_struct_msg(const mavlink_message_t &msg)
mavrosflight::MavROSflight * mavrosflight_
Definition: rosflight_io.h:213
#define ROS_INFO(...)
bool load_from_file(std::string filename)
ros::Publisher imu_temp_pub_
Definition: rosflight_io.h:167
bool param(const std::string &param_name, T &param_val, const T &default_val) const
bool paramGetSrvCallback(rosflight_msgs::ParamGet::Request &req, rosflight_msgs::ParamGet::Response &res)
static void quaternionTFToMsg(const Quaternion &bt, geometry_msgs::Quaternion &msg)
void heartbeatTimerCallback(const ros::TimerEvent &e)
bool rebootSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
ros::Time get_ros_time_ms(uint32_t boot_ms)
ros::ServiceServer param_set_srv_
Definition: rosflight_io.h:191
std::string getService() const
ROSFLIGHT_ERROR_CODE
Definition: rosflight.h:113
mavlink_rosflight_status_t prev_status_
Definition: rosflight_io.h:208
TFSIMD_FORCE_INLINE const tfScalar & x() const
ros::ServiceServer calibrate_baro_srv_
Definition: rosflight_io.h:198
void commandCallback(rosflight_msgs::Command::ConstPtr msg)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::Publisher version_pub_
Definition: rosflight_io.h:183
ros::Publisher error_pub_
Definition: rosflight_io.h:185
#define ROS_WARN_STREAM(args)
TFSIMD_FORCE_INLINE const tfScalar & z() const
void handle_named_value_float_msg(const mavlink_message_t &msg)
bool paramSetSrvCallback(rosflight_msgs::ParamSet::Request &req, rosflight_msgs::ParamSet::Response &res)
bool paramWriteSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
ros::Time get_ros_time_us(uint64_t boot_us)
bool get_param_value(std::string name, double *value)
OFFBOARD_CONTROL_MODE
Definition: rosflight.h:84
ros::Publisher diff_pressure_pub_
Definition: rosflight_io.h:170
bool calibrateImuBiasSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
void handle_hard_error_msg(const mavlink_message_t &msg)
void handle_version_msg(const mavlink_message_t &msg)
void handle_rc_channels_raw_msg(const mavlink_message_t &msg)
ros::ServiceServer imu_calibrate_bias_srv_
Definition: rosflight_io.h:195
ros::Publisher gnss_pub_
Definition: rosflight_io.h:174
static Time now()
T saturate(T value, T min, T max)
Definition: rosflight_io.h:154
ros::ServiceServer param_save_to_file_srv_
Definition: rosflight_io.h:193
ROSCPP_DECL void shutdown()
ros::Publisher euler_pub_
Definition: rosflight_io.h:181
ros::Subscriber command_sub_
Definition: rosflight_io.h:162
ros::ServiceServer calibrate_airspeed_srv_
Definition: rosflight_io.h:199
std::string getTopic() const
bool paramSaveToFileCallback(rosflight_msgs::ParamFile::Request &req, rosflight_msgs::ParamFile::Response &res)
std::map< std::string, ros::Publisher > named_value_int_pubs_
Definition: rosflight_io.h:186
void attitudeCorrectionCallback(geometry_msgs::Quaternion::ConstPtr msg)
void handle_rosflight_gnss_msg(const mavlink_message_t &msg)
ros::Publisher rc_raw_pub_
Definition: rosflight_io.h:169
bool rebootToBootloaderSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
ros::ServiceServer param_write_srv_
Definition: rosflight_io.h:192
virtual void on_new_param_received(std::string name, double value)
Called when a parameter is received from the autopilot for the first time.
#define ROS_ERROR(...)
ros::ServiceServer reboot_bootloader_srv_
Definition: rosflight_io.h:201
ros::ServiceServer param_get_srv_
Definition: rosflight_io.h:190
bool calibrateAirspeedSrvCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
void handle_rosflight_gnss_raw_msg(const mavlink_message_t &msg)
void send_message(const mavlink_message_t &msg)
Send a mavlink message.
std::map< std::string, ros::Publisher > named_command_struct_pubs_
Definition: rosflight_io.h:188
ros::Publisher gnss_raw_pub_
Definition: rosflight_io.h:175
ros::Subscriber attitude_sub_
Definition: rosflight_io.h:163
std::map< std::string, ros::Publisher > named_value_float_pubs_
Definition: rosflight_io.h:187
ros::ServiceServer param_load_from_file_srv_
Definition: rosflight_io.h:194
#define ROS_DEBUG(...)


rosflight
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 20:00:13