FlightController.cpp
Go to the documentation of this file.
00001 #include "FlightController.hpp"
00002 
00003 #include <iostream>
00004 
00005 namespace fcu {
00006 
00007 FlightController::FlightController(const std::string &device, const uint baudrate) {
00008     client.connect(device, baudrate);
00009     client.start();
00010 }
00011 
00012 FlightController::~FlightController() {
00013     client.stop();
00014 }
00015 
00016 void FlightController::waitForConnection() {
00017     std::cout<<"Wait for FC..."<<std::endl;
00018     msp::msg::Ident ident;
00019     while(!client.request(ident, 0.5));
00020     std::cout<<"MultiWii version "<<uint(ident.version)<<" ready"<<std::endl;
00021 }
00022 
00023 void FlightController::initialise() {
00024     // wait for connection to be established
00025     while(client.request(ident, 0.5)==-1);
00026 
00027     msp::msg::ApiVersion api;
00028     if(client.request(api)) {
00029         // this is Cleanflight
00030         firmware = FirmwareType::CLEANFLIGHT;
00031         std::cout<<"Cleanflight API "<<api.major<<"."<<api.minor<<"."<<api.protocol<<" ready"<<std::endl;
00032     }
00033     else {
00034         // this is MultiWii
00035         firmware = FirmwareType::MULTIWII;
00036         std::cout<<"MultiWii version "<<uint(ident.version)<<" ready"<<std::endl;
00037     }
00038 
00039     // get sensors
00040     msp::msg::Status status;
00041     client.request(status);
00042     sensors = status.sensors;
00043 
00044     // get boxes
00045     initBoxes();
00046 
00047     // determine channel mapping
00048     if(isFirmwareMultiWii()) {
00049         // default mapping
00050         channel_map.clear();
00051         for(uint8_t i(0); i<MAX_MAPPABLE_RX_INPUTS; i++) {
00052             channel_map.push_back(i);
00053         }
00054     }
00055     else {
00056         // get channel mapping from MSP_RX_MAP
00057         msp::msg::RxMap rx_map;
00058         client.request(rx_map);
00059         channel_map = rx_map.map;
00060     }
00061 }
00062 
00063 bool FlightController::isFirmware(const FirmwareType firmware_type) {
00064     return firmware == firmware_type;
00065 }
00066 
00067 void FlightController::initBoxes() {
00068     client.setPrintWarnings(true);
00069     // get box names
00070     msp::msg::BoxNames box_names;
00071     if(!client.request(box_names))
00072         throw std::runtime_error("Cannot get BoxNames!");
00073 
00074     // get box IDs
00075     msp::msg::BoxIds box_ids;
00076     if(!client.request(box_ids))
00077         throw std::runtime_error("Cannot get BoxIds!");
00078 
00079     assert(box_names.box_names.size()==box_ids.box_ids.size());
00080 
00081     box_name_ids.clear();
00082     for(uint ibox(0); ibox<box_names.box_names.size(); ibox++) {
00083         if(isFirmwareCleanflight()) {
00084             // workaround for wrong box ids in cleanflight
00085             // cleanflight's box ids are in order of the box names
00086             // https://github.com/cleanflight/cleanflight/issues/2606
00087             box_name_ids[box_names.box_names[ibox]] = ibox;
00088         }
00089         else {
00090             box_name_ids[box_names.box_names[ibox]] = box_ids.box_ids[ibox];
00091         }
00092     }
00093     client.setPrintWarnings(false);
00094 }
00095 
00096 bool FlightController::isStatusActive(const std::string& status_name) {
00097     if(box_name_ids.count(status_name)==0) {
00098         // box ids have not been initialised or requested status is unsupported by FC
00099         throw std::runtime_error("Box ID of "+status_name+" is unknown! You need to call 'initBoxes()' first.");
00100     }
00101 
00102     msp::msg::Status status;
00103     client.request(status);
00104 
00105     // check if ARM box id is amongst active box IDs
00106     return status.active_box_id.count(box_name_ids.at(status_name));
00107 }
00108 
00109 bool FlightController::setRc(const uint16_t roll, const uint16_t pitch,
00110                              const uint16_t yaw, const uint16_t throttle,
00111                              const uint16_t aux1, const uint16_t aux2,
00112                              const uint16_t aux3, const uint16_t aux4,
00113                              const std::vector<uint16_t> auxs)
00114 {
00115     if(isFirmwareMultiWii() && hasDynBal()) {
00116         throw std::runtime_error(
00117             "DYNBALANCE is active!\n"
00118             "RC commands will have no effect on motors.");
00119     }
00120 
00121     msp::msg::SetRc rc;
00122     // insert mappable channels
00123     rc.channels.resize(MAX_MAPPABLE_RX_INPUTS);
00124     rc.channels[channel_map[0]] = roll;
00125     rc.channels[channel_map[1]] = pitch;
00126     rc.channels[channel_map[2]] = yaw;
00127     rc.channels[channel_map[3]] = throttle;
00128     rc.channels[channel_map[4]] = aux1;
00129     rc.channels[channel_map[5]] = aux2;
00130     rc.channels[channel_map[6]] = aux3;
00131     rc.channels[channel_map[7]] = aux4;
00132 
00133     // insert remaining aux channels
00134     rc.channels.insert(std::end(rc.channels), std::begin(auxs), std::end(auxs));
00135 
00136     // send MSP_SET_RAW_RC without waiting for ACK
00137     return client.respond(rc, false);
00138 }
00139 
00140 bool FlightController::setRc(const std::vector<uint16_t> channels) {
00141     msp::msg::SetRc rc;
00142     rc.channels = channels;
00143     return client.respond(rc, false);
00144 }
00145 
00146 bool FlightController::setMotors(const std::array<uint16_t,msp::msg::N_MOTOR> &motor_values) {
00147     if(isFirmwareMultiWii() && !hasDynBal()) {
00148         throw std::runtime_error(
00149             "DYNBALANCE is not active!\n"
00150             "Set '#define DYNBALANCE' in your MultiWii 'config.h'");
00151     }
00152 
00153     msp::msg::SetMotor motor;
00154     motor.motor = motor_values;
00155     return client.respond(motor);
00156 }
00157 
00158 bool FlightController::arm(const bool arm) {
00159     // arm:
00160     // throttle: 1000 (bottom), yaw: 2000 (right)
00161     // disarm:
00162     // throttle: 1000 (bottom), yaw: 1000 (left)
00163 
00164     const uint16_t yaw = arm ? 2000 : 1000;
00165 
00166     return setRc(1500, 1500, yaw, 1000, 1000, 1000, 1000, 1000);
00167 }
00168 
00169 bool FlightController::arm_block() {
00170     // attempt to arm while FC is disarmed
00171     while(isArmed()==false) {
00172         arm(true);
00173         std::this_thread::sleep_for(std::chrono::milliseconds(1));
00174     }
00175     return true;
00176 }
00177 
00178 bool FlightController::disarm_block() {
00179     // attempt to disarm while FC is armed
00180     while(isArmed()==true) {
00181         arm(false);
00182         std::this_thread::sleep_for(std::chrono::milliseconds(1));
00183     }
00184     return true;
00185 }
00186 
00187 int FlightController::updateFeatures(const std::set<std::string> &add,
00188                                      const std::set<std::string> &remove)
00189 {
00190     // get original feature configuration
00191     msp::msg::Feature feature_in;
00192     if(!client.request(feature_in))
00193         return -1;
00194 
00195     // update feature configuration
00196     msp::msg::SetFeature feature_out;
00197     feature_out.features = feature_in.features;
00198     // enable features
00199     for(const std::string &a : add) {
00200         feature_out.features.insert(a);
00201     }
00202     // disable features
00203     for(const std::string &rem : remove) {
00204         feature_out.features.erase(rem);
00205     }
00206 
00207     // check if feature configuration changed
00208     if(feature_out.features==feature_in.features)
00209         return 0;
00210 
00211     if(!client.respond(feature_out))
00212         return -1;
00213 
00214     // make settings permanent and reboot
00215     if(!writeEEPROM())
00216         return -1;
00217     if(!reboot())
00218         return -1;
00219 
00220     return 1;
00221 }
00222 
00223 bool FlightController::reboot() {
00224     return client.respond(msp::msg::Reboot());
00225 }
00226 
00227 bool FlightController::writeEEPROM() {
00228     return client.respond(msp::msg::WriteEEPROM());
00229 }
00230 
00231 } // namespace msp


msp
Author(s): Christian Rauch
autogenerated on Mon Oct 9 2017 03:02:13