rc_io.cpp
Go to the documentation of this file.
00001 
00009 /*
00010  * Copyright 2014 Vladimir Ermakov.
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 3 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful, but
00018  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00019  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00020  * for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License along
00023  * with this program; if not, write to the Free Software Foundation, Inc.,
00024  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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         /* -*- rx handlers -*- */
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                 /* if we receive RC_CHANNELS, drop RC_CHANNELS_RAW */
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         /* -*- low-level send functions -*- */
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         /* -*- callbacks -*- */
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 }; // namespace mavplugin
00236 
00237 PLUGINLIB_EXPORT_CLASS(mavplugin::RCIOPlugin, mavplugin::MavRosPlugin)
00238 


mavros
Author(s): Vladimir Ermakov
autogenerated on Wed Aug 26 2015 12:29:13