00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <mavros/mavros_plugin.h>
00028 #include <pluginlib/class_list_macros.h>
00029
00030 #include <mavros/RCIn.h>
00031 #include <mavros/RCOut.h>
00032 #include <mavros/OverrideRCIn.h>
00033
00034 namespace mavplugin {
00035
00039 class RCIOPlugin : public MavRosPlugin {
00040 public:
00041 RCIOPlugin() :
00042 uas(nullptr),
00043 raw_rc_in(0),
00044 raw_rc_out(0),
00045 has_rc_channels_msg(false)
00046 { };
00047
00048 void initialize(UAS &uas_,
00049 ros::NodeHandle &nh,
00050 diagnostic_updater::Updater &diag_updater)
00051 {
00052 uas = &uas_;
00053
00054 rc_nh = ros::NodeHandle(nh, "rc");
00055 rc_in_pub = rc_nh.advertise<mavros::RCIn>("in", 10);
00056 rc_out_pub = rc_nh.advertise<mavros::RCOut>("out", 10);
00057 override_sub = rc_nh.subscribe("override", 10, &RCIOPlugin::override_cb, this);
00058
00059 uas->sig_connection_changed.connect(boost::bind(&RCIOPlugin::connection_cb, this, _1));
00060 };
00061
00062 std::string const get_name() const {
00063 return "RCIO";
00064 };
00065
00066 const message_map get_rx_handlers() {
00067 return {
00068 MESSAGE_HANDLER(MAVLINK_MSG_ID_RC_CHANNELS_RAW, &RCIOPlugin::handle_rc_channels_raw),
00069 MESSAGE_HANDLER(MAVLINK_MSG_ID_RC_CHANNELS, &RCIOPlugin::handle_rc_channels),
00070 MESSAGE_HANDLER(MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, &RCIOPlugin::handle_servo_output_raw),
00071 };
00072 }
00073
00074 private:
00075 std::recursive_mutex mutex;
00076 UAS *uas;
00077
00078 std::vector<uint16_t> raw_rc_in;
00079 std::vector<uint16_t> raw_rc_out;
00080 bool has_rc_channels_msg;
00081
00082 ros::NodeHandle rc_nh;
00083 ros::Publisher rc_in_pub;
00084 ros::Publisher rc_out_pub;
00085 ros::Subscriber override_sub;
00086
00087
00088
00089 void handle_rc_channels_raw(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
00090 mavlink_rc_channels_raw_t port;
00091 mavlink_msg_rc_channels_raw_decode(msg, &port);
00092 lock_guard lock(mutex);
00093
00094
00095 if (has_rc_channels_msg)
00096 return;
00097
00098 size_t offset = port.port * 8;
00099 if (raw_rc_in.size() < offset + 8)
00100 raw_rc_in.resize(offset + 8);
00101
00102 #define SET_RC_IN(mavidx) \
00103 raw_rc_in[offset + mavidx - 1] = port.chan ## mavidx ## _raw
00104 SET_RC_IN(1);
00105 SET_RC_IN(2);
00106 SET_RC_IN(3);
00107 SET_RC_IN(4);
00108 SET_RC_IN(5);
00109 SET_RC_IN(6);
00110 SET_RC_IN(7);
00111 SET_RC_IN(8);
00112 #undef SET_RC_IN
00113
00114 mavros::RCInPtr rcin_msg = boost::make_shared<mavros::RCIn>();
00115
00116 rcin_msg->header.stamp = ros::Time::now();
00117 rcin_msg->rssi = port.rssi;
00118 rcin_msg->channels = raw_rc_in;
00119
00120 rc_in_pub.publish(rcin_msg);
00121 }
00122
00123 void handle_rc_channels(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
00124 mavlink_rc_channels_t channels;
00125 mavlink_msg_rc_channels_decode(msg, &channels);
00126 lock_guard lock(mutex);
00127
00128 ROS_INFO_COND_NAMED(!has_rc_channels_msg, "rc", "RC_CHANNELS message detected!");
00129 has_rc_channels_msg = true;
00130
00131 if (channels.chancount > 18) {
00132 raw_rc_in.resize(18);
00133 ROS_WARN_THROTTLE_NAMED(60, "rc",
00134 "FCU receives %u RC channels, but RC_CHANNELS can store 18",
00135 channels.chancount);
00136 }
00137 else
00138 raw_rc_in.resize(channels.chancount);
00139
00140 #define IFSET_RC_IN(mavidx) \
00141 if (channels.chancount >= mavidx) \
00142 raw_rc_in[mavidx-1] = channels.chan ## mavidx ## _raw
00143 IFSET_RC_IN(1);
00144 IFSET_RC_IN(2);
00145 IFSET_RC_IN(3);
00146 IFSET_RC_IN(4);
00147 IFSET_RC_IN(5);
00148 IFSET_RC_IN(6);
00149 IFSET_RC_IN(7);
00150 IFSET_RC_IN(8);
00151 IFSET_RC_IN(9);
00152 IFSET_RC_IN(10);
00153 IFSET_RC_IN(11);
00154 IFSET_RC_IN(12);
00155 IFSET_RC_IN(13);
00156 IFSET_RC_IN(14);
00157 IFSET_RC_IN(15);
00158 IFSET_RC_IN(16);
00159 IFSET_RC_IN(17);
00160 IFSET_RC_IN(18);
00161 #undef IFSET_RC_IN
00162
00163 mavros::RCInPtr rcin_msg = boost::make_shared<mavros::RCIn>();
00164
00165 rcin_msg->header.stamp = ros::Time::now();
00166 rcin_msg->rssi = channels.rssi;
00167 rcin_msg->channels = raw_rc_in;
00168
00169 rc_in_pub.publish(rcin_msg);
00170 }
00171
00172 void handle_servo_output_raw(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
00173 mavlink_servo_output_raw_t port;
00174 mavlink_msg_servo_output_raw_decode(msg, &port);
00175 lock_guard lock(mutex);
00176
00177 size_t offset = port.port * 8;
00178 if (raw_rc_out.size() < offset + 8)
00179 raw_rc_out.resize(offset + 8);
00180
00181 #define SET_RC_OUT(mavidx) \
00182 raw_rc_out[offset + mavidx - 1] = port.servo ## mavidx ## _raw
00183 SET_RC_OUT(1);
00184 SET_RC_OUT(2);
00185 SET_RC_OUT(3);
00186 SET_RC_OUT(4);
00187 SET_RC_OUT(5);
00188 SET_RC_OUT(6);
00189 SET_RC_OUT(7);
00190 SET_RC_OUT(8);
00191 #undef SET_RC_OUT
00192
00193 mavros::RCOutPtr rcout_msg = boost::make_shared<mavros::RCOut>();
00194
00195 rcout_msg->header.stamp = ros::Time::now();
00196 rcout_msg->channels = raw_rc_out;
00197
00198 rc_out_pub.publish(rcout_msg);
00199 }
00200
00201
00202
00203 void rc_channels_override(const boost::array<uint16_t, 8> &channels) {
00204 mavlink_message_t msg;
00205
00206 mavlink_msg_rc_channels_override_pack_chan(UAS_PACK_CHAN(uas), &msg,
00207 UAS_PACK_TGT(uas),
00208 channels[0],
00209 channels[1],
00210 channels[2],
00211 channels[3],
00212 channels[4],
00213 channels[5],
00214 channels[6],
00215 channels[7]
00216 );
00217 UAS_FCU(uas)->send_message(&msg);
00218 }
00219
00220
00221
00222 void connection_cb(bool connected) {
00223 lock_guard lock(mutex);
00224 raw_rc_in.clear();
00225 raw_rc_out.clear();
00226 has_rc_channels_msg = false;
00227 }
00228
00229 void override_cb(const mavros::OverrideRCIn::ConstPtr req) {
00230
00231 rc_channels_override(req->channels);
00232 }
00233 };
00234
00235 };
00236
00237 PLUGINLIB_EXPORT_CLASS(mavplugin::RCIOPlugin, mavplugin::MavRosPlugin)
00238