Qualcomm Navigator Flight Control Interface  2.0
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
flight_control_interface.hpp
1 /****************************************************************************
2  * Copyright (c) 2018 John A. Dougherty. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in
12  * the documentation and/or other materials provided with the
13  * distribution.
14  * 3. Neither the name ATLFlight nor the names of its contributors may be
15  * used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  * In addition Supplemental Terms apply. See the SUPPLEMENTAL file.
33  ****************************************************************************/
34 
35 
36 #ifndef SNAV_FCI_FLIGHT_CONTROL_INTERFACE_HPP_
37 #define SNAV_FCI_FLIGHT_CONTROL_INTERFACE_HPP_
38 
39 #include <atomic>
40 #include <condition_variable>
41 #include <cstdbool>
42 #include <mutex>
43 #include <string>
44 #include <thread>
45 
46 #include <Eigen/Geometry>
47 
48 #include "snav/snapdragon_navigator.h"
49 
50 #include "api/waypoint.hpp"
51 #include "api/config/landing_config.hpp"
52 #include "api/config/rx_config.hpp"
53 #include "api/config/takeoff_config.hpp"
54 #include "api/config/tx_config.hpp"
55 #include "api/config/waypoint_config.hpp"
56 #include "imp/inc/snav_cached_data_thread_safe.hpp"
57 #include "imp/inc/state_info.hpp"
58 #include "imp/inc/planner.hpp"
59 #include "imp/inc/transform.hpp"
60 #include "imp/inc/tx_command_thread_safe.hpp"
61 
66 namespace snav_fci
67 {
68 
81 {
82 public:
100  enum class Permissions
101  {
102  READ_WRITE,
105  READ_ONLY,
108  };
109 
116  enum class Return
117  {
118  SUCCESS,
119  FAILURE,
120  NOT_CONNECTED,
131  NO_LOCK,
133  };
134 
138  enum class Action
139  {
140  NONE,
141  TAKEOFF,
144  LAND,
145  };
146 
164  explicit FlightControlInterface(const Permissions& requested_access);
165 
172  ~FlightControlInterface() noexcept;
173 
192  Return configure_tx(const TxConfig& tx_config);
193 
210  Return configure_rx(const RxConfig& rx_config);
211 
226  void wait_for_configure() const noexcept;
227 
240  Return connect();
241 
247  Return disconnect() noexcept;
248 
268 
286  Return stop_props();
287 
311  Return takeoff(const TakeoffConfig& takeoff_config);
312 
316  Return takeoff();
317 
318 
331  Return takeoff_nb(const TakeoffConfig& takeoff_config);
332 
336  Return takeoff_nb();
337 
362  Return land(const LandingConfig& landing_config);
363 
367  Return land();
368 
381  Return land_nb(const LandingConfig& landing_config);
382 
386  Return land_nb();
387 
409  Return go_to_waypoint(const Waypoint& waypoint);
410 
423  Return go_to_waypoint_nb(const Waypoint& waypoint);
424 
438  Return configure_planner(const PlannerConfig& config);
439 
455  Return preload_waypoints(const std::vector<Waypoint>& waypoints);
456 
476  Return compute_trajectory(StateVector starting_state);
477 
513  Return execute_mission(const double t_start = 0);
514 
527  Return execute_mission_nb(const double t_start = 0);
528 
539  void wait_on_action() const noexcept;
540 
550  Permissions get_permissions() const noexcept;
551 
561  Return get_last_action_result() const noexcept;
562 
572  Action get_last_action() const noexcept;
573 
583  Action get_current_action() const noexcept;
584 
599  Return get_current_trajectory(std::vector<snav_traj_gen::SnavTrajectory>& traj) const;
600 
619  Return get_last_optimized_trajectory(std::vector<snav_traj_gen::SnavTrajectory>& traj) const;
620 
635  Return get_waypoints(std::vector<Waypoint>& waypoints) const;
636 
654  Return get_optimized_waypoints(std::vector<Waypoint>& waypoints) const;
655 
665  Planner::Status get_planner_status() const;
666 
679  float get_trajectory_time() const;
680 
703  Return set_waypoint_frame_tf(const Eigen::Quaternionf& q_pw,
704  const Eigen::Vector3f& t_pw);
705 
723  Return get_waypoint_frame_tf(Eigen::Quaternionf& q_pw,
724  Eigen::Vector3f& t_pw) const;
725 
744  Return set_tx_command(const TxCommand& command);
745 
757  SnavCachedData get_snav_cached_data() const;
758 
773  StateVector get_estimated_state(const SnavCachedData& snav_data) const;
774 
789  StateVector get_desired_state(const SnavCachedData& snav_data) const;
790 
815  Return convert_velocity_to_rc_command(const std::array<float, 3> velocity,
816  const float yaw_rate, RcCommand& rc_command);
817 
821  static void preempt_current_action();
822 
837  inline static void set_verbosity(bool verbose)
838  {
839  verbose_ = verbose;
840  }
841 
845  inline static bool tx_ok()
846  {
847  return tx_ok_;
848  }
849 
853  inline static bool rx_ok()
854  {
855  return rx_ok_;
856  }
857 
861  inline static bool ok()
862  {
863  return rx_ok_ && tx_ok_;
864  }
865 
877  static std::string get_return_as_string(Return ret_code);
878 
879 private:
880 
881  // Disallow copy and assign
883  FlightControlInterface& operator=(const FlightControlInterface&) = delete;
884 
888  static void tx_loop();
889  static void update_waypoint_frame_parent_transform();
890  static void send_tx_command();
891  static void rx_loop();
892  static void check_tx_conditions();
893  static float constrain_min_max(float input, const float min, const float max);
894  static bool has_closed_loop_position_control(SnRcCommandType);
895  static void print_error(const std::string& message);
896  static void print_error(const std::string& origin, const std::string& message);
897  static void print_warning(const std::string& message);
898  static void print_warning(const std::string& origin, const std::string& message);
899  static void print_info(const std::string& message);
900  static void print_message(const std::string& prefix, const std::string& origin,
901  const std::string& message);
902  static void enter_action(Action action);
903  static void exit_action(const Return& ret_code);
904 
908  void enforce_init_precondition() const;
909  void enforce_connected_precondition() const;
910  void enforce_write_precondition() const;
911  void enforce_in_flight_precondition() const;
912  void enforce_no_action_in_progress_precondition() const;
913  void enforce_tx_connection_invariant() const;
914  int infer_metadata_from_mode(const SnMode, const bool, TxCommand::Mode&, SnInputCommandType&,
915  SnRcCommandType&);
916  void enforce_props_state_constraint(const SnPropsState);
917  void do_not_enforce_props_state_constraint();
918  void update_tx_command_pos_ctrl();
919  Return takeoff_impl(std::unique_lock<std::mutex>& lock, const TakeoffConfig& config);
920  Return land_impl(std::unique_lock<std::mutex>& lock, const LandingConfig& config);
921  Return go_to_waypoint_impl(std::unique_lock<std::mutex>& lock, const Waypoint& wp);
922  Return execute_mission_impl(std::unique_lock<std::mutex>& lock, const double t_start);
923  Return execute_planner(std::unique_lock<std::mutex>& lock, const double t_start = 0);
924 
925  // wrappers around functions to catch exceptions; safe for threads
926  void takeoff_safe() noexcept;
927  void takeoff_safe(const TakeoffConfig&) noexcept;
928  void land_safe() noexcept;
929  void land_safe(const LandingConfig&) noexcept;
930  void go_to_waypoint_safe(const Waypoint&) noexcept;
931  void execute_mission_safe(const double t_start) noexcept;
932 
936  static std::mutex connection_mutex_;
937  static std::mutex command_mutex_;
938  static TxConfig tx_config_;
939  static bool configured_tx_;
940  static RxConfig rx_config_;
941  static bool configured_rx_;
942  static std::condition_variable configured_rx_cv_;
943  static TxCommandThreadSafe tcts_;
944  static TransformThreadSafe tf_ep_; // ESTIMATION <-> (parent of WAYPOINT)
945  static TransformThreadSafe tf_pw_; // (parent of WAYPOINT) <-> WAYPOINT
946  static TransformThreadSafe tf_ev_; // ESTIMATION <-> snav VIO frame
947  static StateVector desired_setpoint_wrt_e_; // Desired state w.r.t. ESTIMATION
948  static StateVector desired_setpoint_wrt_w_; // Desired state w.r.t. WAYPOINT
949  static SnavCachedDataThreadSafe scdts_;
950  static StateInfoThreadSafe sits_;
951  static std::thread tx_thread_;
952  static std::atomic_bool tx_ok_;
953  static std::thread rx_thread_;
954  static std::atomic_bool rx_ok_;
955  static bool write_access_taken_;
956  static int num_connections_;
957  static std::atomic_bool verbose_;
958  // system_clock is used here instead of steady_clock so that an absolute
959  // timestamp relative to the wall clock can be provided to the execute
960  // mission function, which is useful for synchronizing multiple robots. Also,
961  // system_clock may be continually adjusted to maintain synchronization among
962  // a multi-robot system where clock drift may be significant over the course
963  // of a mission. However, stepping the system_clock during a mission could
964  // cause undefined behavior. Be careful! It may make sense to make this
965  // configurable and only use system_clock if the absolute time sync is
966  // required.
967  static std::chrono::time_point<std::chrono::system_clock> t0_;
968  static std::mutex time_mutex_;
969  static Planner planner_;
970  static std::thread action_thread_;
971  static std::atomic<Action> current_action_;
972  static std::atomic<Action> last_action_;
973  static std::atomic<Return> last_action_result_;
974  static std::atomic_bool kill_current_action_;
975  static std::condition_variable action_cv_;
976  static std::mutex action_mutex_;
977 
981  std::atomic_bool connected_;
982  std::atomic<Permissions> permissions_;
983 
984 };
985 
986 } // namespace snav_fci
987 
988 #endif // SNAV_FCI_FLIGHT_CONTROL_INTERFACE_HPP_
989 
~FlightControlInterface() noexcept
Destructor of FlightControlInterface.
Return stop_props()
Blocking call to stop the propellers.
Structure containing options for the Planner.
Definition: planner_config.hpp:44
Return compute_trajectory(StateVector starting_state)
Compute a trajectory through the given waypoints.
Return go_to_waypoint_nb(const Waypoint &waypoint)
Non-blocking call to go to specified waypoint.
Interface to the Qualcomm Navigator Flight Controller.
Definition: flight_control_interface.hpp:80
static std::string get_return_as_string(Return ret_code)
Convert a Return code to a string.
Return convert_velocity_to_rc_command(const std::array< float, 3 > velocity, const float yaw_rate, RcCommand &rc_command)
Convert metric velocity command into an RcCommand suitable for sending to the flight controller based...
Structure containing the inputs to the sn_send_rc_command() Qualcomm Navigator API function...
Definition: rc_command.hpp:51
Return go_to_waypoint(const Waypoint &waypoint)
Blocking call to go to specified waypoint.
Return set_tx_command(const TxCommand &command)
Directly set the command being sent to the flight controller.
void wait_on_action() const noexcept
Wait for the currently-executing action to complete.
static bool ok()
Whether or not read and write access to Qualcomm Navigator is ok.
Definition: flight_control_interface.hpp:861
void wait_for_configure() const noexcept
Block until FlightControlInterface has been configured.
Definition: tx_command.hpp:41
Return disconnect() noexcept
End connection to Qualcomm Navigator.
SnavCachedData get_snav_cached_data() const
Get a copy of the latest data from the cache.
float get_trajectory_time() const
Get the current trajectory time.
Return get_optimized_waypoints(std::vector< Waypoint > &waypoints) const
Get the optimized waypoints.
Return get_last_action_result() const noexcept
Get the result of the most recently executed action.
Return configure_planner(const PlannerConfig &config)
Specify the configuration options for the planner.
Return start_props()
Blocking call to start the propellers.
Return get_waypoints(std::vector< Waypoint > &waypoints) const
Get the input waypoints.
static void set_verbosity(bool verbose)
Set verbosity of FlightControlInterface.
Definition: flight_control_interface.hpp:837
Return get_current_trajectory(std::vector< snav_traj_gen::SnavTrajectory > &traj) const
Get the current trajectory.
Return execute_mission(const double t_start=0)
Execute the trajectory-following mission.
StateVector get_desired_state(const SnavCachedData &snav_data) const
Get the desired state as a StateVector with respect to ReferenceFrame::WAYPOINT from the SnavCachedDa...
Return preload_waypoints(const std::vector< Waypoint > &waypoints)
Load a vector of waypoints.
static void preempt_current_action()
Send preempt signal to currently-executing action.
Return execute_mission_nb(const double t_start=0)
Non-blocking call to execute the trajectory-following mission.
Action get_last_action() const noexcept
Get the most recently executed action.
Structure containing position and yaw along with their derivatives and some metadata.
Definition: waypoint.hpp:52
Return get_waypoint_frame_tf(Eigen::Quaternionf &q_pw, Eigen::Vector3f &t_pw) const
Get the transform between ReferenceFrame::WAYPOINT and its parent.
Structure containing position and yaw along with their derivatives.
Definition: state_vector.hpp:50
Return connect()
Establish connection to Qualcomm Navigator.
Action get_current_action() const noexcept
Get the currently-executing action.
Return configure_tx(const TxConfig &tx_config)
Specify configuration options for sending commands to Qualcomm Navigator.
Action
Enum used for possible actions.
Definition: flight_control_interface.hpp:138
StateVector get_estimated_state(const SnavCachedData &snav_data) const
Get the estimated state as a StateVector with respect to ReferenceFrame::WAYPOINT from the SnavCached...
FlightControlInterface(const Permissions &requested_access)
Constructs an instance of FlightControlInterface.
static bool tx_ok()
Whether or not write access to Qualcomm Navigator is ok.
Definition: flight_control_interface.hpp:845
Return set_waypoint_frame_tf(const Eigen::Quaternionf &q_pw, const Eigen::Vector3f &t_pw)
Updates the transform between ReferenceFrame::WAYPOINT and its parent.
Planner::Status get_planner_status() const
Get the current status of the Planner.
Permissions get_permissions() const noexcept
Return the permissions of this object.
Return configure_rx(const RxConfig &rx_config)
Specify configuration options for receiving data from Qualcomm Navigator.
Structure containing options for takeoff.
Definition: takeoff_config.hpp:46
Structure containing options for the TX thread.
Definition: tx_config.hpp:46
Structure containing options for the RX thread.
Definition: rx_config.hpp:44
Structure containing options for landing.
Definition: landing_config.hpp:46
Permissions
Defines the permissions of an instance of FlightControlInterface.
Definition: flight_control_interface.hpp:100
Return get_last_optimized_trajectory(std::vector< snav_traj_gen::SnavTrajectory > &traj) const
Get the last optimized trajectory.
static bool rx_ok()
Whether or not read access to Qualcomm Navigator is ok.
Definition: flight_control_interface.hpp:853
Return
Return codes for FlightControlInterface.
Definition: flight_control_interface.hpp:116