FlightController.cpp
Go to the documentation of this file.
1 #include "FlightController.hpp"
2 #include <iostream>
3 
4 namespace fcu {
5 
7  msp_version_(1),
8  control_source_(ControlSource::NONE),
9  msp_timer_(std::bind(&FlightController::generateMSP, this), 0.1) {}
10 
12 
13 bool FlightController::connect(const std::string &device, const size_t baudrate,
14  const double &timeout, const bool print_info) {
15  if(!client_.start(device, baudrate)) return false;
16 
18  if(client_.sendMessage(fcvar, timeout)) {
20  if(print_info) std::cout << fcvar;
21  }
22 
24  msp::msg::ApiVersion api_version(fw_variant_);
25  if(client_.sendMessage(api_version, timeout)) {
26  if(print_info) std::cout << api_version;
27  msp_version_ = api_version.major();
29  }
30  }
31 
32  if(print_info) {
34  if(client_.sendMessage(fcver, timeout)) {
35  std::cout << fcver;
36  }
37  }
38 
40  if(client_.sendMessage(boardinfo, timeout)) {
41  if(print_info) std::cout << boardinfo;
42  board_name_ = boardinfo.name();
43  }
44 
45  if(print_info) {
47  if(client_.sendMessage(buildinfo, timeout)) std::cout << buildinfo;
48  }
49 
51  client_.sendMessage(status, timeout);
52  if(print_info) std::cout << status;
53  sensors_ = status.sensors;
54 
56  client_.sendMessage(ident, timeout);
57  if(print_info) std::cout << ident;
58  capabilities_ = ident.capabilities;
59 
60  // get boxes
61  initBoxes();
62 
63  // determine channel mapping
65  // default mapping
66  for(uint8_t i(0); i < msp::msg::MAX_MAPPABLE_RX_INPUTS; ++i) {
67  channel_map_[i] = i;
68  }
69  }
70  else {
71  // get channel mapping from MSP_RX_MAP
73  client_.sendMessage(rx_map, timeout);
74  if(print_info) std::cout << rx_map;
75  channel_map_ = rx_map.map;
76  }
77 
78  return true;
79 }
80 
82 
84 
86  client_.setLoggingLevel(level);
87 }
88 
90  {
91  std::lock_guard<std::mutex> lock(msp_updates_mutex);
92  flight_mode_ = mode;
93  }
94  generateMSP();
95 }
96 
98 
100  if(source == control_source_) return;
101 
103  if(!client_.sendMessage(rxConfig))
104  std::cout << "client_.sendMessage(rxConfig) failed" << std::endl;
105  std::cout << rxConfig;
106 
107  msp::msg::SetRxConfig setRxConfig(fw_variant_);
108  static_cast<msp::msg::RxConfigSettings &>(setRxConfig) =
109  static_cast<msp::msg::RxConfigSettings &>(rxConfig);
110 
111  if(source == ControlSource::SBUS) {
112  setRxConfig.receiverType = 3;
113  setRxConfig.serialrx_provider = 2;
114  }
115  else if(source == ControlSource::MSP) {
116  setRxConfig.receiverType = 4;
117  }
118  client_.sendMessage(setRxConfig);
119 
120  control_source_ = source;
121 }
122 
125  client_.sendMessage(rxConfig);
126 
127  if(rxConfig.receiverType.set() && rxConfig.receiverType() == 4)
128  return ControlSource::MSP;
129  else if(rxConfig.serialrx_provider() == 2)
130  return ControlSource::SBUS;
131  return ControlSource::OTHER;
132 }
133 
134 void FlightController::setRPYT(std::array<double, 4> &&rpyt) {
135  {
136  std::lock_guard<std::mutex> lock(msp_updates_mutex);
137  rpyt_.swap(rpyt);
138  }
139  generateMSP();
140 }
141 
143  std::vector<uint16_t> cmds(6, 1000);
144  // manually remapping from RPYT to TAER (american RC)
145  // TODO: make this respect channel mapping
146  {
147  std::lock_guard<std::mutex> lock(msp_updates_mutex);
148  cmds[0] = uint16_t(rpyt_[3] * 500) + 1500;
149  cmds[1] = uint16_t(rpyt_[0] * 500) + 1500;
150  cmds[2] = uint16_t(rpyt_[1] * 500) + 1500;
151  cmds[3] = uint16_t(rpyt_[2] * 500) + 1500;
152 
153  if(!(uint32_t(flight_mode_.modifier) &
154  uint32_t(FlightMode::MODIFIER::ARM)))
155  cmds[4] = 1000;
156  else if(uint32_t(flight_mode_.secondary) &
158  cmds[4] = 2000;
159  else
160  cmds[4] = 1500;
161 
162  switch(flight_mode_.primary) {
164  cmds[5] = 1000;
165  break;
167  cmds[5] = 1500;
168  break;
170  cmds[5] = 2000;
171  break;
172  default:
173  break;
174  }
175  }
176  setRc(cmds);
177 }
178 
180  msp::msg::WriteEEPROM writeEEPROM(fw_variant_);
181  return client_.sendMessage(writeEEPROM);
182 }
183 
186  return client_.sendMessage(reboot);
187 }
188 
190  return fw_variant_;
191 }
192 
194 
195 std::string FlightController::getBoardName() const { return board_name_; }
196 
198  // get box names
199  msp::msg::BoxNames box_names(fw_variant_);
200  if(!client_.sendMessage(box_names))
201  throw std::runtime_error("Cannot get BoxNames!");
202 
203  // get box IDs
204  msp::msg::BoxIds box_ids(fw_variant_);
205  if(!client_.sendMessage(box_ids))
206  throw std::runtime_error("Cannot get BoxIds!");
207  assert(box_names.box_names.size() == box_ids.box_ids.size());
208 
209  box_name_ids_.clear();
210  for(size_t ibox(0); ibox < box_names.box_names.size(); ibox++) {
212  // workaround for wrong box ids in cleanflight
213  // cleanflight's box ids are in order of the box names
214  // https://github.com/cleanflight/cleanflight/issues/2606
215  box_name_ids_[box_names.box_names[ibox]] = ibox;
216  }
217  else {
218  box_name_ids_[box_names.box_names[ibox]] = box_ids.box_ids[ibox];
219  }
220  }
221 }
222 
223 bool FlightController::isStatusActive(const std::string &status_name,
224  const double &timeout) {
225  if(box_name_ids_.count(status_name) == 0) {
226  // box ids have not been initialised or requested status is unsupported
227  // by FC
228  throw std::runtime_error(
229  "Box ID of " + status_name +
230  " is unknown! You need to call 'initBoxes()' first.");
231  }
232 
234  client_.sendMessage(status, timeout);
235 
236  // check if ARM box id is amongst active box IDs
237  return status.box_mode_flags.count(box_name_ids_.at(status_name));
238 }
239 
240 bool FlightController::setRc(const uint16_t roll, const uint16_t pitch,
241  const uint16_t yaw, const uint16_t throttle,
242  const uint16_t aux1, const uint16_t aux2,
243  const uint16_t aux3, const uint16_t aux4,
244  const std::vector<uint16_t> auxs) {
246  // insert mappable channels
248  rc.channels[channel_map_[0]] = roll;
249  rc.channels[channel_map_[1]] = pitch;
250  rc.channels[channel_map_[2]] = yaw;
251  rc.channels[channel_map_[3]] = throttle;
252 
253  rc.channels.emplace_back(aux1);
254  rc.channels.emplace_back(aux2);
255  rc.channels.emplace_back(aux3);
256  rc.channels.emplace_back(aux4);
257 
258  // insert remaining aux channels
259  rc.channels.insert(std::end(rc.channels), std::begin(auxs), std::end(auxs));
260 
261  // send MSP_SET_RAW_RC without waiting for ACK
262  return client_.sendMessageNoWait(rc);
263 }
264 
265 bool FlightController::setRc(const std::vector<uint16_t> channels) {
267  rc.channels = channels;
268  return client_.sendMessageNoWait(rc);
269 }
270 
272  const std::array<uint16_t, msp::msg::N_MOTOR> &motor_values) {
274  motor.motor = motor_values;
275  return client_.sendMessage(motor);
276 }
277 
278 int FlightController::updateFeatures(const std::set<std::string> &add,
279  const std::set<std::string> &remove) {
280  // get original feature configuration
281  msp::msg::Feature feature_in(fw_variant_);
282  if(!client_.sendMessage(feature_in)) return -1;
283 
284  // update feature configuration
285  msp::msg::SetFeature feature_out(fw_variant_);
286  feature_out.features = feature_in.features;
287  // enable features
288  for(const std::string &a : add) {
289  feature_out.features.insert(a);
290  }
291  // disable features
292  for(const std::string &rem : remove) {
293  feature_out.features.erase(rem);
294  }
295 
296  // check if feature configuration changed
297  if(feature_out.features == feature_in.features) return 0;
298 
299  if(!client_.sendMessage(feature_out)) return -1;
300 
301  // make settings permanent and reboot
302  if(!saveSettings()) return -1;
303  if(!reboot()) return -1;
304 
305  return 1;
306 }
307 
308 } // namespace fcu
msp::FirmwareVariant fw_variant_
Cleanflight.
Definition: msp_msg.hpp:405
bool start(const std::string &device, const size_t baudrate=115200)
Start communications with a flight controller.
Definition: Client.cpp:34
Value< uint8_t > serialrx_provider
Definition: msp_msg.hpp:1201
int updateFeatures(const std::set< std::string > &add=std::set< std::string >(), const std::set< std::string > &remove=std::set< std::string >())
Enable and disable features on the FC To apply updates, changes will be written to the EEPROM and the...
Value< std::string > identifier
Definition: msp_msg.hpp:436
bool sendMessageNoWait(const msp::Message &message)
Send a message, but do not wait for any response.
Definition: Client.cpp:173
std::array< uint8_t, msp::msg::MAX_MAPPABLE_RX_INPUTS > channel_map_
std::array< uint16_t, N_MOTOR > motor
Definition: msp_msg.hpp:4543
bool disconnect()
Stops MSP control if active, and disconnects the internal Client object.
bool setVersion(const int &ver)
Change the device path on the next connect.
Definition: Client.cpp:20
bool saveSettings()
Sends message to flight controller to save all settings.
std::set< msp::msg::Capability > capabilities_
std::set< std::string > features
Definition: msp_msg.hpp:1048
void setLoggingLevel(const LoggingLevel &level)
Set the verbosity of the output.
Definition: Client.cpp:18
msp::client::Client client_
std::array< double, 4 > rpyt_
bool stop()
Stop communications with a flight controller.
Definition: Client.cpp:39
static const std::map< std::string, FirmwareVariant > variant_map
std::vector< uint16_t > channels
Definition: msp_msg.hpp:4272
void initBoxes()
Queries the flight controller for Box (flight mode) information.
FirmwareVariant
Enum of firmware variants.
ControlSource getControlSource()
Queries the currently active control source.
FlightController()
FlightController Constructor.
void setRPYT(std::array< double, 4 > &&rpyt)
Sets roll, pitch, yaw, and throttle values. They are sent immediately and stored for resending if aut...
bool isConnected() const
Tests connection to a flight controller.
void setFlightMode(const FlightMode mode)
Sets data structure with all flags governing flight mode.
MODIFIER modifier
Definition: FlightMode.hpp:49
Value< uint8_t > receiverType
Definition: msp_msg.hpp:1220
void setControlSource(const ControlSource source)
Sets which instruction source the flight controller should listen to. Also starts periodic MSP contro...
SECONDARY_MODE secondary
Definition: FlightMode.hpp:48
std::vector< std::string > box_names
Definition: msp_msg.hpp:3450
~FlightController()
~FlightController Destructor
std::set< std::string > features
Definition: msp_msg.hpp:1076
void setLoggingLevel(const msp::client::LoggingLevel &level)
Set the verbosity of the output.
static const size_t MAX_MAPPABLE_RX_INPUTS
Definition: msp_msg.hpp:313
FlightMode getFlightMode() const
Queries data structure with all flags governing flight mode.
bool setMotors(const std::array< uint16_t, msp::msg::N_MOTOR > &motor_values)
Directly sets motor values using SetMotor message.
std::set< msp::msg::Sensor > sensors_
std::set< size_t > box_mode_flags
Definition: msp_msg.hpp:2674
std::string getBoardName() const
Queries the currently set board name.
bool setRc(const uint16_t roll, const uint16_t pitch, const uint16_t yaw, const uint16_t throttle, const uint16_t aux1=1000, const uint16_t aux2=1000, const uint16_t aux3=1000, const uint16_t aux4=1000, const std::vector< uint16_t > auxs=std::vector< uint16_t >())
Set RC channels in order: roll, pitch, yaw, throttle by using channel mapping.
bool sendMessage(msp::Message &message, const double &timeout=0)
Send a message to the connected flight controller. If the message sends data to the flight controller...
Definition: Client.cpp:123
msp::FirmwareVariant getFwVariant() const
Queries the currently set firmware variant (Cleanflight, Betaflight, etc.)
void generateMSP()
Method used to generate the Rc message sent to the flight controller.
PRIMARY_MODE primary
Definition: FlightMode.hpp:47
bool reboot()
Starts message to flight controller signalling that it should reboot. Will result in the serial devic...
ByteVector box_ids
Definition: msp_msg.hpp:3537
bool isConnected() const
Query the system to see if a connection is active.
Definition: Client.cpp:71
bool set() const
Queries if the data has been set.
Definition: Value.hpp:53
bool connect(const std::string &device, const size_t baudrate=115200, const double &timeout=0.0, const bool print_info=false)
Connects to a physical flight controller, which includes connecting the internal Client object and qu...
std::map< std::string, size_t > box_name_ids_
Requests (1xx)
Definition: msp_msg.hpp:2590
int getProtocolVersion() const
Queries the currently set protocol (MSPv1 or MSPv2)
Response (2xx)
Definition: msp_msg.hpp:4267
bool isStatusActive(const std::string &status_name, const double &timeout=0)
Queries the flight controller to see if a status is active.


msp
Author(s): Christian Rauch
autogenerated on Tue Oct 6 2020 03:38:57