Commit 4abb2f6e authored by Gus Grubba's avatar Gus Grubba

Merge commit 'ebb5b8ce' into Airmap

* commit 'ebb5b8ce': (40 commits)
  Including airmapd into the repo (macOS only)
  Restore expanded state when enabling AirMap
  AirMap Settings
  Control on Fly View Eliminated flight widget "states" Define flight widget top margin (plugin options)
  Add expand icon
  Expand/Colapse Controllers Adjust colors Remove unused image
  Initial Mockup
  qgroundcontrol.pro: update build to latest airmapd master
  AirMapManager: update authorizations to changed airmapd interface
  rebase fixup: remove AirMapController.{cc,h}
  remove submodule commits qmqtt and tiny-AES128-C
  AirMapManager: error handling, change to updated API of airmapd
  AirMapManager: update polygons to changed airmapd interface
  AirMapManager: update flight search according to updated airmapd
  AirMap: remove SITA registration numbers
  AirspaceManagement & AirMapManager: add weather request API
  AirMapManager: add LifetimeChecker class to prevent callbacks from accessing invalid memory
  AirMapManager: handle multi_polygon
  AirMapManager: change backend to use airmapd
  AirMap: refactor for multi-vehicle support & base class API
  ...
parents 55fafa52 ebb5b8ce
......@@ -124,3 +124,24 @@ contains (DEFINES, DISABLE_ZEROCONF) {
message("Skipping support for Zeroconf (unsupported platform)")
}
#
# [OPTIONAL] AirMap Support
#
contains (DEFINES, DISABLE_AIRMAP) {
message("Skipping support for AirMap (manual override from command line)")
# Otherwise the user can still disable this feature in the user_config.pri file.
} else:exists(user_config.pri):infile(user_config.pri, DEFINES, DISABLE_AIRMAP) {
message("Skipping support for AirMap (manual override from user_config.pri)")
} else {
AIRMAPD_PATH = $$PWD/libs/airmapd
INCLUDEPATH += \
$${AIRMAPD_PATH}/include
MacBuild|iOSBuild {
message("Including support for AirMap")
LIBS += -L$${AIRMAPD_PATH}/macOS/Qt.5.9 -lairmap-qt
DEFINES += QGC_AIRMAP_ENABLED
} else {
message("Skipping support for Airmap (unsupported platform)")
}
}
#ifndef AIRMAP_AIRCRAFT_H_
#define AIRMAP_AIRCRAFT_H_
#include <string>
namespace airmap {
/// Aircraft describes an aircraft in terms of its model and its manufacturer.
struct Aircraft {
/// Model bundles up a model id and a product name.
struct Model {
std::string id; ///< The unique id of the model in the context of AirMap.
std::string name; ///< The human-readable name of the model.
};
/// Manufacturer bundles up an id and a human-readable name.
/// Please note that the id is only unique/relevant in the context of the
/// AirMap services.
struct Manufacturer {
std::string id; ///< The unique id of the manufacturer in the context of AirMap.
std::string name; ///< The human-readable name of the manufacturer.
};
Model model; ///< Details describing the model of an aircraft.
Manufacturer manufacturer; ///< Details about the manufacturer of an aircraft.
};
} // namespace airmap
#endif // AIRMAP_AIRCRAFT_H_
#ifndef AIRMAP_AIRCRAFTS_H_
#define AIRMAP_AIRCRAFTS_H_
#include <airmap/aircraft.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/optional.h>
#include <airmap/outcome.h>
#include <functional>
#include <string>
#include <vector>
namespace airmap {
/// Aircrafts models access to a database of aircraft models (specifically drones)
/// and manufacturers.
class Aircrafts : DoNotCopyOrMove {
public:
/// Manufacturers groups together types to ease interaction with
/// Aircrafts::manufacturers.
struct Manufacturers {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<std::string> manufacturer_name; ///< Search for the specific manufacturer with this name.
};
/// Result models the outcome of calling Flights::manufacturers.
using Result = Outcome<std::vector<Aircraft::Manufacturer>, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Flights::manufacturers finishes.
using Callback = std::function<void(const Result&)>;
};
/// Models groups together types to ease interaction with
/// Aircrafts::models.
struct Models {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<Aircraft::Manufacturer> manufacturer; ///< Only list models by this manufacturer.
Optional<std::string> model_name; ///< Search for the specific model with this name.
};
/// Result models the outcome of calling Flights::models.
using Result = Outcome<std::vector<Aircraft>, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Flights::models finishes.
using Callback = std::function<void(const Result&)>;
};
/// ModelForId groups together types to ease interaction with
/// Aircrafts::model_for_id.
struct ModelForId {
/// Parameters bundles up input parameters.
struct Parameters {
std::string id; ///< Search for the model with this id.
};
/// Result models the outcome of calling Flights::model_for_id.
using Result = Outcome<Aircraft, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Flights::model_for_id finishes.
using Callback = std::function<void(const Result&)>;
};
/// manufacturers queries the AirMap services for known aircraft
/// manufacturers, reporting results to 'cb'.
virtual void manufacturers(const Manufacturers::Parameters& parameters, const Manufacturers::Callback& cb) = 0;
/// models queries the AirMap services for detailed information about
/// known Aircraft models and reports back results to 'cb'.
virtual void models(const Models::Parameters& parameters, const Models::Callback& cb) = 0;
/// models queries the AirMap services for detailed information about
/// an Aircraft model identified by 'ModelForId::Parameters::id' and reports back results to 'cb'.
virtual void model_for_id(const ModelForId::Parameters& parameters, const ModelForId::Callback& cb) = 0;
protected:
/// @cond
Aircrafts() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_AIRCRAFTS_H_
This diff is collapsed.
#ifndef AIRMAP_AIRSPACES_H_
#define AIRMAP_AIRSPACES_H_
#include <airmap/airspace.h>
#include <airmap/date_time.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/outcome.h>
#include <functional>
#include <vector>
namespace airmap {
/// Airspaces provides functionality to query the airspace database.
class Airspaces : DoNotCopyOrMove {
public:
/// ForIds groups together types to ease interaction with
/// Airspaces::ForIds.
struct ForIds {
/// Parameters bundles up input parameters.
struct Parameters {
Airspace::Id id; ///< Search for the airspace with this id.
};
/// Result models the outcome of calling Airspaces::for_id.
using Result = Outcome<std::vector<Airspace>, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Airspaces::for_id finishes.
using Callback = std::function<void(const Result&)>;
};
/// Search groups together types to ease interaction with
/// Airspaces::Search.
struct Search {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<Airspace::Type> types; ///< Search for airspaces with either one of these types.
Optional<Airspace::Type> ignored_types; ///< Ignore airspaces with either one of these types.
Optional<bool> full; ///< If true, the complete description of airspaces in the result set is requested.
Geometry geometry; ///< Search airspaces intersection this geometry.
Optional<std::uint32_t> buffer; ///< Buffer around the geometry in [m].
Optional<std::uint32_t> limit; ///< Limit the number of results to 'limit'.
Optional<std::uint32_t> offset;
Optional<DateTime> date_time;
};
/// Result models the outcome of calling Airspaces::search.
using Result = Outcome<std::vector<Airspace>, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Airspaces::search finishes.
using Callback = std::function<void(const Result&)>;
};
/// search queries the AirMap services for surrounding airspaces and
/// reports back the results to 'cb'.
virtual void search(const Search::Parameters& parameters, const Search::Callback& cb) = 0;
/// for_ids queries the AirMap services for detailed information about
/// airspaces identified by UUIDs and reports back results to 'cb'.
virtual void for_ids(const ForIds::Parameters& parameters, const ForIds::Callback& cb) = 0;
protected:
/// cond
Airspaces() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_AIRSPACES_H_
#ifndef AIRMAP_AUTHENTICATOR_H_
#define AIRMAP_AUTHENTICATOR_H_
#include <airmap/credentials.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/outcome.h>
#include <airmap/token.h>
#include <chrono>
#include <functional>
#include <stdexcept>
#include <string>
namespace airmap {
/// Authenticator provides functionality to authenticate with the AirMap services.
class Authenticator : DoNotCopyOrMove {
public:
/// Scope enumerates all known authentication scopes.
enum class Scope { access_token = 0, open_id = 1, open_id_offline_access = 2 };
/// GrantType enumerates all known grant types.
enum class GrantType {
password = 0, ///< The grant is constituted by a password
bearer = 1 ///< The grant is constituted by a bearer
};
/// Connection enumerates all known types of connection to users.
enum class Connection {
username_password_authentication = 0 ///< authentication requires username/password
};
/// AuthenticateWithPassword groups together types to ease interaction with
/// Authenticator::authenticate_with_password.
struct AuthenticateWithPassword {
/// Parameters bundles up input parameters.
struct Params {
Credentials::OAuth oauth; ///< OAuth-specific credentials for this authentication request.
GrantType grant_type{GrantType::password}; ///< The grant type of this authentication request.
Scope scope{Scope::open_id_offline_access}; ///< The scope of this authentication request.
Connection connection{
Connection::username_password_authentication}; ///< The connection type of the authentication request.
};
/// Result models the outcome of calling Authenticator::authenticate_with_password.
using Result = Outcome<Token::OAuth, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Authenticator::authenticate_with_password finishes.
using Callback = std::function<void(const Result&)>;
};
/// AuthenticateAnonymously groups together types to ease interaction with
/// Authenticator::authenticate_anonymously.
struct AuthenticateAnonymously {
/// The input parameters.
using Params = Credentials::Anonymous;
/// Result models the outcome of calling Authenticator::authenticate_anonymously.
using Result = Outcome<Token::Anonymous, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Authenticator::authenticate_anonymously finishes.
using Callback = std::function<void(const Result&)>;
};
/// RenewAuthentication groups together types to ease interaction with
/// Authenticator::renew_authentication.
struct RenewAuthentication {
/// The input parameters.
struct Params {
std::string client_id; ///< The app id for which authentication renewal is requested.
std::string refresh_token; ///< The refresh token for the authentication renewal request.
GrantType grant_type{GrantType::bearer}; ///< The grant type of the authentication renewal request.
Scope scope{Scope::open_id}; ///< The scope of the authentication renewal request.
};
/// Result models the outcome of calling Authenticator::renew_authentication.
using Result = Outcome<Token::Refreshed, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Authenticator::renew_authentication finishes.
using Callback = std::function<void(const Result&)>;
};
/// authenticate_with_password authenticates the user described in 'params' with
/// the AirMap services and reports the result to 'cb'.
virtual void authenticate_with_password(const AuthenticateWithPassword::Params& params,
const AuthenticateWithPassword::Callback& cb) = 0;
/// authenticate_anonymously authenticates an anonymous user described by Params::user_id
/// with the AirMap services and reports the result to 'cb'.
virtual void authenticate_anonymously(const AuthenticateAnonymously::Params&,
const AuthenticateAnonymously::Callback&) = 0;
/// renew_authentication renews a pre-authenticated JWT as given in Params::user_id with
/// the AirMap services and reports the result to 'cb'.
virtual void renew_authentication(const RenewAuthentication::Params& params,
const RenewAuthentication::Callback& cb) = 0;
protected:
/// @cond
Authenticator() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_AUTHENTICATOR_H_
#ifndef AIRMAP_CLIENT_H_
#define AIRMAP_CLIENT_H_
#include <airmap/credentials.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/optional.h>
#include <airmap/outcome.h>
#include <cstdint>
#include <functional>
#include <iosfwd>
#include <memory>
#include <string>
namespace airmap {
class Aircrafts;
class Airspaces;
class Authenticator;
class FlightPlans;
class Flights;
class Pilots;
class RuleSets;
class Status;
class Telemetry;
class Traffic;
/// Client enables applications to use the AirMap services and APIs.
class Client : DoNotCopyOrMove {
public:
/// Version enumerates all known versions available to clients.
enum class Version { production, staging };
/// Configuration bundles up parameters enabling
/// customization of a Client implementation behavior.
struct Configuration {
std::string host; ///< Address of the host exposing the AirMap services.
Version version; ///< The version of the AirMap services that should be used.
struct {
std::string host; ///< Address of the host exposing the sso service.
std::uint16_t port; ///< Port on the host exposing the sso service.
} sso; ///< The SSO endpoint used for the authenticating with the AirMap services.
struct {
std::string host; ///< Address of the host exposing the AirMap telemetry endpoints.
std::uint16_t port; ///< Port of the host exposing the AirMap telemetry endpoints.
} telemetry; ///< The telemetry submission endpoint.
struct {
std::string host; ///< Address of the mqtt broker serving air traffic information.
std::uint16_t port; ///< Port of the mqtt broker serving air traffic information.
} traffic; ///< The traffic endpoint.
Credentials credentials; ///< Credentials that are required to authorize access to the AirMap services.
};
/// default_production_configuration returns a Configuration instance that works
/// against the AirMap production API and telemetry endpoints.
static Configuration default_production_configuration(const Credentials& credentials);
/// default_staging_configuration returns a Configuration instance that works
/// against the AirMap staging API and telemetry endpoints.
static Configuration default_staging_configuration(const Credentials& credentials);
/// default_configuration returns a Configuration instance that works against
/// the AirMap API and telemetry endpoints indicated by 'version'.
static Configuration default_configuration(Version version, const Credentials& credentials);
/// load_configuration_from_json loads a configuration from 'in', assuming the following
/// JSON format:
///
/// @code{.json}
/// {
/// "host": "api.airmap.com",
/// "version": "production",
/// "sso": {
/// "host": "sso.airmap.io",
/// "port": 443
/// },
/// "telemetry": {
/// "host": "api-udp-telemetry.airmap.com",
/// "port": 16060
/// },
/// "traffic": {
/// "host": "mqtt-prod.airmap.io",
/// "port": 8883
/// },
/// "credentials": {
/// "api-key": "your api key should go here",
/// "oauth": {
/// "client-id": "your client id should go here",
/// "device-id": "your device id should go here, or generate one with uuid-gen",
/// "username": "your AirMap username should go here",
/// "password": "your AirMap password should go here"
/// },
/// "anonymous": {
/// "id": "some id"
/// }
/// }
/// }
/// @endcode
static Configuration load_configuration_from_json(std::istream& in);
/// authenticator returns the Authenticator implementation provided by the client.
virtual Authenticator& authenticator() = 0;
/// aircrafts returns the Aircrafts implementation provided by the client.
virtual Aircrafts& aircrafts() = 0;
/// airspaces returns the Airspaces implementation provided by the client.
virtual Airspaces& airspaces() = 0;
/// flight_plans returns the FlightPlans implementation provided by the client.
virtual FlightPlans& flight_plans() = 0;
/// flights returns the Flights implementation provided by the client.
virtual Flights& flights() = 0;
/// pilots returns the Pilots implementation provided by the client.
virtual Pilots& pilots() = 0;
/// rulesets returns the RuleSets implementation provided by the client.
virtual RuleSets& rulesets() = 0;
/// status returns the Status implementation provided by the client.
virtual Status& status() = 0;
/// telemetry returns the Telemetry implementation provided by the client.
virtual Telemetry& telemetry() = 0;
/// traffic returns the Traffic implementation provided by the client.
virtual Traffic& traffic() = 0;
protected:
/// @cond
Client() = default;
/// @endcond
};
/// @cond
std::istream& operator>>(std::istream& in, Client::Version& version);
std::ostream& operator<<(std::ostream& out, Client::Version version);
/// @endcond
} // namespace airmap
#endif // AIRMAP_CLIENT_H_
#ifndef AIRMAP_CONTEXT_H_
#define AIRMAP_CONTEXT_H_
#include <airmap/client.h>
#include <airmap/date_time.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/logger.h>
#include <airmap/monitor/client.h>
#include <airmap/outcome.h>
#include <functional>
#include <unordered_set>
namespace airmap {
/// Context consitutes the point-of-entry for interaction with the classes and interfaces
/// in airmap::*.
class Context : DoNotCopyOrMove {
public:
/// ReturnCode enumerates all known return values for a call to run or exec.
enum class ReturnCode {
success = 0, /// Execution finished successfully
error = 1, /// Execution finished with an error
already_running = 2 /// Indicates that the context is already executing on another thread
};
/// @cond
using ClientCreateResult = Outcome<std::shared_ptr<Client>, Error>;
using ClientCreateCallback = std::function<void(const ClientCreateResult&)>;
using MonitorClientCreateResult = Outcome<std::shared_ptr<monitor::Client>, Error>;
using MonitorClientCreateCallback = std::function<void(const MonitorClientCreateResult&)>;
using CreateResult = Outcome<std::shared_ptr<Context>, Error>;
using SignalHandler = std::function<void(int)>;
using SignalSet = std::unordered_set<int>;
/// @endcond
/// create tries to assemble and return a new Context instance.
static CreateResult create(const std::shared_ptr<Logger>& logger);
/// create_client_with_configuration schedules creation of a new client with 'configuration'
/// and reports results to 'cb'.
virtual void create_client_with_configuration(const Client::Configuration& configuration,
const ClientCreateCallback& cb) = 0;
/// create_monitor_client_with_configuration schedules creation of a new monitor::Client with 'configuration'
/// and reports results to 'cb'.
virtual void create_monitor_client_with_configuration(const monitor::Client::Configuration& configuration,
const MonitorClientCreateCallback& cb) = 0;
/// exec hands a thread of execution to a Context instance, monitoring
/// the signals present in 'signal_set' and dispatching incoming signals
/// to the registered handlers.
///
/// Implementations are expected to block the current thread until
/// either an error occured or the user explicitly requests a Context
/// instance to stop.
virtual ReturnCode exec(const SignalSet& signal_set, const SignalHandler& handler) = 0;
/// run hands a thread of execution to the context.
///
/// Implementations are expected to block the current thread until
/// either an error occured or the user explicitly requests a Context
/// instance to stop.
virtual ReturnCode run() = 0;
/// stop requests an instance to shut down its operation and return from
/// run.
virtual void stop(ReturnCode rc = ReturnCode::success) = 0;
/// dispatch executes 'task' on the thread running this Context instance.
virtual void dispatch(const std::function<void()>& task) = 0;
/// schedule_in schedules execution of 'functor' in 'wait_for' [us].
virtual void schedule_in(const Microseconds& wait_for, const std::function<void()>& functor) = 0;
protected:
/// @cond
Context() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_CONTEXT_H_
#ifndef AIRMAP_CREDENTIALS_H_
#define AIRMAP_CREDENTIALS_H_
#include <airmap/optional.h>
#include <iosfwd>
#include <string>
namespace airmap {
/// Credentials bundles up all credentials required
/// to use the AirMap SDK and APIs.
struct Credentials {
enum class Type { anonymous, oauth };
/// Anonymous bundles up all attributes needed to
/// authenticate anonymously with the AirMap services.
struct Anonymous {
std::string id;
};
/// OAuth bundles up all attributes needed to authenticate
/// with username/password with the AirMap services.
struct OAuth {
std::string username;
std::string password;
std::string client_id;
std::string device_id;
};
std::string api_key; ///< Use this api key when accessing the AirMap services
Optional<OAuth> oauth; /// Optional attributes for authenticating with username/password with the AirMap services
Optional<Anonymous> anonymous; /// Optional attributes for authenticating anonymously with the AirMap services
};
/// operator>> extracts type from in.
std::istream& operator>>(std::istream& in, Credentials::Type& type);
/// operator<< inserts type into out.
std::ostream& operator<<(std::ostream& out, Credentials::Type type);
} // namespace airmap
#endif // AIRMAP_CREDENTIALS_H_
#ifndef AIRMAP_DATE_TIME_H_
#define AIRMAP_DATE_TIME_H_
#include <boost/date_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <cstdint>
#include <memory>
#include <string>
namespace airmap {
/// Clock marks the reference for time measurements.
using Clock = boost::posix_time::microsec_clock;
/// DateTime marks a specific point in time, in reference to Clock.
using DateTime = boost::posix_time::ptime;
using Hours = boost::posix_time::hours;
using Minutes = boost::posix_time::minutes;
using Seconds = boost::posix_time::seconds;
using Milliseconds = boost::posix_time::milliseconds;
using Microseconds = boost::posix_time::microseconds;
/// milliseconds_since_epoch returns the milliseconds that elapsed since the UNIX epoch.
std::uint64_t milliseconds_since_epoch(const DateTime& dt);
/// microseconds_since_epoch returns the microseconds that elapsed since the UNIX epoch.
std::uint64_t microseconds_since_epoch(const DateTime& dt);
/// from_seconds_since_epoch returns a DateTime.
DateTime from_seconds_since_epoch(const Seconds& s);
/// from_milliseconds_since_epoch returns a DateTime.
DateTime from_milliseconds_since_epoch(const Milliseconds& ms);
/// from_microseconds_since_epoch returns a DateTime.
DateTime from_microseconds_since_epoch(const Microseconds& us);
// moves the datetime forward to the specified hour
DateTime move_to_hour(const DateTime& dt, int hour);
namespace iso8601 {
/// parse parses a DateTime instance from the string s in iso8601 format.
DateTime parse(const std::string& s);
/// generate returns a string in iso8601 corresponding to 'dt'.
std::string generate(const DateTime& dt);
} // namespace iso8601
} // namespace airmap
#endif // AIRMAP_DATE_TIME_H_
#ifndef AIRMAP_DO_NOT_COPY_OR_MOVE_H_
#define AIRMAP_DO_NOT_COPY_OR_MOVE_H_
namespace airmap {
/// @cond
struct DoNotCopyOrMove {
DoNotCopyOrMove() = default;
DoNotCopyOrMove(const DoNotCopyOrMove&) = delete;
DoNotCopyOrMove(DoNotCopyOrMove&&) = delete;
virtual ~DoNotCopyOrMove() = default;
DoNotCopyOrMove& operator=(const DoNotCopyOrMove&) = delete;
DoNotCopyOrMove& operator=(DoNotCopyOrMove&&) = delete;
};
/// @endcond
} // namespace airmap
#endif // AIRMAP_DO_NOT_COPY_OR_MOVE_H_
#ifndef AIRMAP_ERROR_H_
#define AIRMAP_ERROR_H_
#include <airmap/do_not_copy_or_move.h>
#include <airmap/optional.h>
#include <cstdint>
#include <iosfwd>
#include <map>
#include <memory>
#include <string>
#include <vector>
namespace airmap {
/// Error models an error raised by an AirMap component.
struct Error {
/// Value is a discriminated union type wrapping up multiple atomic types and
/// their composition into a vector or a dictionary.
class Value {
public:
/// Type enumerates all datatypes that can be wrapped in a Value.
enum class Type {
undefined, ///< Marks the undefined type.
boolean, ///< Marks a boolean type.
integer, ///< Marks an integer type with 64 bits.
floating_point, ///< Marks a double-precision floating point number.
string, ///< Marks a string.
blob, ///< Marks a binary blob.
dictionary, ///< Marks a dictionary of values.
vector ///< Marks a vector of values.
};
/// Value initializes a new Value instance of type undefined.
explicit Value();
/// Value initializes a new Value instance of type boolean with 'value'.
explicit Value(bool value);
/// Value initializes a new Value instance of type integer with 'value'.
explicit Value(std::int64_t value);
/// Value initializes a new Value instance of type floating_point with 'value'.
explicit Value(double value);
/// Value initializes a new Value instance of type string with 'value'.
explicit Value(const std::string& value);
/// Value initializes a new Value instance of type blob with 'value'.
explicit Value(const std::vector<std::uint8_t>& value);
/// Value initializes a new Value instance of type dictionary with 'value'.
explicit Value(const std::map<Value, Value>& value);
/// Value initializes a new Value instance of type vector with 'value'.
explicit Value(const std::vector<Value>& value);
/// Value copy-constructs a value from 'other'.
Value(const Value& other);
/// Value move-constructs a value from 'other'.
Value(Value&&);
/// ~Value cleans up all resources by a Value instance.
~Value();
/// operator= assigns type and value from rhs.
Value& operator=(const Value& rhs);
/// operator= moves type and value from rhs.
Value& operator=(Value&& rhs);
/// type returns the Type of this Value instance.
Type type() const;
/// boolean returns the boolean value of this Value instance.
/// The behavior in case of type() != Type::boolean is undefined.
bool boolean() const;
/// integer returns the boolean value of this Value instance.
/// The behavior in case of type() != Type::integer is undefined.
std::int64_t integer() const;
/// floating_point returns the floating point value of this Value instance.
/// The behavior in case of type() != Type::floating_point is undefined.
double floating_point() const;
/// string returns the string value of this Value instance.
/// The behavior in case of type() != Type::string is undefined.
const std::string& string() const;
/// blob returns the blob value of this Value instance.
/// The behavior in case of type() != Type::blob is undefined.
const std::vector<std::uint8_t> blob() const;
/// dictionary returns the dictionary value of this Value instance.
/// The behavior in case of type() != Type::dictionary is undefined.
const std::map<Value, Value>& dictionary() const;
/// vector returns the vector value of this Value instance.
/// The behavior in case of type() != Type::vector is undefined.
const std::vector<Value>& vector() const;
private:
union Details {
Details();
~Details();
bool boolean;
std::int64_t integer;
double floating_point;
std::string string;
std::vector<std::uint8_t> blob;
std::map<Value, Value> dictionary;
std::vector<Value> vector;
};
Value& construct(bool value);
Value& construct(std::int64_t value);
Value& construct(double value);
Value& construct(const std::string& value);
Value& construct(std::string&& value);
Value& construct(const std::vector<std::uint8_t>& value);
Value& construct(std::vector<std::uint8_t>&& value);
Value& construct(const std::map<Value, Value>& value);
Value& construct(std::map<Value, Value>&& value);
Value& construct(const std::vector<Value>& value);
Value& construct(std::vector<Value>&& value);
Value& construct(const Value& value);
Value& construct(Value&& value);
Value& destruct();
Type type_;
Details details_;
};
/// Error initializes a new error instance with 'message'.
explicit Error();
/// Error initializes a new error instance with 'message'.
explicit Error(const std::string& message);
/// message returns the message describing an error condition.
const std::string& message() const;
/// message sets the message of the Error instance to 'message'.
Error message(const std::string& message) const;
/// message sets the message of the Error instance to 'message'.
Error& message(const std::string& message);
/// description returns the optional description of an error condition.
const Optional<std::string>& description() const;
/// clear_description resets the description of the Error instance.
Error clear_description() const;
/// clear_description resets the description of the Error instance.
Error& clear_description();
/// description sets the description of the Error instance to 'description'.
Error description(const std::string& description) const;
/// description sets the description of the Error instance to 'description'.
Error& description(const std::string& description);
/// values returns the additional values describing an error condition.
const std::map<Value, Value>& values() const;
/// clear_values resets the values of the Error instance.
Error clear_values() const;
/// clear_values resets the values of the Error instance.
Error& clear_values();
/// value adds the pair (key, value) to the additional values describing an error condition.
Error value(const Value& key, const Value& value) const;
/// value adds the pair (key, value) to the additional values describing an error condition.
Error& value(const Value& key, const Value& value);
private:
std::string message_; ///< Short, human-readable message.
Optional<std::string> description_; ///< Detailed description of the error, meant to be used for defect analysis.
std::map<Value, Value> values_; ///< Dictionary of additional data attached to the error.
};
/// operator== returns true if both type and value of lhs and rhs compare equal.
bool operator==(const Error::Value& lhs, const Error::Value& rhs);
/// operator< returns true if type and value of lhs compare < than type and value of rhs.
bool operator<(const Error::Value& lhs, const Error::Value& rhs);
/// operator<< inserts 'value' into 'out'.
std::ostream& operator<<(std::ostream& out, const Error::Value& value);
/// operator<< inserts 'error' into 'out'.
std::ostream& operator<<(std::ostream& out, const Error& error);
} // namespace airmap
#endif // AIRMAP_ERROR_H_
\ No newline at end of file
#ifndef AIRMAP_EVALUATION_H_
#define AIRMAP_EVALUATION_H_
#include <airmap/optional.h>
#include <airmap/ruleset.h>
#include <airmap/status.h>
#include <cstdint>
#include <iosfwd>
#include <iostream>
#include <string>
#include <vector>
namespace airmap {
/// Evaluation bundles together information regarding an airspace ruleset evaluation.
struct Evaluation {
/// Authority models an authority capable of authorizing flight plans.
struct Authority {
std::string id; ///< The id of the authority.
std::string name; ///< The name of the authority.
};
/// Authorization bundles up the authorization status of a flight plan.
struct Authorization {
/// Status enumerates all known states of an Authorization.
enum class Status {
accepted, ///< The flight plan is accepted.
rejected, ///< The flight plan is rejected.
pending, ///< The request for authorization is pending a response.
accepted_upon_submission, ///< The request will be accepted on submission.
rejected_upon_submission ///< The request will be rejected on submission.
};
Status status; ///< The overall status of the request.
Authority authority; ///< The authority that handles the request.
std::string message; ///< The human-readable message provided by the authority.
};
/// Validation bundles up the validation status of a flight plan.
struct Validation {
/// Status enumerates all known states of a Validation.
enum class Status {
valid, ///< The validation succeeded.
invalid, ///< The validation was rejected.
unknown ///< The status is unknown.
};
/// Feature describes a specific feature that requires validation.
struct Feature {
std::string code; ///< The code of the feature.
std::string description; ///< The description of the feature.
};
Status status; ///< The overall status of the validation.
std::string data; ///< The data provided for validation.
std::string message; ///< The human-readable message provided by the authority.
Feature feature; ///< The specific feature requiring validation.
Authority authority; ///< The authority carrying out the validation.
};
/// Failure enumrates all known failures during evaluation.
enum class Failure {
validation, ///< The validation failed.
authorization, ///< The authorization failed.
rulesets ///< The ruleset engine failed.
};
std::vector<RuleSet> rulesets; ///< All RuleSet instances relevant to a specific briefing/flight plan.
std::vector<Validation> validations; ///< All Validation instances relevant to a specific briefing/flight plan.
std::vector<Authorization>
authorizations; ///< All Authorization instances relevant to a specific briefing/flight plan.
std::vector<Failure> failures; ///< All Failure instances relevant to a specific briefing/flight plan.
};
/// @cond
std::ostream& operator<<(std::ostream& out, Evaluation::Authorization::Status status);
std::istream& operator>>(std::istream& in, Evaluation::Authorization::Status& status);
std::ostream& operator<<(std::ostream& out, Evaluation::Validation::Status status);
std::istream& operator>>(std::istream& in, Evaluation::Validation::Status& status);
std::ostream& operator<<(std::ostream& out, Evaluation::Failure failure);
std::istream& operator>>(std::istream& in, Evaluation::Failure& failure);
/// @endcond
} // namespace airmap
#endif // AIRMAP_EVALUATION_H_
#ifndef AIRMAP_FLIGHT_H_
#define AIRMAP_FLIGHT_H_
#include <airmap/date_time.h>
#include <airmap/flight_plan.h>
#include <airmap/geometry.h>
#include <airmap/pilot.h>
#include <cstdint>
namespace airmap {
/// Flight bundles together properties describing an individual flight.
struct Flight {
using Id = std::string;
Id id; ///< The unique identifier of a flight in the context of AirMap.
Optional<FlightPlan::Id> flight_plan_id; ///< The flight plan corresponding to this flight.
Pilot pilot; ///< The pilot responsible for the flight.
Pilot::Aircraft aircraft; ///< The aircraft conducting the flight.
float latitude; ///< The latitude component of the takeoff point in [°].
float longitude; ///< The longitude component of the takeoff point in [°].
float max_altitude; ///< The maximum altitude over the entire flight in [m].
Geometry geometry; ///< The geometry describing the flight.
DateTime created_at; ///< Point in time when the flight was created.
DateTime start_time; ///< Point in time when the flight will start/was started.
DateTime end_time; ///< Point in time when the fligth will end.
};
} // namespace airmap
#endif // AIRMAP_FLIGHT_H_
#ifndef AIRMAP_FLIGHT_PLAN_H_
#define AIRMAP_FLIGHT_PLAN_H_
#include <airmap/date_time.h>
#include <airmap/evaluation.h>
#include <airmap/geometry.h>
#include <airmap/optional.h>
#include <airmap/pilot.h>
#include <airmap/ruleset.h>
#include <airmap/status.h>
#include <cstdint>
#include <iosfwd>
#include <string>
#include <unordered_map>
#include <vector>
namespace airmap {
/// FlightPlan bundles together properties describing a plan for a flight.
struct FlightPlan {
/// Id models a unique identifier for a flight plan in the context of AirMap.
using Id = std::string;
/// Briefing bundles together information and data for a flight plan.
/// The target audience is a hypothetical pilot or operator conducting
/// the flight described in the flight plan.
struct Briefing {
/// AdvisoryStatus summarizes the status of all advisories applying to a specific flight plan.
struct AdvisoryStatus {
Status::Color color; ///< The overall color of the status.
std::vector<Status::Advisory> advisories; ///< The collection of relevant advisories.
};
DateTime created_at; ///< The timestamp when the briefing was requested and created by the AirMap services.
AdvisoryStatus airspace; ///< The summary over all advisories relevant to a specific briefing/flight plan.
Evaluation evaluation; ///< The airspace ruleset evaluation returned for the briefing.
};
Id id; ///< The unique identifier of a flight in the context of AirMap.
Optional<std::string> flight_id; ///< The unique identifier of the flight that is created on successful submission.
Pilot pilot; ///< The pilot responsible for the flight.
Pilot::Aircraft aircraft; ///< The aircraft conducting the flight.
struct {
float latitude; ///< The latitude component of the takeoff coordinates in [°].
float longitude; ///< The longitude component of the takeoff coordinates in [°].
} takeoff; ///< The takeoff coordinate.
struct {
float max; ///< The maximum altitude over the entire flight in [m].
float min; ///< The minimum altitude over the entire flight in [m].
} altitude_agl; ///< The altitude range of the flight in [m] above ground level.
float buffer; ///< The buffer in [m] around the geometry.
Geometry geometry; ///< The geometry describing the flight.
DateTime start_time; ///< Point in time when the flight will start/was started.
DateTime end_time; ///< Point in time when the fligth will end.
};
} // namespace airmap
#endif // AIRMAP_FLIGHT_PLAN_H_
#ifndef AIRMAP_FLIGHT_PLANS_H_
#define AIRMAP_FLIGHT_PLANS_H_
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/flight_plan.h>
#include <airmap/outcome.h>
#include <cstdint>
#include <functional>
#include <vector>
namespace airmap {
/// FlightPlans provides functionality for managing flight plans.
class FlightPlans : DoNotCopyOrMove {
public:
/// ForId bundles up types to ease interaction with
/// FlightPlans::for_id.
struct ForId {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<std::string> authorization; ///< Authorization token obtained by logging in to the AirMap services.
FlightPlan::Id id; ///< Search for the flight with this id.
};
/// Result models the outcome of calling FlightPlans::for_id.
using Result = Outcome<FlightPlan, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to FlightPlans::for_id finishes.
using Callback = std::function<void(const Result&)>;
};
/// Create bundles up types to ease interaction with
/// FlightPlans::create_by_point and FlightPlans::create_by_polygon.
struct Create {
/// Parameters bundles up input parameters.
struct Parameters {
std::string authorization; ///< Authorization token obtained by logging in to the AirMap services.
Pilot pilot; ///< The pilot responsible for the flight.
Optional<Pilot::Aircraft> aircraft; ///< The aircraft conducting the flight.
float latitude; ///< The latitude component of the takeoff point in [°].
float longitude; ///< The longitude component of the takeoff point in [°].
float max_altitude; ///< The maximum altitude over the entire flight in [m].
float min_altitude; ///< The minimum altitude over the entire flight in [m].
float buffer; ///< The buffer in [m] around the geometry.
Geometry geometry; ///< The geometry describing the flight.
DateTime start_time; ///< Point in time when the flight will start/was started.
DateTime end_time; ///< Point in time when the fligth will end.
std::vector<RuleSet::Id> rulesets; ///< RuleSets that apply to this flight plan.
std::unordered_map<std::string, RuleSet::Feature::Value>
features; ///< Additional properties of the planned flight.
};
/// Result models the outcome of calling FlightPlans::create_by_polygon.
using Result = Outcome<FlightPlan, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to FlightPlans::create_by_point or FlightPlans::create_by_polygon finishes.
using Callback = std::function<void(const Result&)>;
};
/// Update bundles up types to ease interaction with
/// FlightPlans::update.
struct Update {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<std::string> authorization; ///< Authorization token obtained by logging in to the AirMap services.
FlightPlan flight_plan; ///< The details of the plan that should be created with the AirMap services.
};
/// Result models the outcome of calling FlightPlans::update.
using Result = Outcome<FlightPlan, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to FlightPlans::update finishes.
using Callback = std::function<void(const Result&)>;
};
/// Delete bundles up types to ease interaction with
/// FlightPlans::delete_.
struct Delete {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<std::string> authorization; ///< Authorization token obtained by logging in to the AirMap services.
FlightPlan::Id id; ///< Id of the flight plan that should be deleted.
};
/// Response models the response from the AirMap services.
struct Response {
FlightPlan::Id id; ///< Id of the flight plan that was deleted.
};
/// Result models the outcome of calling FlightPlans::delete_flight.
using Result = Outcome<Response, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to FlightPlans::delete_flight finishes.
using Callback = std::function<void(const Result&)>;
};
/// RenderBriefing bundles up types to ease interaction with
/// FlightPlans::render_briefing.
struct RenderBriefing {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<std::string> authorization; ///< Authorization token obtained by logging in to the AirMap services.
FlightPlan::Id id; ///< Id of the flight plan that should be rendered as a briefing.
};
/// Result models the outcome of calling FlightPlans::submit.
using Result = Outcome<FlightPlan::Briefing, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to FlightPlans::submit finishes.
using Callback = std::function<void(const Result&)>;
};
/// Submit bundles up types to ease interaction with
/// FlightPlans::submit.
struct Submit {
/// Parameters bundles up input parameters.
struct Parameters {
Optional<std::string> authorization; ///< Authorization token obtained by logging in to the AirMap services.
FlightPlan::Id id; ///< Id of the flight plan that should be submitted.
};
/// Result models the outcome of calling FlightPlans::submit.
using Result = Outcome<FlightPlan, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to FlightPlans::submit finishes.
using Callback = std::function<void(const Result&)>;
};
/// for_id queries the AirMap services for detailed information about
/// a flight plan identified by a UUID and reports back results to 'cb'.
virtual void for_id(const ForId::Parameters& parameters, const ForId::Callback& cb) = 0;
/// create_by_polygon creates a flight plan for 'parameters' and reports
/// results back to 'cb'.
virtual void create_by_polygon(const Create::Parameters& parameters, const Create::Callback& cb) = 0;
/// update updates a flight plan identified by 'parameters' and reports
/// results back to 'cb'.
virtual void update(const Update::Parameters& parameters, const Update::Callback& cb) = 0;
/// delete deletes a flight plan identified by 'parameters' and reports
/// results back to 'cb'.
virtual void delete_(const Delete::Parameters& parameters, const Delete::Callback& cb) = 0;
/// render_briefing requests rendering a briefing for a flight plan identified by 'parameters' and reports
/// results back to 'cb'.
virtual void render_briefing(const RenderBriefing::Parameters& parameters, const RenderBriefing::Callback& cb) = 0;
/// submit submits a flight plan identified by 'parameters' and reports
/// results back to 'cb'.
virtual void submit(const Submit::Parameters& parameters, const Submit::Callback& cb) = 0;
protected:
/// @cond
FlightPlans() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_FLIGHT_PLANS_H_
This diff is collapsed.
#ifndef AIRMAP_GEOMETRY_H_
#define AIRMAP_GEOMETRY_H_
#include <airmap/optional.h>
#include <vector>
namespace airmap {
/// Geometry bundles up different types of geometries.
class Geometry {
public:
/// Type enumerates all known geometry types.
enum class Type {
invalid, ///< Marks an invalid geometry.
point, ///< Geometry contains a Point.
multi_point, ///< Geometry contains a MultiPoint.
line_string, ///< Geometry contains a LineString.
multi_line_string, ///< Geometry contains a MultiLineString.
polygon, ///< Geometry contains a Polygon.
multi_polygon, ///< Geometry contains a MultiPolygon.
geometry_collection ///< Geometry is a GemetryCollection.
};
/// Coordinate marks a point in 3-dimensional space.
struct Coordinate {
double latitude; /// The latitude component of this coordinate in [°].
double longitude; /// The longitude component of this coordinate in [°].
Optional<double> altitude; /// The altitude component of this coordinate in [m].
Optional<double> elevation;
};
/// CoordinateVector is a collection of points in 3-dimensional space.
template <Type tag>
struct CoordinateVector {
std::vector<Coordinate> coordinates; ///< The individual coordinates.
};
using Point = Coordinate;
using MultiPoint = CoordinateVector<Type::multi_point>;
using LineString = CoordinateVector<Type::line_string>;
using MultiLineString = std::vector<LineString>;
/// Polygon follows the GeoJSON standard, citing from https://tools.ietf.org/html/rfc7946:
/// * For type "Polygon", the "coordinates" member MUST be an array of
/// linear ring coordinate arrays.
/// * For Polygons with more than one of these rings, the first MUST be
/// the exterior ring, and any others MUST be interior rings. The
/// exterior ring bounds the surface, and the interior rings (if
/// present) bound holes within the surface.
struct Polygon {
CoordinateVector<Type::polygon> outer_ring;
std::vector<CoordinateVector<Type::polygon>> inner_rings;
};
using MultiPolygon = std::vector<Polygon>;
using GeometryCollection = std::vector<Geometry>;
/// point returns a Geometry instance with Type::point at the given coordinate (lat, lon).
static Geometry point(double lat, double lon);
/// polygon returns a Geometry instance with Type::polygon with the given 'coordinates'.
static Geometry polygon(const std::vector<Coordinate>& coordinates);
/// Initializes a new instance with Type::invalid.
Geometry();
/// Geometry initializes a new instance with the given Point.
explicit Geometry(const Point& other);
/// Geometry initializes a new instance with the given MultiPoint.
explicit Geometry(const MultiPoint& other);
/// Geometry initializes a new instance with the given LineString.
explicit Geometry(const LineString& other);
/// Geometry initializes a new instance with the given MultiLineString.
explicit Geometry(const MultiLineString& other);
/// Geometry initializes a new instance with the given Polyon.
explicit Geometry(const Polygon& other);
/// Geometry initializes a new instance with the given MultiPolygon.
explicit Geometry(const MultiPolygon& other);
/// Geometry initializes a new instance with the given GeometryCollection.
explicit Geometry(const GeometryCollection& other);
/// @cond
Geometry(const Geometry& other);
~Geometry();
Geometry& operator=(const Geometry& rhs);
bool operator==(const Geometry& rhs) const;
/// @endcond
/// type returns the Type of the geometry.
Type type() const;
/// details_for_point returns an immutable instance to the contained Point instance.
const Point& details_for_point() const;
/// details_for_multi_point returns an immutable instance to the contained MultiPoint instance.
const MultiPoint& details_for_multi_point() const;
/// details_for_line_string returns an immutable instance to the contained LineString instance.
const LineString& details_for_line_string() const;
/// details_for_multi_line_string returns an immutable instance to the contained MultiLineString instance.
const MultiLineString& details_for_multi_line_string() const;
/// details_for_polygon returns an immutable instance to the contained Polygon instance.
const Polygon& details_for_polygon() const;
/// details_for_multi_polygon returns an immutable instance to the contained MultiPolygon instance.
const MultiPolygon& details_for_multi_polygon() const;
/// details_for_geometry_collection returns an immutable instance to the contained GeometryCollection instance.
const GeometryCollection details_for_geometry_collection() const;
private:
struct Invalid {};
union Data {
Data();
~Data();
Invalid invalid;
Point point;
MultiPoint multi_point;
LineString line_string;
MultiLineString multi_line_string;
Polygon polygon;
MultiPolygon multi_polygon;
GeometryCollection geometry_collection;
};
Geometry& reset();
void set_point(const Point& point);
void set_multi_point(const MultiPoint& multi_point);
void set_line_string(const LineString& line_string);
void set_multi_line_string(const MultiLineString& multi_line_string);
void set_polygon(const Polygon& polygon);
void set_multi_polygon(const MultiPolygon& multi_polygon);
void set_geometry_collection(const GeometryCollection& geometry_collection);
Geometry& set_geometry(const Geometry& other);
Type type_;
Data data_;
};
/// @cond
bool operator==(const Geometry::Coordinate& lhs, const Geometry::Coordinate& rhs);
bool operator==(const Geometry::Polygon& lhs, const Geometry::Polygon& rhs);
template <Geometry::Type tag>
bool operator==(const Geometry::CoordinateVector<tag>& lhs, const Geometry::CoordinateVector<tag>& rhs) {
return lhs.coordinates == rhs.coordinates;
}
/// @endcond
} // namespace airmap
#endif // AIRMAP_GEOMETRY_H_
#ifndef AIRMAP_LOGGER_H_
#define AIRMAP_LOGGER_H_
#include <airmap/do_not_copy_or_move.h>
#include <iostream>
#include <memory>
namespace airmap {
/// Logger abstracts logging of human-readable message
/// providing details on the operation of the system.
class Logger : DoNotCopyOrMove {
public:
/// Severity enumerates all known levels of severity
enum class Severity { debug = 0, info = 1, error = 2 };
/// debug logs a message from component with Severity::debug.
void debug(const char* message, const char* component);
/// info logs a message from component with Severity::info.
void info(const char* message, const char* component);
/// error logs a message from component with Severity::error.
void error(const char* message, const char* component);
/// log handles the incoming log message originating from component.
/// Implementation should handle the case of component being a nullptr
/// gracefully.
virtual void log(Severity severity, const char* message, const char* component) = 0;
/// should_log should return true if 'message' with 'severity' originating from
/// 'component' should be logged.
///
/// Implementations should handle the case of either message or component being nullptr
/// gracefully.
virtual bool should_log(Severity severity, const char* message, const char* component) = 0;
protected:
Logger() = default;
};
/// operator< returns true iff the numeric value of lhs < rhs.
bool operator<(Logger::Severity lhs, Logger::Severity rhs);
/// operator>> parses severity from in.
std::istream& operator>>(std::istream& in, Logger::Severity& severity);
/// create_default_logger returns a Logger implementation writing
/// log messages to 'out'.
std::shared_ptr<Logger> create_default_logger(std::ostream& out = std::cerr);
/// create_filtering_logger returns a logger that filters out log entries
/// with a severity smaller than the configurated severity.
std::shared_ptr<Logger> create_filtering_logger(Logger::Severity severity, const std::shared_ptr<Logger>& logger);
/// create_null_logger returns a logger that does the equivalent of
/// > /dev/null.
std::shared_ptr<Logger> create_null_logger();
} // namespace airmap
#endif // AIRMAP_LOGGER_H_
\ No newline at end of file
# AirMap Monitor Service {#monitord}
The AirMap monitor service monitors the state of vehicles and takes
action based on changes to this state:
- when the state of a vehicle changes to active:
- create a flight with the AirMap services
- start flight communications
- transmit telemetry updates to AirMap
- receive updates for manned and unmanned aerial traffic relevant to a flight
- when the state of a vehicle changes to inactive:
- stop flight communications
- end flight
The daemon exposes its functionality via a gRPC interface (see
`${AIRMAPD_ROOT}/interfaces/grpc/airmap/monitor/monitor.proto`). Client
applications can either rely on the C++-API avaiable in
`${AIRMAPD_ROOT}/include/airmap/monitor/client.h` or rely on the gRPC
ecosystem to easily connect to the daemon in their choice of language
and runtime. Please see `${AIRMAPD_ROOT/examples/monitor/client.cpp` for
an example of using the C++-API. The following diagram summarizes the overall setup:
![monitord](doc/images/monitord.png)
# Service Configuration
The service is executed with the following command:
```
$ airmap daemon
```
Please note that the service needs exactly one MavLink endpoint to be configured on the command line.
The following endpoint types are supported:
- TCP: Provide `--tcp-endpoint-ip=IP` and `--tcp-endpoint-port=PORT` to `airmap daemon`.
- UDP: Provide `--udp-endpoint-port=PORT` to `airmap daemon`.
- Serial: Provide `--serial-device=PATH/TO/DEVICE` to `airmap daemon`.
The gRPC endpoint exported by the service can be specified with `--grpc-endpoint=ENDPOINT`, defaulting to `0.0.0.0:9090`.
The overall daemon configuration for accessing the AirMap services can be specified with `--config-file=PATH/TO/CONFIG/FILE`.
By default, the config file is expected in `~/.config/airmap/production/config.json`.
\ No newline at end of file
#ifndef AIRMAP_MONITOR_CLIENT_H_
#define AIRMAP_MONITOR_CLIENT_H_
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/traffic.h>
#include <memory>
#include <vector>
namespace airmap {
/// namespace monitor bundles up types and functions to
/// interact with the AirMap monitor daemon.
namespace monitor {
/// Client provides access to the AirMap monitor service.
class Client : DoNotCopyOrMove {
public:
/// Configuration bundles up creation-time parameters of a Client.
struct Configuration {
std::string endpoint; ///< The remote endpoint hosting the service.
std::shared_ptr<Logger> logger; ///< The logger instance.
};
/// Updates models updates delivered to clients.
struct Update {
std::vector<Traffic::Update> traffic; ///< Traffic updates.
};
/// UpdateStream abstracts a source of incoming updates.
class UpdateStream : DoNotCopyOrMove {
public:
/// Reveiver models an entity interested in receiving updates.
class Receiver : DoNotCopyOrMove {
public:
/// handle_update is invoked for every update sent out by the service.
virtual void handle_update(const Update& update) = 0;
};
/// subscribe connects 'receiver' to the stream of updates.
virtual void subscribe(const std::shared_ptr<Receiver>& receiver) = 0;
/// unsubscribe disconnects 'receiver' from the stream of updates.
virtual void unsubscribe(const std::shared_ptr<Receiver>& receiver) = 0;
protected:
UpdateStream() = default;
};
/// ConnectToUpdates bundles up types for calls to Client::connect_to_updates.
struct ConnectToUpdates {
/// Result models the outcome of calling Client::connect_to_updates.
using Result = Outcome<std::shared_ptr<UpdateStream>, Error>;
/// Callback models the async receiver for a call to Client::connect_to_updates.
using Callback = std::function<void(const Result&)>;
};
/// connect_to_updates connects to incoming updates.
virtual void connect_to_updates(const ConnectToUpdates::Callback& cb) = 0;
protected:
Client() = default;
};
} // namespace monitor
} // namespace airmap
/// @example monitor/client.cpp
/// Illustrates how to use airmap::monitor::Client to connect
/// to an AirMap monitor instance.
#endif // AIRMAP_MONITOR_CLIENT_H_
\ No newline at end of file
#ifndef AIRMAP_OPTIONAL_H_
#define AIRMAP_OPTIONAL_H_
#include <iostream>
#include <type_traits>
namespace airmap {
/// Optional manages an optional contained value of type T.
template <typename T>
class Optional {
public:
/// Optional initializes a new instance with no contained value.
Optional() : has_value{false} {
}
/// Optional initializes a new instance with 'other'.
Optional(const Optional& other) : has_value{other.has_value} {
if (has_value)
new (&storage.value) T(other.storage.value);
}
/// Optional initializes a new instance with 'other'.
Optional(Optional<T>&& other) : has_value{other.has_value} {
if (has_value)
new (&storage.value) T(other.storage.value);
}
/// Optional initializes a new instance with 'value'.
Optional(const T& value) : has_value{true} {
new (&storage.value) T(value);
}
/// Optional initializes a new instance with 'value'.
Optional(T&& value) : has_value{true} {
new (&storage.value) T(value);
}
/// ~Optional cleans up the instance and calls the destructor
/// of the contained value if one is set.
~Optional() {
reset();
}
/// @cond
Optional& operator=(const Optional& rhs) {
if (rhs.has_value)
set(rhs.storage.value);
else
reset();
return *this;
}
Optional& operator=(const T& rhs) {
set(rhs);
return *this;
}
Optional& operator=(Optional&& rhs) {
if (rhs.has_value)
set(rhs.storage.value);
else
reset();
return *this;
}
bool operator==(const Optional& rhs) const {
if (has_value != rhs.has_value)
return false;
return has_value && (storage.value == rhs.storage.value);
}
/// @endcond
/// operator bool returns true if this instance contains a value.
explicit operator bool() const {
return has_value;
}
/// get returns an immutable reference to the contained value.
/// If no value is contained in this instance, the result of the call is undefined.
const T& get() const {
return storage.value;
}
/// get returns an immutable reference to the contained value.
/// If no value is contained in this instance, the result of the call is undefined.
T& get() {
return storage.value;
}
/// set adjusts the contained value to 'value'.
void set(const T& value) {
reset();
has_value = true;
new (&storage.value) T(value);
}
/// reset frees up any contained value if one is set.
/// After this call has completed, no value is contained in this Optional instance.
void reset() {
if (has_value)
(&storage.value)->~T();
has_value = false;
}
private:
bool has_value;
union Storage {
Storage() {
}
~Storage() {
}
T value;
} storage;
};
/// operator<< inserts value into out.
template <typename T>
inline std::ostream& operator<<(std::ostream& out, const Optional<T>& value) {
if (value)
out << value.get();
else
out << "not set";
return out;
}
/// @cond
template <typename T>
using Required = Optional<T>;
/// @endcond
} // namespace airmap
#endif // AIRMAP_OPTIONAL_H_
#ifndef AIRMAP_OUTCOME_H_
#define AIRMAP_OUTCOME_H_
#include <type_traits>
namespace airmap {
/// Outcome models a return value from a function XOR an error object
/// describing the error condition if no value can be returned.
template <typename Value, typename Error>
class Outcome {
public:
/// @cond
static_assert(not std::is_same<Value, Error>::value, "Value and Error must not be the same type");
static_assert(std::is_copy_constructible<Value>::value && std::is_move_constructible<Value>::value,
"Value must be copy- and move-constructible");
static_assert(std::is_copy_constructible<Error>::value && std::is_move_constructible<Error>::value,
"Error must be copy- and move-constructible");
/// @endcond
/// Outcome initializes a new instance with value.
explicit Outcome(const Value& value) : type{Type::value} {
new (&data.value) Value{value};
}
/// Outcome initializes a new instance with error.
explicit Outcome(const Error& error) : type{Type::error} {
new (&data.error) Error{error};
}
/// Outcome initializes a new instance with the value or error of 'other'.
Outcome(const Outcome& other) : type{other.type} {
switch (type) {
case Type::error:
new (&data.error) Error{other.data.error};
break;
case Type::value:
new (&data.value) Value{other.data.value};
break;
}
}
/// Outcome initializes a new instance with the value or error of 'other'.
Outcome(Outcome&& other) : type{other.type} {
switch (type) {
case Type::error:
new (&data.error) Error{other.data.error};
break;
case Type::value:
new (&data.value) Value{other.data.value};
break;
}
}
/// Outcome assigns the value or error contained in 'other' to this instance.
Outcome& operator=(const Outcome& other) {
switch (type) {
case Type::error: {
(&data.error)->~Error();
break;
}
case Type::value: {
(&data.value)->~Value();
break;
}
}
type = other.type;
switch (type) {
case Type::error: {
new (&data.error) Error{other.data.error};
break;
}
case Type::value: {
new (&data.value) Value{other.data.value};
break;
}
}
return *this;
}
/// Outcome assigns the value or error contained in 'other' to this instance.
Outcome& operator=(Outcome&& other) {
switch (type) {
case Type::error: {
(&data.error)->~Error();
break;
}
case Type::value: {
(&data.value)->~Value();
break;
}
}
type = other.type;
switch (type) {
case Type::error: {
new (&data.error) Error{other.data.error};
break;
}
case Type::value: {
new (&data.value) Value{other.data.value};
break;
}
}
return *this;
}
/// ~Outcome frees up the contained error or value contained in this instance.
~Outcome() {
switch (type) {
case Type::error:
data.error.~Error();
break;
case Type::value:
data.value.~Value();
break;
}
}
/// operator bool returns true if a value is contained in this instance.
explicit operator bool() const {
return !has_error();
}
/// has_error returns true if this instance carries an error.
inline bool has_error() const {
return type == Type::error;
}
/// has_value returns true if this instance carries a value.
inline bool has_value() const {
return type == Type::value;
}
/// error returns an immutable reference to the Error contained in this instance.
/// The result of this call is undefined if has_error() returns false.
inline const Error& error() const {
return data.error;
}
/// value returns an immutable reference to the Value contained in this instance.
/// The result of this call is undefined if has_value() returns false.
inline const Value& value() const {
return data.value;
}
private:
enum class Type { value, error };
Type type;
union Data {
Data() : value{} {
}
~Data() {
}
Value value;
Error error;
} data;
};
} // namespace airmap
#endif // AIRMAP_OUTCOME_H_
#ifndef AIRMAP_PILOT_H_
#define AIRMAP_PILOT_H_
#include <airmap/aircraft.h>
#include <airmap/date_time.h>
#include <airmap/optional.h>
#include <cstdint>
#include <map>
#include <string>
namespace airmap {
/// Pilot bundles up all properties describing a pilot on the AirMap services.
struct Pilot {
/// Aircraft describes a vehicle owned by a Pilot.
struct Aircraft {
std::string id; ///< The unique id of the vehicle in the context of AirMap.
std::string nick_name; ///< The human-readable nickname of the vehicle.
airmap::Aircraft model; ///< The model of the aircraft.
DateTime created_at; ///< Timestamp marking the creation of the device in the AirMap system.
};
std::string id; ///< The unique id of the pilot in the context of AirMap.
std::string first_name; ///< The first name of the pilot.
std::string last_name; ///< The last name of the pilot.
std::string user_name; ///< The AirMap username of this pilot.
Optional<std::string> picture_url; ///< The URL of a picture showing the pilot.
/// VerificationStatus summarizes the
/// status of contact detail verification.
struct VerificationStatus {
bool email; ///< true iff the email address of the pilot has been verified
bool phone; ///< true iff the phone number of the pilot has been verified
} verification_status;
/// Statistics about the pilot and her
/// flight experience as recorded by the
/// AirMap services.
struct Statistics {
struct Flight {
std::uint64_t total; ///< The total number of flights
DateTime last_flight_time; ///< Date and time of the last flight
} flight; ///< Statistical details about flights conducted by a pilot.
struct Aircraft {
std::uint64_t total; ///< The total number of aircrafts
} aircraft; ///< Statistical details about aircrafts owned by a pilot
} statistics;
/// App- and user-specific metadata.
struct Metadata {
std::map<std::string, std::string> app; ///< App-specific meta-data.
std::map<std::string, std::string> user; ///< User-specific meta-data.
} metadata; ///< Metadata associated with a pilot.
DateTime created_at; ///< Timestamp of the creation of this pilot in the AirMap system.
};
} // namespace airmap
#endif // AIRMAP_PILOT_H_
This diff is collapsed.
#ifndef AIRMAP_QT_CLIENT_H_
#define AIRMAP_QT_CLIENT_H_
#include <airmap/client.h>
#include <airmap/context.h>
#include <airmap/error.h>
#include <airmap/logger.h>
#include <airmap/outcome.h>
#include <QObject>
namespace airmap {
/// @namespace namespace qt bundles up types and functions that help with integrating AirMap functionality
/// into Qt-based applications and libraries.
namespace qt {
/// Client implements the airmap::Client interface, bridging over between
/// the Qt event loop and the native event loop of the native airmap::Client.
///
/// All callback invocations that might happen in the context of a Client instance
/// are dispatched to the Qt applications' main thread.
class Client : public QObject, public airmap::Client {
public:
using CreateResult = Outcome<Client*, Error>;
using CreateCallback = std::function<void(const CreateResult&)>;
/// create creates a new Client instance with parent 'parent', logging to 'logger', using the config
/// 'configuration'. The result of the request is reported to 'cb', on the thread that issued the create request.
///
/// Please note that this function must be called on Qt's main thread as event dispatching between different
/// event loops to the Qt world is set up here.
static void create(const Client::Configuration& configuration, const std::shared_ptr<Logger>& logger, QObject* parent,
const CreateCallback& cb);
~Client();
// From airmap::Client
Authenticator& authenticator() override;
Aircrafts& aircrafts() override;
Airspaces& airspaces() override;
FlightPlans& flight_plans() override;
Flights& flights() override;
Pilots& pilots() override;
RuleSets& rulesets() override;
Status& status() override;
Telemetry& telemetry() override;
Traffic& traffic() override;
private:
/// @cond
struct Private;
Client(std::unique_ptr<Private>&& d, QObject* parent);
std::unique_ptr<Private> d_;
/// @endcond
};
} // namespace qt
} // namespace airmap
/// @example qt/client.cpp
/// Illustrates how to use airmap::qt::Client, airmap::qt::DispatchingLogger and airmap::qt::Logger.
#endif // AIRMAP_QT_CLIENT_H_
#ifndef AIRMAP_QT_LOGGER_H_
#define AIRMAP_QT_LOGGER_H_
#include <airmap/logger.h>
#include <QLoggingCategory>
#include <memory>
namespace airmap {
namespace qt {
/// Logger is an airmap::Logger implementation that uses to
/// Qt's logging facilities.
class Logger : public airmap::Logger {
public:
/// logging_category returns a QLoggingCategory instance
/// that enables calling code to fine-tune logging behavior of a Logger instance.
QLoggingCategory& logging_category();
/// Logger initializes a new instance.
Logger();
/// ~Logger cleans up all resources held by a Logger instance.
~Logger();
// From airmap::Logger
void log(Severity severity, const char* message, const char* component) override;
bool should_log(Severity severity, const char* message, const char* component) override;
private:
struct Private;
std::unique_ptr<Private> d_;
};
/// DispatchingLogger is an airmap::Logger implementation that dispatches to Qt's main
/// event loop for logger invocation
class DispatchingLogger : public airmap::Logger {
public:
/// DispatchingLogger initializes a new instance with 'next'.
DispatchingLogger(const std::shared_ptr<airmap::Logger>& next);
/// ~DispatchingLogging cleans up all resources held a DispatchingLogger instance.
~DispatchingLogger();
// From airmap::Logger
void log(Severity severity, const char* message, const char* component) override;
bool should_log(Severity severity, const char* message, const char* component) override;
private:
struct Private;
std::unique_ptr<Private> d_;
};
} // namespace qt
} // namespace airmap
#endif // AIRMAP_QT_LOGGER_H_
#ifndef AIRMAP_QT_TYPES_H_
#define AIRMAP_QT_TYPES_H_
#include <airmap/aircraft.h>
#include <airmap/airspace.h>
#include <airmap/credentials.h>
#include <airmap/date_time.h>
#include <airmap/flight.h>
#include <airmap/flight_plan.h>
#include <airmap/geometry.h>
#include <airmap/optional.h>
#include <airmap/outcome.h>
#include <airmap/pilot.h>
#include <airmap/rule.h>
#include <airmap/ruleset.h>
#include <airmap/status.h>
#include <airmap/telemetry.h>
#include <airmap/token.h>
#include <airmap/traffic.h>
#include <airmap/version.h>
#include <QMetaType>
Q_DECLARE_METATYPE(airmap::Aircraft)
Q_DECLARE_METATYPE(airmap::Airspace)
Q_DECLARE_METATYPE(airmap::Credentials)
Q_DECLARE_METATYPE(airmap::DateTime)
Q_DECLARE_METATYPE(airmap::Error)
Q_DECLARE_METATYPE(airmap::FlightPlan)
Q_DECLARE_METATYPE(airmap::Flight)
Q_DECLARE_METATYPE(airmap::Geometry)
Q_DECLARE_METATYPE(airmap::Pilot)
Q_DECLARE_METATYPE(airmap::Rule)
Q_DECLARE_METATYPE(airmap::RuleSet)
Q_DECLARE_METATYPE(airmap::RuleSet::Rule)
Q_DECLARE_METATYPE(airmap::Status::Advisory)
Q_DECLARE_METATYPE(airmap::Status::Wind)
Q_DECLARE_METATYPE(airmap::Status::Weather)
Q_DECLARE_METATYPE(airmap::Status::Report)
Q_DECLARE_METATYPE(airmap::Telemetry::Position)
Q_DECLARE_METATYPE(airmap::Telemetry::Speed)
Q_DECLARE_METATYPE(airmap::Telemetry::Attitude)
Q_DECLARE_METATYPE(airmap::Telemetry::Barometer)
Q_DECLARE_METATYPE(airmap::Optional<airmap::Telemetry::Update>)
Q_DECLARE_METATYPE(airmap::Token::Type)
Q_DECLARE_METATYPE(airmap::Token::Anonymous)
Q_DECLARE_METATYPE(airmap::Token::OAuth)
Q_DECLARE_METATYPE(airmap::Token::Refreshed)
Q_DECLARE_METATYPE(airmap::Token)
Q_DECLARE_METATYPE(airmap::Traffic::Update::Type)
Q_DECLARE_METATYPE(airmap::Traffic::Update)
Q_DECLARE_METATYPE(airmap::Version)
namespace airmap {
namespace qt {
/// register_types makes airmap::* types known to the Qt type system.
///
/// This function has to be called at least once to be able to use airmap::*
/// types in queued signal-slot connections.
void register_types();
} // namespace qt
} // namespace airmap
#endif // AIRMAP_QT_TYPES_H_
#ifndef AIRMAP_RULE_H_
#define AIRMAP_RULE_H_
#include <string>
namespace airmap {
struct Rule {
// TODO(tvoss): Fill in values once schema is known.
enum class Type {};
Type type;
std::string id;
std::string name;
std::string description;
std::string jurisdiction;
// TODO(tvoss): Add requirements here.
};
bool operator==(const Rule& lhs, const Rule& rhs);
} // namespace airmap
#endif // AIRMAP_RULE_H_
#ifndef AIRMAP_RULESET_H_
#define AIRMAP_RULESET_H_
#include <airmap/date_time.h>
#include <airmap/geometry.h>
#include <airmap/optional.h>
#include <airmap/pilot.h>
#include <airmap/status.h>
#include <cstdint>
#include <iosfwd>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
namespace airmap {
/// RuleSet bundles together properties describing a ruleset.
struct RuleSet {
// Feature describes a flight feature modelled by a particular rule.
struct Feature;
/// Rule models the individual result of a Rule evaluation.
struct Rule {
/// Status enumerates all known status codes of a rule.
enum class Status {
unknown, ///< The status of the rule is unknown.
conflicting, ///< The rule is conflicting.
not_conflicting, ///< The rule is not conflicting, all good to go.
missing_info, ///< The evaluation requires further information.
informational ///< The rule is of informational nature.
};
Status status; ///< The status of the rule.
std::string short_text; ///< The human-readable short summary of the rule.
std::string description; ///< The human-readable description of the rule.
std::int32_t display_order; ///< An indicator for ordering the ruleset.
std::vector<Feature> features; ///< The features modelled by the rule.
};
/// SelectionType enumerates all known types for a RuleSet.
enum class SelectionType {
pickone, ///< One rule from the overall set needs to be picked.
required, ///< Satisfying the RuleSet is required.
optional ///< Satisfying the RuleSet is not required.
};
/// Jurisdiction describes a jurisdiction in a geographical scope.
struct Jurisdiction {
/// Region enumerates all known regional scopes of a jurisdiction.
enum class Region {
national, ///< The jurisdiction applies nation-wide.
state, ///< The jurisdiction applies to a specific state.
county, ///< The jurisdiction applies to a specific county.
city, ///< The jurisdiction applies to a specific city.
local ///< The jurisdiction only applies locally.
};
/// Id models a unique identifier for a jurisdiction in the context of AirMap.
using Id = std::uint64_t;
Id id; ///< The unique id.
std::string name; ///< The human-readable name.
Region region; ///< The regional scope.
};
/// Id models a unique identifier for a briefing in the context of AirMap.
using Id = std::string;
Id id; ///< The unique id.
SelectionType selection_type; ///< The selection type.
std::string name; ///< The human-readable name.
std::string short_name; ///< The human-readable short name.
std::string description; ///< The human readable description.
bool is_default;
Jurisdiction jurisdiction; ///< The jurisdiction.
std::vector<std::string> airspace_types; ///< The layers that a RuleSet instance applies to.
std::vector<Rule> rules; ///< The individual rules in the set.
struct Feature {
enum class Type { unknown, boolean, floating_point, string };
enum class Measurement { unknown, speed, weight, distance };
enum class Unit { unknown, kilograms, meters, meters_per_sec };
class Value {
public:
Value();
explicit Value(bool value);
explicit Value(double value);
explicit Value(const std::string& value);
Value(const Value& other);
Value(Value&& other);
~Value();
Value& operator=(const Value& other);
Value& operator=(Value&& other);
Type type() const;
bool boolean() const;
double floating_point() const;
const std::string& string() const;
private:
Value& construct(const Value& other);
Value& construct(Value&& other);
Value& construct(bool value);
Value& construct(double value);
Value& construct(const std::string& value);
Value& destruct();
Type type_;
union Detail {
Detail();
~Detail();
bool b;
double d;
std::string s;
} detail_;
};
Optional<Value> value(bool b) const;
Optional<Value> value(double d) const;
Optional<Value> value(const std::string& s) const;
std::int32_t id{-1};
std::string name;
Optional<std::string> code;
std::string description;
RuleSet::Rule::Status status;
Type type{Type::unknown};
Measurement measurement{Measurement::unknown};
Unit unit{Unit::unknown};
};
};
std::ostream& operator<<(std::ostream& out, RuleSet::Feature::Type type);
std::istream& operator>>(std::istream& in, RuleSet::Feature::Type& type);
std::ostream& operator<<(std::ostream& out, RuleSet::Feature::Measurement measurement);
std::istream& operator>>(std::istream& in, RuleSet::Feature::Measurement& measurement);
std::ostream& operator<<(std::ostream& out, RuleSet::Feature::Unit unit);
std::istream& operator>>(std::istream& in, RuleSet::Feature::Unit& unit);
std::ostream& operator<<(std::ostream& out, RuleSet::Jurisdiction::Region region);
std::istream& operator>>(std::istream& in, RuleSet::Jurisdiction::Region& region);
std::ostream& operator<<(std::ostream& out, RuleSet::SelectionType type);
std::istream& operator>>(std::istream& in, RuleSet::SelectionType& type);
std::ostream& operator<<(std::ostream& out, RuleSet::Rule::Status status);
std::istream& operator>>(std::istream& in, RuleSet::Rule::Status& status);
} // namespace airmap
#endif // AIRMAP_RULESET_H_
#ifndef AIRMAP_RULESETS_H_
#define AIRMAP_RULESETS_H_
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/evaluation.h>
#include <airmap/geometry.h>
#include <airmap/outcome.h>
#include <airmap/ruleset.h>
#include <cstdint>
#include <functional>
#include <vector>
namespace airmap {
/// RuleSets provides functionality for managing contextual airspace.
class RuleSets : DoNotCopyOrMove {
public:
/// Search bundles up types to ease interaction with
/// RuleSets::search.
struct Search {
struct Parameters {
Required<Geometry> geometry; ///< Search for rulesets intersecting this geometry.
};
/// Result models the outcome of calling RuleSets::search.
using Result = Outcome<std::vector<RuleSet>, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to RuleSets::search finishes.
using Callback = std::function<void(const Result&)>;
};
/// ForId bundles up types to ease interaction with
/// RuleSets::for_id.
struct ForId {
struct Parameters {
RuleSet::Id id; ///< Search for the ruleset with this id.
};
/// Result models the outcome of calling RuleSets::for_id.
using Result = Outcome<RuleSet, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to RuleSets::for_id finishes.
using Callback = std::function<void(const Result&)>;
};
/// FetchRules bundles up types to ease interaction with
/// RuleSets::fetch_rules.
struct FetchRules {
struct Parameters {
Optional<std::string> rulesets; ///< Fetch rules which apply to these rulesets.
};
/// Result models the outcome of calling RuleSets::fetch_rules.
using Result = Outcome<std::vector<RuleSet>, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to RuleSets::fetch_rules finishes.
using Callback = std::function<void(const Result&)>;
};
/// EvaluateRules bundles up types to ease interaction with
/// RuleSets::evaluate_rulesets.
struct EvaluateRules {
struct Parameters {
Required<Geometry> geometry; ///< Evaluate rulesets intersecting this geometry.
std::unordered_map<std::string, RuleSet::Feature::Value>
features; ///< Additional properties of the planned flight.
Required<std::string> rulesets; ///< Evaluate these rulesets.
};
/// Result models the outcome of calling RuleSets::evaluate_rulesets.
using Result = Outcome<Evaluation, Error>;
/// Callback describes the function signature of the callback that is invoked
/// when a call to RuleSets::evaluate_rulesets finishes.
using Callback = std::function<void(const Result&)>;
};
/// search queries the AirMap services for detailed information about
/// rulesets identified by geometry and reports back results to 'cb'.
virtual void search(const Search::Parameters& parameters, const Search::Callback& cb) = 0;
/// for_id queries the AirMap services for detailed information about
/// a ruleset identified by a UUID and reports back results to 'cb'.
virtual void for_id(const ForId::Parameters& parameters, const ForId::Callback& cb) = 0;
/// fetch_rules fetches rules from the rulesets identified by 'parameters' and
/// reports back results to 'cb'.
virtual void fetch_rules(const FetchRules::Parameters& parameters, const FetchRules::Callback& cb) = 0;
/// evaluate_rulesets evaluates rulesets and geometry identified by 'parameters' and
/// reports back results to 'cb'.
virtual void evaluate_rulesets(const EvaluateRules::Parameters& parameters, const EvaluateRules::Callback& cb) = 0;
protected:
/// @cond
RuleSets() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_RULESETS_H_
#ifndef AIRMAP_STATUS_H_
#define AIRMAP_STATUS_H_
#include <airmap/airspace.h>
#include <airmap/date_time.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/geometry.h>
#include <airmap/optional.h>
#include <airmap/outcome.h>
#include <cstdint>
#include <functional>
#include <iosfwd>
#include <string>
#include <vector>
namespace airmap {
/// Status provides functionality to query airspace and weather information about
/// a geographic area.
class Status : DoNotCopyOrMove {
public:
/// Color enumerates known colors assigned to advisories.
enum class Color { green = 0, yellow = 1, orange = 2, red = 3 };
/// Advisory bundles together airspace information and its evaluation in terms
/// good to fly/needs information or feedback/conflict.
struct Advisory {
Airspace airspace; /// The airspace that the advisory refers to.
Color color; /// The evaluation of the airspace.
};
/// Wind bundles up attributes describing a wind conditions.
struct Wind {
std::uint32_t heading = 0; ///< The heading in [°].
std::uint32_t speed = 0; ///< The speed in [°].
std::uint32_t gusting = 0;
};
/// Weather bundles up attributes describing a weather condition.
struct Weather {
std::string condition; ///< The overall weather condition.
std::string icon; ///< The icon or class of icon that should be used for display purposes.
Wind wind; ///< The details about the current wind conditions.
std::int32_t temperature = 0; ///< The temperature in [°C].
float humidity = 0.0;
std::uint32_t visibility = 0; ///< Visibility in [m].
std::uint32_t precipitation = 0; ///< The probability of precipitation in [%].
};
/// Report summarizes information about a geographic area.
struct Report {
std::uint32_t max_safe_distance = 0; ///< The distance to the area that is considered safe in [m].
Color advisory_color; ///< The overall evaluation of all advisories.
std::vector<Advisory> advisories; ///< All relevant advisories.
Weather weather; ///< The weather conditions.
};
/// GetStatus bundles up types to ease interaction
/// with Status::get_status*.
struct GetStatus {
/// Parameters bundles up input parameters.
struct Parameters {
Required<float> latitude; ///< The latitude of the center point of the query.
Required<float> longitude; ///< The longitude of the center point of the query.
Optional<Airspace::Type> types; ///< Query status information for these types of airspaces.
Optional<Airspace::Type> ignored_types; ///< Ignore these types of airspaces when querying status information.
Optional<bool> weather; ///< If true, weather conditions are included with the status report.
Optional<DateTime> flight_date_time; ///< Time when a flight is going to happen.
Optional<Geometry> geometry; ///< The geometry for the query.
Optional<std::uint32_t> buffer; ///< Buffer around the center point of the query.
};
/// Result models the outcome of calling Status::get_status*.
using Result = Outcome<Report, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Status::get_status* finishes.
using Callback = std::function<void(const Result&)>;
};
/// get_status searches flight advisories for 'parameters' and reports
/// results back to 'cb'.
virtual void get_status_by_point(const GetStatus::Parameters& parameters, const GetStatus::Callback& cb) = 0;
/// get_status searches flight advisories for 'parameters' and reports
/// results back to 'cb'.
virtual void get_status_by_path(const GetStatus::Parameters& parameters, const GetStatus::Callback& cb) = 0;
/// get_status searches flight advisories for 'parameters' and reports
/// results back to 'cb'.
virtual void get_status_by_polygon(const GetStatus::Parameters& parameters, const GetStatus::Callback& cb) = 0;
protected:
/// @cond
Status() = default;
/// @endcond
};
/// @cond
std::ostream& operator<<(std::ostream& out, Status::Color color);
std::istream& operator>>(std::istream& in, Status::Color& color);
/// @endcond
} // namespace airmap
#endif // AIRMAP_STATUS_H_
#ifndef AIRMAP_TELEMETRY_H_
#define AIRMAP_TELEMETRY_H_
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <cstdint>
#include <string>
#include <type_traits>
namespace airmap {
struct Flight;
/// Telemetry provides functionality to submit telemetry updates to the
/// AirMap services during flight.
class Telemetry : DoNotCopyOrMove {
public:
/// Position describes a timestamped geographical position.
struct Position {
std::uint64_t timestamp; ///< Ingestion timestamp of the update.
double latitude; ///< The latitude of the position [°].
double longitude; ///< The longitude of the position in [°].
double altitude_msl; ///< The altitude above mean sea level of the position in [m].
double altitude_gl; ///< The altitude above ground level of the position in [m].
double horizontal_accuracy; ///< The horizontal accuracy of the position in [m].
};
/// Speed describes the timestamped 3-dim velocity of a vehicle.
struct Speed {
std::uint64_t timestamp; ///< Ingestion timestamp of the update.
float velocity_x; ///< The velocity of the vehicle in direction of the x axis in [m/s].
float velocity_y; ///< The velocity of the vehicle in direction of the y axis in [m/s].
float velocity_z; ///< The velocity of the vehicle in direction of the z axis in [m/s].
};
/// Attitude describes the timestamped 3-dim orientation of a vehicle.
struct Attitude {
std::uint64_t timestamp; ///< Ingestion timestamp of the update.
float yaw; ///< The yaw of the vehicle in [°/s].
float pitch; ///< The pitch of the vehicle in [°/s].
float roll; ///< The roll of the vehicle in [°/s].
};
/// Barometer describes the timestamped atmospheric pressurce conditions.
struct Barometer {
std::uint64_t timestamp; ///< Ingestion timestamp of the update.
float pressure; ///< The atmospheric pressure measurement in [Pa].
};
/// @cond
static_assert(std::is_pod<Position>::value, "Position must be a POD");
static_assert(std::is_pod<Speed>::value, "Speed must be a POD");
static_assert(std::is_pod<Attitude>::value, "Attitude must be a POD");
static_assert(std::is_pod<Barometer>::value, "Barometer must be a POD");
/// @endcond
/// Update models an update of the current position, speed, attitude or atmospheric pressure
/// measurement/estimate.
class Update {
public:
/// Type enumerates all known update types.
enum class Type : std::uint8_t {
position = 1, ///< The update contains a Position instance.
speed = 2, ///< The update contains a Speed instance.
attitude = 3, ///< The update contains an Attitude instance.
barometer = 4 ///< The update contains a Barometer instance.
};
/// Update initializes a new instance with 'position'.
explicit Update(const Position& position);
/// Update initializes a new instance with 'speed'.
explicit Update(const Speed& speed);
/// Update initializes a new instance with 'attitude'.
explicit Update(const Attitude& attitude);
/// Update initializes a new instance with 'barometer'.
explicit Update(const Barometer& barometer);
/// type returns the Type of the update contained within this instance.
Type type() const;
/// position returns the position update contained within this instance.
/// The behavior is undefined if type() != Type::position.
const Position& position() const;
/// speed returns the speed update contained within this instance.
/// The behavior is undefined if type() != Type::speed.
const Speed& speed() const;
/// attitude returns the attitde update contained within this instance.
/// The behavior is undefined if type() != Type::attitude.
const Attitude& attitude() const;
/// barometer returns the barometer update contained within this instance.
/// The behavior is undefined if type() != Type::barometer.
const Barometer& barometer() const;
private:
Type type_;
union {
Position position;
Speed speed;
Attitude attitude;
Barometer barometer;
} data_;
};
/// submit_updates sends the telemetry data in 'updates' associated to 'flight' to the AirMap
/// services.
virtual void submit_updates(const Flight& flight, const std::string& key,
const std::initializer_list<Update>& updates) = 0;
protected:
/// @cond
Telemetry() = default;
/// @endcond
};
} // namespace airmap
#endif // AIRMAP_TELEMETRY_H_
#ifndef AIRMAP_TIMESTAMP_H_
#define AIRMAP_TIMESTAMP_H_
#include <airmap/date_time.h>
namespace airmap {
/// Timestamp models a specific point in time.
using Timestamp = DateTime;
} // namespace airmap
#endif // AIRMAP_TIMESTAMP_H_
#ifndef AIRMAP_TOKEN_H_
#define AIRMAP_TOKEN_H_
#include <airmap/optional.h>
#include <chrono>
#include <iosfwd>
#include <string>
namespace airmap {
/// Token models an authentication token required to access the AirMap services.
class Token {
public:
/// Type enumerates all known token types.
enum class Type {
unknown, ///< Marks the unknown token type.
anonymous, ///< The token contains an Anonymous instance.
oauth, ///< The token contains an OAuth instance.
refreshed ///< The token contains a Refreshed instance.
};
/// Anonymous models a token for an anonymous authentication with the AirMap services.
struct Anonymous {
std::string id; ///< The authentication id.
};
/// OAuth models a token for an authentication with OAuth credentials with the AirMap services.
struct OAuth {
enum class Type { bearer };
Type type; ///< The type of the OAuth token.
std::string refresh; ///< The refresh token for subsequent renewal requests.
std::string id; ///< The id token.
std::string access; ///< The access token.
};
/// Refreshed models a token for a refreshed authentication with OAuth credentials with the AirMap services.
struct Refreshed {
OAuth::Type type; ///< The type of the Refreshed token.
std::chrono::seconds expires_in; ///< The token expires in 'expires_in' seconds.
std::string id; ///< The id token.
Optional<OAuth> original_token; ///< The original token used for renewal.
};
/// load_from_json reads a Token instance from the input stream 'in'.
static Token load_from_json(std::istream& in);
/// Token constructs a new invalid instance.
explicit Token();
/// Token constructs a new instance with Type::anonymous.
explicit Token(const Anonymous& anonymous);
/// Token constructs a new instance with Type::oauth.
explicit Token(const OAuth& oauth);
/// Token constructs a new instance with Type::refreshed.
explicit Token(const Refreshed& refreshed);
/// @cond
Token(const Token& token);
Token(Token&& token);
~Token();
Token& operator=(const Token& token);
Token& operator=(Token&& token);
/// @endcond
/// type returns the Type of this Token instance.
Type type() const;
/// id returns the common id of this Token instance.
const std::string& id() const;
/// anonymous returns the details for a Type::anonymous Token instance.
const Anonymous& anonymous() const;
/// anonymous returns the details for a Type::anonymous Token instance.
Anonymous& anonymous();
/// oauth returns the details for a Type::oauth Token instance.
const OAuth& oauth() const;
/// oauth returns the details for a Type::oauth Token instance.
OAuth& oauth();
/// refreshed returns the details for a Type::refreshed Token instance.
const Refreshed& refreshed() const;
/// refreshed returns the details for a Type::refreshed Token instance.
Refreshed& refreshed();
private:
union Data {
Data();
~Data();
Anonymous anonymous;
OAuth oauth;
Refreshed refreshed;
};
Token& construct(const Token& token);
Token& construct(const Anonymous& anonymous);
Token& construct(const OAuth& oauth);
Token& construct(const Refreshed& refreshed);
Token& destruct();
Type type_;
Data data_;
};
/// operator<< inserts type into out.
std::ostream& operator<<(std::ostream& out, Token::Type type);
/// operator>> extracts type from in.
std::istream& operator>>(std::istream& in, Token::Type& type);
/// operator== returns true iff lhs equals rhs.
bool operator==(const Token::OAuth& lhs, const Token::OAuth& rhs);
/// operator== returns true iff lhs equals rhs.
bool operator==(Token::OAuth::Type lhs, Token::OAuth::Type rhs);
/// operator== returns true iff lhs equals rhs.
bool operator==(const Token::Refreshed& lhs, const Token::Refreshed& rhs);
} // namespace airmap
#endif // AIRMAP_TOKEN_H_
#ifndef AIRMAP_TRAFFIC_H_
#define AIRMAP_TRAFFIC_H_
#include <airmap/date_time.h>
#include <airmap/do_not_copy_or_move.h>
#include <airmap/error.h>
#include <airmap/logger.h>
#include <airmap/outcome.h>
#include <functional>
#include <iosfwd>
#include <stdexcept>
#include <string>
#include <vector>
namespace airmap {
/// Traffic provides access to the AirMap situational awareness
/// and traffic alerts.
class Traffic : DoNotCopyOrMove {
public:
/// Update bundles together information about aerial traffic
/// relevant to a UAV flight.
struct Update {
/// Type enumerates all known types of Traffic::Update.
enum class Type {
unknown, ///< Marks the unknown type.
situational_awareness, ///< Marks updates that provide planning information to operators and vehicles.
alert ///< Marks updates about aircrafts that are likely to collide with the current aircraft.
};
std::string id; ///< The unique id of the underlying track in the context of AirMap.
std::string aircraft_id; ///< The 'other' aircraft's id.
double latitude; ///< The latitude of the other aircraft in [°].
double longitude; ///< The longitude of the other aircraft in [°].
double altitude; ///< The altitude of the other aircraft in [m].
double ground_speed; ///< The speed over ground of the other aircraft in [m/s].
double heading; ///< The heading of the other aircraft in [°].
double direction; ///< The direction of the other aircraft in relation to the current aircraft in [°].
DateTime recorded; ///< The time when the datum triggering the udpate was recorded.
DateTime timestamp; ///< The time when the update was generated.
};
/// Monitor models handling of individual subscribers
/// to per-flight alerts and awareness notices.
class Monitor : DoNotCopyOrMove {
public:
/// Parameters bundles up input parameters.
struct Params {
std::string flight_id; ///< The id of the flight for which traffic udpates should be started.
std::string authorization; ///< The authorization token.
};
/// Result models the outcome of calling Traffic::monitor.
using Result = Outcome<std::shared_ptr<Monitor>, Error>;
/// Callback describes the function signature of the callback that is
/// invoked when a call to Traffic::monitor finishes.
using Callback = std::function<void(const Result&)>;
/// Subscriber abstracts handling of batches of Update instances.
class Subscriber {
public:
/// handle_update is invoked when a new batch of Update instances
/// is available.
virtual void handle_update(Update::Type type, const std::vector<Update>& update) = 0;
protected:
Subscriber() = default;
};
/// FunctionalSubscriber is a convenience class that dispatches
/// to a function 'f' for handling batches of Update instances.
class FunctionalSubscriber : public Subscriber {
public:
/// FunctionalSubscriber initializes a new instance with 'f'.
explicit FunctionalSubscriber(const std::function<void(Update::Type, const std::vector<Update>&)>& f);
// From subscriber
void handle_update(Update::Type type, const std::vector<Update>& update) override;
private:
std::function<void(Update::Type, const std::vector<Update>&)> f_;
};
/// LoggingSubscriber is a convenience class that logs incoming batches
/// of Update instances.
class LoggingSubscriber : public Subscriber {
public:
/// LoggingSubscriber initializes an instance with 'component', feeding
/// log entries to 'logger'. Please note that no change of ownership takes
/// place for 'component' and the lifetime of component has to exceed the
/// lifetime of a LoggingSubscriber instance.
explicit LoggingSubscriber(const char* component, const std::shared_ptr<Logger>& logger);
// From Subscriber
void handle_update(Update::Type type, const std::vector<Update>& update) override;
private:
const char* component_;
std::shared_ptr<Logger> logger_;
};
/// subscribe registers 'subscriber' such that subsequent batches of
/// Update instances are delivered to 'subscriber'.
virtual void subscribe(const std::shared_ptr<Subscriber>& subscriber) = 0;
/// unsubscribe unregisters 'subscriber'.
virtual void unsubscribe(const std::shared_ptr<Subscriber>& subscriber) = 0;
protected:
Monitor() = default;
};
/// monitor subscribes the user and flight described in 'params' to
/// the AirMap traffic services and reports the result to 'cb'.
virtual void monitor(const Monitor::Params& params, const Monitor::Callback& cb) = 0;
protected:
/// @cond
Traffic() = default;
/// @endcond
};
/// operator<< inserts a textual representation of type into out.
std::ostream& operator<<(std::ostream& out, Traffic::Update::Type type);
} // namespace airmap
#endif // AIRMAP_TRAFFIC_H_
#ifndef AIRMAP_VERSION_H_
#define AIRMAP_VERSION_H_
#include <airmap/date_time.h>
#include <airmap/optional.h>
#include <cstdint>
namespace airmap {
/// Version bundles up information describing a specific version of the AirMap
/// client library. We follow semantic versioning guidelines (see https://semver.org).
struct Version {
/// current returns an immutable reference to the version of the client library.
static const Version& current();
std::uint32_t major; ///< The major version number.
std::uint32_t minor; ///< The minor version number.
std::uint32_t patch; ///< The patch version number.
Optional<std::string> git_revision; ///< The git revision from which the release was build.
Optional<DateTime> build_timestamp; ///< Marks the time when the library was built.
};
} // namespace airmap
#endif // AIRMAP_VERSION_H_
libairmap-cpp.0.dylib
\ No newline at end of file
libairmap-cpp.0.0.1.dylib
\ No newline at end of file
libairmap-qt.0.dylib
\ No newline at end of file
libairmap-qt.0.0.1.dylib
\ No newline at end of file
......@@ -123,6 +123,7 @@
<file alias="ZoomPlus.svg">src/FlightMap/Images/ZoomPlus.svg</file>
<file alias="ZoomMinus.svg">src/FlightMap/Images/ZoomMinus.svg</file>
<file alias="Help.svg">src/FlightMap/Images/Help.svg</file>
<file alias="Home.svg">src/FlightMap/Images/Home.svg</file>
<file alias="HelpBlack.svg">src/FlightMap/Images/HelpBlack.svg</file>
<file alias="MapAddMission.svg">src/FlightMap/Images/MapAddMission.svg</file>
<file alias="MapAddMissionBlack.svg">src/FlightMap/Images/MapAddMissionBlack.svg</file>
......@@ -171,6 +172,13 @@
<file alias="APM/BrandImageSub">src/FirmwarePlugin/APM/APMBrandImageSub.png</file>
<file alias="PX4/BrandImage">src/FirmwarePlugin/PX4/PX4BrandImage.png</file>
<file alias="subVehicleArrowOpaque.png">src/FlightMap/Images/sub.png</file>
<file alias="advisory-icon.svg">src/Airmap/images/advisory-icon.svg</file>
</qresource>
<qresource prefix="/airmap">
<file alias="advisory-icon.svg">src/Airmap/images/advisory-icon.svg</file>
<file alias="colapse.svg">src/Airmap/images/colapse.svg</file>
<file alias="expand.svg">src/Airmap/images/expand.svg</file>
<file alias="pencil.svg">src/Airmap/images/pencil.svg</file>
</qresource>
<qresource prefix="/res">
<file alias="action.svg">resources/action.svg</file>
......@@ -207,6 +215,7 @@
<file alias="wind-rose-arrow.svg">resources/wind-rose-arrow.svg</file>
<file alias="XDelete.svg">resources/XDelete.svg</file>
<file alias="XDeleteBlack.svg">resources/XDeleteBlack.svg</file>
<file alias="waypoint.svg">resources/waypoint.svg</file>
<file>resources/icons/qgroundcontrol.ico</file>
</qresource>
<qresource prefix="/res/firmware">
......
......@@ -505,6 +505,9 @@ HEADERS += \
src/LogCompressor.h \
src/MG.h \
src/MissionManager/CameraCalc.h \
src/MissionManager/AirspaceController.h \
src/MissionManager/AirMapManager.h \
src/MissionManager/AirspaceManagement.h \
src/MissionManager/CameraSection.h \
src/MissionManager/CameraSpec.h \
src/MissionManager/ComplexMissionItem.h \
......@@ -564,6 +567,7 @@ HEADERS += \
src/QmlControls/RCChannelMonitorController.h \
src/QmlControls/ScreenToolsController.h \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \
src/Settings/AirMapSettings.h \
src/Settings/AppSettings.h \
src/Settings/AutoConnectSettings.h \
src/Settings/BrandImageSettings.h \
......@@ -697,6 +701,9 @@ SOURCES += \
src/JsonHelper.cc \
src/LogCompressor.cc \
src/MissionManager/CameraCalc.cc \
src/MissionManager/AirspaceController.cc \
src/MissionManager/AirMapManager.cc \
src/MissionManager/AirspaceManagement.cc \
src/MissionManager/CameraSection.cc \
src/MissionManager/CameraSpec.cc \
src/MissionManager/ComplexMissionItem.cc \
......@@ -753,6 +760,7 @@ SOURCES += \
src/QmlControls/RCChannelMonitorController.cc \
src/QmlControls/ScreenToolsController.cc \
src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \
src/Settings/AirMapSettings.cc \
src/Settings/AppSettings.cc \
src/Settings/AutoConnectSettings.cc \
src/Settings/BrandImageSettings.cc \
......
......@@ -15,6 +15,10 @@
<file alias="JoystickIndicator.qml">src/ui/toolbar/JoystickIndicator.qml</file>
</qresource>
<qresource prefix="/qml">
<file alias="QGroundControl/Airmap/qmldir">src/Airmap/QGroundControl.Airmap.qmldir</file>
<file alias="QGroundControl/Airmap/AirspaceControl.qml">src/Airmap/AirspaceControl.qml</file>
<file alias="QGroundControl/Airmap/AirspaceRegulation.qml">src/Airmap/AirspaceRegulation.qml</file>
<file alias="AirmapSettings.qml">src/Airmap/AirmapSettings.qml</file>
<file alias="AnalyzeView.qml">src/AnalyzeView/AnalyzeView.qml</file>
<file alias="AppSettings.qml">src/ui/AppSettings.qml</file>
<file alias="BluetoothSettings.qml">src/ui/preferences/BluetoothSettings.qml</file>
......@@ -195,6 +199,7 @@
<file alias="MavCmdInfoRover.json">src/MissionManager/MavCmdInfoRover.json</file>
<file alias="MavCmdInfoSub.json">src/MissionManager/MavCmdInfoSub.json</file>
<file alias="MavCmdInfoVTOL.json">src/MissionManager/MavCmdInfoVTOL.json</file>
<file alias="AirMap.SettingsGroup.json">src/Settings/AirMap.SettingsGroup.json</file>
<file alias="App.SettingsGroup.json">src/Settings/App.SettingsGroup.json</file>
<file alias="AutoConnect.SettingsGroup.json">src/Settings/AutoConnect.SettingsGroup.json</file>
<file alias="FlightMap.SettingsGroup.json">src/Settings/FlightMap.SettingsGroup.json</file>
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="72px" height="72px" viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M36,0C21.089,0,9,12.089,9,27s22.5,45,27,45s27-30.089,27-45S50.911,0,36,0z M36,45c-9.927,0-18-8.077-18-18
S26.073,9,36,9s18,8.077,18,18S45.927,45,36,45z"/>
</svg>
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtMultimedia 5.5
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.MultiVehicleManager 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controllers 1.0
import QGroundControl.SettingsManager 1.0
QGCView {
id: _qgcView
viewPanel: panel
color: qgcPal.window
anchors.fill: parent
anchors.margins: ScreenTools.defaultFontPixelWidth
property real _labelWidth: ScreenTools.defaultFontPixelWidth * 20
property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 30
property real _panelWidth: _qgcView.width * _internalWidthRatio
property Fact _enableAirMapFact: QGroundControl.settingsManager.appSettings.enableAirMap
property bool _airMapEnabled: _enableAirMapFact.rawValue
readonly property real _internalWidthRatio: 0.8
QGCPalette { id: qgcPal }
QGCViewPanel {
id: panel
anchors.fill: parent
QGCFlickable {
clip: true
anchors.fill: parent
contentHeight: settingsColumn.height
contentWidth: settingsColumn.width
Column {
id: settingsColumn
width: _qgcView.width
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.margins: ScreenTools.defaultFontPixelWidth
//-----------------------------------------------------------------
//-- General
Item {
width: _panelWidth
height: generalLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: QGroundControl.settingsManager.unitsSettings.visible
QGCLabel {
id: generalLabel
text: qsTr("General")
font.family: ScreenTools.demiboldFontFamily
}
}
Rectangle {
height: generalCol.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
Column {
id: generalCol
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
FactCheckBox {
text: qsTr("Enable AirMap Services")
fact: _enableAirMapFact
visible: _enableAirMapFact.visible
}
QGCCheckBox {
text: qsTr("Disable Telemetry")
checked: false
enabled: _airMapEnabled
onClicked:
{
}
}
}
}
//-----------------------------------------------------------------
//-- Login / Registration
Item {
width: _panelWidth
height: loginLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: QGroundControl.settingsManager.appSettings.visible
QGCLabel {
id: loginLabel
text: qsTr("Login / Registration")
font.family: ScreenTools.demiboldFontFamily
}
}
Rectangle {
height: loginGrid.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
GridLayout {
id: loginGrid
columns: 2
rowSpacing: ScreenTools.defaultFontPixelHeight * 0.25
anchors.centerIn: parent
QGCLabel { text: qsTr("Email:") }
QGCTextField {
width: _editFieldWidth
enabled: _airMapEnabled
}
QGCLabel { text: qsTr("Password:") }
QGCTextField {
width: _editFieldWidth
enabled: _airMapEnabled
}
Item {
width: 1
height: 1
Layout.columnSpan: 2
}
QGCLabel {
text: qsTr("Forgot Your AirMap Password?")
Layout.alignment: Qt.AlignHCenter
Layout.columnSpan: 2
}
Item {
width: 1
height: 1
Layout.columnSpan: 2
}
QGCButton {
text: qsTr("Register for an AirMap Account")
Layout.alignment: Qt.AlignHCenter
Layout.columnSpan: 2
enabled: _airMapEnabled
}
}
}
//-----------------------------------------------------------------
//-- Pilot Profile
Item {
width: _panelWidth
height: profileLabel.height
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
visible: QGroundControl.settingsManager.appSettings.visible
QGCLabel {
id: profileLabel
text: qsTr("Pilot Profile")
font.family: ScreenTools.demiboldFontFamily
}
}
Rectangle {
height: profileGrid.height + (ScreenTools.defaultFontPixelHeight * 2)
width: _panelWidth
color: qgcPal.windowShade
anchors.margins: ScreenTools.defaultFontPixelWidth
anchors.horizontalCenter: parent.horizontalCenter
GridLayout {
id: profileGrid
columns: 2
columnSpacing: ScreenTools.defaultFontPixelHeight * 2
rowSpacing: ScreenTools.defaultFontPixelWidth * 0.25
anchors.centerIn: parent
QGCLabel { text: qsTr("Name:") }
QGCLabel { text: qsTr("John Doe") }
QGCLabel { text: qsTr("User Name:") }
QGCLabel { text: qsTr("joe36") }
QGCLabel { text: qsTr("Email:") }
QGCLabel { text: qsTr("jonh@doe.com") }
QGCLabel { text: qsTr("Phone:") }
QGCLabel { text: qsTr("+1 212 555 1212") }
}
}
}
}
}
}
This diff is collapsed.
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQml 2.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Airmap 1.0
Item {
id: _root
height: regCol.height
property var textColor: "white"
property var regColor: "white"
property var regTitle: ""
property var regText: ""
Column {
id: regCol
spacing: ScreenTools.defaultFontPixelHeight * 0.5
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.5
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 0.5
Row {
spacing: ScreenTools.defaultFontPixelWidth
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.5
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 0.5
Rectangle {
width: height
height: ScreenTools.defaultFontPixelWidth * 1.5
radius: height * 0.5
color: regColor
anchors.verticalCenter: parent.verticalCenter
}
QGCLabel {
text: regTitle
color: textColor
}
}
QGCLabel {
text: regText
color: textColor
anchors.left: parent.left
anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 0.5
anchors.right: parent.right
anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 0.5
wrapMode: Text.WordWrap
font.pointSize: ScreenTools.smallFontPointSize
}
}
}
Module QGroundControl.Airmap
AirspaceControl 1.0 AirspaceControl.qml
AirspaceRegulation 1.0 AirspaceRegulation.qml
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="72px" height="72px" viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<title>Page 1</title>
<desc>Created with Sketch.</desc>
<g id="Map-Copy-8" transform="translate(-2396.000000, -714.000000)">
<g id="Group-3" transform="translate(2379.000000, 693.000000)">
<path id="Page-1" class="st0" d="M88.463,84.307L57.076,25.426c-0.797-1.46-2.322-2.388-4-2.388c-1.681,0-3.203,0.928-3.978,2.388
L17.532,84.307c-0.753,1.391-0.706,3.095,0.106,4.445c0.822,1.372,2.303,2.21,3.894,2.21h62.95c1.591,0,3.05-0.841,3.869-2.21
C89.17,87.402,89.213,85.701,88.463,84.307L88.463,84.307z M52.995,82.811c-1.876,0-3.395-1.519-3.395-3.396
c0-1.874,1.519-3.396,3.395-3.396s3.398,1.523,3.398,3.396C56.39,81.289,54.871,82.811,52.995,82.811z M56.363,48.674
L54.505,72.04c-0.104,1.499-0.929,2.62-2.188,2.62c-1.258,0-2.083-1.121-2.188-2.62l-1.858-23.367
c-0.096-1.352-0.014-2.576,1.059-3.691c0.861-0.896,1.853-1.568,2.99-1.568s2.126,0.671,2.99,1.568
C56.377,46.097,56.459,47.322,56.363,48.674L56.363,48.674z"/>
</g>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" enable-background="new 0 0 72 72" xml:space="preserve">
<g>
<polygon points="70.2,41.7 36,1.797 1.8,41.7 10.35,41.7 10.35,70.203 27.45,70.203 27.45,47.401 44.55,47.401 44.55,70.203
61.65,70.203 61.65,41.7 "/>
</g>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="72px" height="36px" viewBox="0 0 72 36" style="enable-background:new 0 0 72 36;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
<polyline class="st0" points="3.6,34 36,1.6 68.4,34 "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="72px" height="36px" viewBox="0 0 72 36" style="enable-background:new 0 0 72 36;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#FFFFFF;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
<polyline class="st0" points="3.6,1.6 36,34 68.4,1.6 "/>
</svg>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="72px" height="72px" viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M60.299,0.003c-3.006,0-6.011,1.132-8.285,3.41l-0.011,0.011L7.931,48.217L0,71.997l23.781-7.931l0.492-0.481
l44.311-43.59v-0.011c4.553-4.553,4.556-12.023,0-16.571C66.308,1.137,63.304,0.003,60.299,0.003z M60.299,5.828
c1.493,0,2.986,0.571,4.143,1.728c2.311,2.307,2.314,5.971,0,8.285l-4.623,4.555c-0.651-1.589-1.671-3.273-3.307-4.909
c-1.633-1.633-3.32-2.647-4.909-3.296l4.578-4.646C57.33,6.402,58.814,5.828,60.299,5.828z M47.733,17.157
c1.084,0.091,2.652,0.489,4.635,2.472c1.986,1.986,2.4,3.556,2.495,4.635c0.072,0.818-0.029,0.933-0.08,1.076L24.513,55.129
c-0.652-1.448-1.65-2.977-3.159-4.486c-1.509-1.509-3.038-2.506-4.486-3.159l29.777-30.258
C46.796,17.179,46.916,17.088,47.733,17.157z M12.84,52.348c0.909,0.072,2.359,0.425,4.372,2.438
c2.012,2.012,2.366,3.462,2.438,4.372c0.008,0.099-0.015,0.033-0.011,0.114l-5.585,1.865c-0.438-0.566-0.917-1.135-1.488-1.705
c-0.567-0.567-1.139-1.04-1.705-1.476l1.865-5.596C12.807,52.362,12.741,52.34,12.84,52.348z"/>
</svg>
......@@ -626,4 +626,51 @@ QGCView {
visible: false
}
}
//-- Airspace Indicator
Rectangle {
id: airspaceIndicator
width: airspaceRow.width + (ScreenTools.defaultFontPixelWidth * 3)
height: airspaceRow.height * 1.25
color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(1,1,1,0.95) : Qt.rgba(0,0,0,0.75)
visible: _mainIsMap && flightPermit && flightPermit !== AirspaceAuthorization.PermitUnknown && !messageArea.visible && !criticalMmessageArea.visible
radius: 3
border.width: 1
border.color: qgcPal.globalTheme === QGCPalette.Light ? Qt.rgba(0,0,0,0.35) : Qt.rgba(1,1,1,0.35)
anchors.top: parent.top
anchors.topMargin: ScreenTools.toolbarHeight + (ScreenTools.defaultFontPixelHeight * 0.25)
anchors.horizontalCenter: parent.horizontalCenter
Row {
id: airspaceRow
spacing: ScreenTools.defaultFontPixelWidth
anchors.centerIn: parent
QGCLabel { text: airspaceIndicator.providerName+":"; anchors.verticalCenter: parent.verticalCenter; }
QGCLabel {
text: {
if(airspaceIndicator.flightPermit) {
if(airspaceIndicator.flightPermit === AirspaceAuthorization.PermitPending)
return qsTr("Approval Pending")
if(airspaceIndicator.flightPermit === AirspaceAuthorization.PermitAccepted)
return qsTr("Flight Approved")
if(airspaceIndicator.flightPermit === AirspaceAuthorization.PermitRejected)
return qsTr("Flight Rejected")
}
return ""
}
color: {
if(airspaceIndicator.flightPermit) {
if(airspaceIndicator.flightPermit === AirspaceAuthorization.PermitPending)
return qgcPal.colorOrange
if(airspaceIndicator.flightPermit === AirspaceAuthorization.PermitAccepted)
return qgcPal.colorGreen
}
return qgcPal.colorRed
}
anchors.verticalCenter: parent.verticalCenter;
}
}
property var flightPermit: _activeVehicle ? _activeVehicle.flightPermitStatus : null
property var providerName: _activeVehicle ? _activeVehicle.airspaceController.providerName : ""
}
}
......@@ -57,7 +57,12 @@ FlightMap {
// Track last known map position and zoom from Fly view in settings
onZoomLevelChanged: QGroundControl.flightMapZoom = zoomLevel
onCenterChanged: QGroundControl.flightMapPosition = center
onCenterChanged: {
if(_activeVehicle) {
_activeVehicle.airspaceController.setROI(center, 5000)
}
QGroundControl.flightMapPosition = center
}
// When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires
onUserPannedChanged: {
......@@ -323,4 +328,26 @@ FlightMap {
}
]
}
// Airspace overlap support
MapItemView {
model: _activeVehicle ? _activeVehicle.airspaceController.circles : []
delegate: MapCircle {
center: object.center
radius: object.radius
border.color: "white"
color: "yellow"
opacity: 0.25
}
}
MapItemView {
model: _activeVehicle ? _activeVehicle.airspaceController.polygons : []
delegate: MapPolygon {
border.color: "white"
color: "yellow"
opacity: 0.25
path: object.polygon
}
}
}
......@@ -15,23 +15,26 @@ import QtLocation 5.3
import QtPositioning 5.3
import QtQuick.Layouts 1.2
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl 1.0
import QGroundControl.ScreenTools 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Vehicle 1.0
import QGroundControl.FlightMap 1.0
import QGroundControl.Airmap 1.0
Item {
id: _root
id: widgetRoot
property var qgcView
property bool useLightColors
property var missionController
property bool showValues: true
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property bool _isSatellite: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true
property bool _lightWidgetBorders: _isSatellite
property bool _enableAirMap: QGroundControl.settingsManager.appSettings.enableAirMap.rawValue
readonly property real _margins: ScreenTools.defaultFontPixelHeight * 0.5
......@@ -51,28 +54,14 @@ Item {
if(QGroundControl.corePlugin.options.instrumentWidget) {
if(QGroundControl.corePlugin.options.instrumentWidget.source.toString().length) {
instrumentsLoader.source = QGroundControl.corePlugin.options.instrumentWidget.source
switch(QGroundControl.corePlugin.options.instrumentWidget.widgetPosition) {
case CustomInstrumentWidget.POS_TOP_RIGHT:
instrumentsLoader.state = "topMode"
break;
case CustomInstrumentWidget.POS_BOTTOM_RIGHT:
instrumentsLoader.state = "bottomMode"
break;
case CustomInstrumentWidget.POS_CENTER_RIGHT:
default:
instrumentsLoader.state = "centerMode"
break;
}
} else {
// Note: We currently show alternate instruments all the time. This is a trial change for daily builds.
// Leaving non-alternate code in for now in case the trial fails.
var useAlternateInstruments = true//QGroundControl.settingsManager.appSettings.virtualJoystick.value || ScreenTools.isTinyScreen
if(useAlternateInstruments) {
instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidgetAlternate.qml"
instrumentsLoader.state = "topMode"
} else {
instrumentsLoader.source = "qrc:/qml/QGCInstrumentWidget.qml"
instrumentsLoader.state = QGroundControl.settingsManager.appSettings.showLargeCompass.value == 1 ? "centerMode" : "topMode"
}
}
} else {
......@@ -130,43 +119,31 @@ Item {
text: "The vehicle has failed a pre-arm check. In order to arm the vehicle, resolve the failure or disable the arming check via the Safety tab on the Vehicle Setup page."
}
}
//-- Instrument Panel
Loader {
id: instrumentsLoader
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
Column {
id: instrumentsColumn
spacing: ScreenTools.defaultFontPixelHeight * 0.25
anchors.top: parent.top
anchors.topMargin: QGroundControl.corePlugin.options.instrumentWidget.widgetTopMargin + (ScreenTools.defaultFontPixelHeight * 0.5)
anchors.margins: ScreenTools.defaultFontPixelHeight * 0.5
anchors.right: parent.right
z: QGroundControl.zOrderWidgets
property var qgcView: _root.qgcView
property real maxHeight:parent.height - (anchors.margins * 2)
states: [
State {
name: "topMode"
AnchorChanges {
target: instrumentsLoader
anchors.verticalCenter: undefined
anchors.bottom: undefined
anchors.top: _root ? _root.top : undefined
}
},
State {
name: "centerMode"
AnchorChanges {
target: instrumentsLoader
anchors.top: undefined
anchors.bottom: undefined
anchors.verticalCenter: _root ? _root.verticalCenter : undefined
}
},
State {
name: "bottomMode"
AnchorChanges {
target: instrumentsLoader
anchors.top: undefined
anchors.verticalCenter: undefined
anchors.bottom: _root ? _root.bottom : undefined
}
//-------------------------------------------------------
// Airmap Airspace Control
AirspaceControl {
id: airspaceControl
width: getPreferredInstrumentWidth()
visible: _enableAirMap
anchors.margins: ScreenTools.defaultFontPixelHeight * 0.5
onColapsedChanged: {
widgetRoot.showValues = colapsed
}
]
}
//-------------------------------------------------------
//-- Instrument Panel
Loader {
id: instrumentsLoader
anchors.margins: ScreenTools.defaultFontPixelHeight * 0.5
property var qgcView: widgetRoot.qgcView
property real maxHeight: widgetRoot ? widgetRoot.height - instrumentsColumn.y - airspaceControl.height - (ScreenTools.defaultFontPixelHeight * 4) : 0
}
}
}
......@@ -66,6 +66,7 @@ Rectangle {
anchors.top: parent.bottom
width: parent.width
height: _valuesWidget.height
visible: widgetRoot.showValues
Rectangle {
anchors.fill: _valuesWidget
......
......@@ -45,10 +45,11 @@ bool JsonHelper::validateRequiredKeys(const QJsonObject& jsonObject, const QStri
return true;
}
bool JsonHelper::loadGeoCoordinate(const QJsonValue& jsonValue,
bool altitudeRequired,
QGeoCoordinate& coordinate,
QString& errorString)
bool JsonHelper::_loadGeoCoordinate(const QJsonValue& jsonValue,
bool altitudeRequired,
QGeoCoordinate& coordinate,
QString& errorString,
bool geoJsonFormat)
{
if (!jsonValue.isArray()) {
errorString = QObject::tr("value for coordinate is not array");
......@@ -69,7 +70,11 @@ bool JsonHelper::loadGeoCoordinate(const QJsonValue& jsonValue,
}
}
coordinate = QGeoCoordinate(possibleNaNJsonValue(coordinateArray[0]), possibleNaNJsonValue(coordinateArray[1]));
if (geoJsonFormat) {
coordinate = QGeoCoordinate(coordinateArray[1].toDouble(), coordinateArray[0].toDouble());
} else {
coordinate = QGeoCoordinate(possibleNaNJsonValue(coordinateArray[0]), possibleNaNJsonValue(coordinateArray[1]));
}
if (altitudeRequired) {
coordinate.setAltitude(possibleNaNJsonValue(coordinateArray[2]));
}
......@@ -77,13 +82,18 @@ bool JsonHelper::loadGeoCoordinate(const QJsonValue& jsonValue,
return true;
}
void JsonHelper::saveGeoCoordinate(const QGeoCoordinate& coordinate,
bool writeAltitude,
QJsonValue& jsonValue)
void JsonHelper::_saveGeoCoordinate(const QGeoCoordinate& coordinate,
bool writeAltitude,
QJsonValue& jsonValue,
bool geoJsonFormat)
{
QJsonArray coordinateArray;
coordinateArray << coordinate.latitude() << coordinate.longitude();
if (geoJsonFormat) {
coordinateArray << coordinate.longitude() << coordinate.latitude();
} else {
coordinateArray << coordinate.latitude() << coordinate.longitude();
}
if (writeAltitude) {
coordinateArray << coordinate.altitude();
}
......@@ -91,6 +101,37 @@ void JsonHelper::saveGeoCoordinate(const QGeoCoordinate& coordinate,
jsonValue = QJsonValue(coordinateArray);
}
bool JsonHelper::loadGeoCoordinate(const QJsonValue& jsonValue,
bool altitudeRequired,
QGeoCoordinate& coordinate,
QString& errorString,
bool geoJsonFormat)
{
return _loadGeoCoordinate(jsonValue, altitudeRequired, coordinate, errorString, geoJsonFormat);
}
void JsonHelper::saveGeoCoordinate(const QGeoCoordinate& coordinate,
bool writeAltitude,
QJsonValue& jsonValue)
{
_saveGeoCoordinate(coordinate, writeAltitude, jsonValue, false /* geoJsonFormat */);
}
bool JsonHelper::loadGeoJsonCoordinate(const QJsonValue& jsonValue,
bool altitudeRequired,
QGeoCoordinate& coordinate,
QString& errorString)
{
return _loadGeoCoordinate(jsonValue, altitudeRequired, coordinate, errorString, true /* geoJsonFormat */);
}
void JsonHelper::saveGeoJsonCoordinate(const QGeoCoordinate& coordinate,
bool writeAltitude,
QJsonValue& jsonValue)
{
_saveGeoCoordinate(coordinate, writeAltitude, jsonValue, true /* geoJsonFormat */);
}
bool JsonHelper::validateKeyTypes(const QJsonObject& jsonObject, const QStringList& keys, const QList<QJsonValue::Type>& types, QString& errorString)
{
for (int i=0; i<types.count(); i++) {
......@@ -344,7 +385,7 @@ bool JsonHelper::loadPolygon(const QJsonArray& polygonArray, QmlObjectListModel&
const QJsonValue& pointValue = polygonArray[i];
QGeoCoordinate pointCoord;
if (!JsonHelper::loadGeoCoordinate(pointValue, false /* altitudeRequired */, pointCoord, errorString)) {
if (!JsonHelper::loadGeoCoordinate(pointValue, false /* altitudeRequired */, pointCoord, errorString, true)) {
list.clearAndDeleteContents();
return false;
}
......
......@@ -64,11 +64,33 @@ public:
static bool validateKeys(const QJsonObject& jsonObject, const QList<KeyValidateInfo>& keyInfo, QString& errorString);
/// Loads a QGeoCoordinate
/// Stored as array [ lat, lon, alt ]
/// @return false: validation failed
static bool loadGeoCoordinate(const QJsonValue& jsonValue, ///< json value to load from
bool altitudeRequired, ///< true: altitude must be specified
QGeoCoordinate& coordinate, ///< returned QGeoCordinate
QString& errorString); ///< returned error string if load failure
static bool loadGeoCoordinate(const QJsonValue& jsonValue, ///< json value to load from
bool altitudeRequired, ///< true: altitude must be specified
QGeoCoordinate& coordinate, ///< returned QGeoCordinate
QString& errorString, ///< returned error string if load failure
bool geoJsonFormat = false); ///< if true, use [lon, lat], [lat, lon] otherwise
/// Saves a QGeoCoordinate
/// Stored as array [ lat, lon, alt ]
static void saveGeoCoordinate(const QGeoCoordinate& coordinate, ///< QGeoCoordinate to save
bool writeAltitude, ///< true: write altitude to json
QJsonValue& jsonValue); ///< json value to save to
/// Loads a QGeoCoordinate
/// Stored as array [ lon, lat, alt ]
/// @return false: validation failed
static bool loadGeoJsonCoordinate(const QJsonValue& jsonValue, ///< json value to load from
bool altitudeRequired, ///< true: altitude must be specified
QGeoCoordinate& coordinate, ///< returned QGeoCordinate
QString& errorString); ///< returned error string if load failure
/// Saves a QGeoCoordinate
/// Stored as array [ lon, lat, alt ]
static void saveGeoJsonCoordinate(const QGeoCoordinate& coordinate, ///< QGeoCoordinate to save
bool writeAltitude, ///< true: write altitude to json
QJsonValue& jsonValue); ///< json value to save to
/// Loads a polygon from an array
static bool loadPolygon(const QJsonArray& polygonArray, ///< Array of coordinates
......@@ -76,11 +98,6 @@ public:
QObject* parent, ///< parent for newly allocated QGCQGeoCoordinates
QString& errorString); ///< returned error string if load failure
/// Saves a QGeoCoordinate
static void saveGeoCoordinate(const QGeoCoordinate& coordinate, ///< QGeoCoordinate to save
bool writeAltitude, ///< true: write altitude to json
QJsonValue& jsonValue); ///< json value to save to
/// Loads a list of QGeoCoordinates from a json array
/// @return false: validation failed
static bool loadGeoCoordinateArray(const QJsonValue& jsonValue, ///< json value which contains points
......@@ -116,6 +133,15 @@ public:
private:
static QString _jsonValueTypeToString(QJsonValue::Type type);
static bool _loadGeoCoordinate(const QJsonValue& jsonValue,
bool altitudeRequired,
QGeoCoordinate& coordinate,
QString& errorString,
bool geoJsonFormat);
static void _saveGeoCoordinate(const QGeoCoordinate& coordinate,
bool writeAltitude,
QJsonValue& jsonValue,
bool geoJsonFormat);
static const char* _enumStringsJsonKey;
static const char* _enumValuesJsonKey;
......
This diff is collapsed.
This diff is collapsed.
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "AirspaceController.h"
#include "AirspaceManagement.h"
#include "QGCApplication.h"
#include "QGCQGeoCoordinate.h"
AirspaceController::AirspaceController(QObject* parent)
: QObject(parent)
, _manager(qgcApp()->toolbox()->airspaceManager())
{
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#pragma once
#include "AirspaceManagement.h"
#include "QGCMapPolygon.h"
class AirspaceController : public QObject
{
Q_OBJECT
public:
AirspaceController(QObject* parent = NULL);
~AirspaceController() = default;
Q_PROPERTY(QmlObjectListModel* polygons READ polygons CONSTANT) ///< List of PolygonAirspaceRestriction objects
Q_PROPERTY(QmlObjectListModel* circles READ circles CONSTANT) ///< List of CircularAirspaceRestriction objects
Q_INVOKABLE void setROI(QGeoCoordinate center, double radius) { _manager->setROI(center, radius); }
QmlObjectListModel* polygons() { return _manager->polygonRestrictions(); }
QmlObjectListModel* circles() { return _manager->circularRestrictions(); }
Q_PROPERTY(QString providerName READ providerName CONSTANT)
QString providerName() { return _manager->name(); }
private:
AirspaceManager* _manager;
};
/****************************************************************************
*
* (c) 2017 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "AirspaceManagement.h"
#include <Vehicle.h>
QGC_LOGGING_CATEGORY(AirspaceManagementLog, "AirspaceManagementLog")
AirspaceRestriction::AirspaceRestriction(QObject* parent)
: QObject(parent)
{
}
PolygonAirspaceRestriction::PolygonAirspaceRestriction(const QVariantList& polygon, QObject* parent)
: AirspaceRestriction(parent)
, _polygon(polygon)
{
}
CircularAirspaceRestriction::CircularAirspaceRestriction(const QGeoCoordinate& center, double radius, QObject* parent)
: AirspaceRestriction(parent)
, _center(center)
, _radius(radius)
{
}
AirspaceManager::AirspaceManager(QGCApplication* app, QGCToolbox* toolbox)
: QGCTool(app, toolbox)
{
_roiUpdateTimer.setInterval(2000);
_roiUpdateTimer.setSingleShot(true);
connect(&_roiUpdateTimer, &QTimer::timeout, this, &AirspaceManager::_updateToROI);
qmlRegisterUncreatableType<AirspaceAuthorization>("QGroundControl", 1, 0, "AirspaceAuthorization", "Reference only");
qRegisterMetaType<WeatherInformation>();
}
AirspaceManager::~AirspaceManager()
{
if (_restrictionsProvider) {
delete _restrictionsProvider;
}
_polygonRestrictions.clearAndDeleteContents();
_circleRestrictions.clearAndDeleteContents();
}
void AirspaceManager::setToolbox(QGCToolbox* toolbox)
{
QGCTool::setToolbox(toolbox);
// we should not call virtual methods in the constructor, so we instantiate the restriction provider here
_restrictionsProvider = instantiateRestrictionProvider();
if (_restrictionsProvider) {
connect(_restrictionsProvider, &AirspaceRestrictionProvider::requestDone, this,
&AirspaceManager::_restrictionsUpdated);
}
}
void AirspaceManager::setROI(const QGeoCoordinate& center, double radiusMeters)
{
_roiCenter = center;
_roiRadius = radiusMeters;
_roiUpdateTimer.start();
}
void AirspaceManager::_updateToROI()
{
if (_restrictionsProvider) {
_restrictionsProvider->setROI(_roiCenter, _roiRadius);
}
}
void AirspaceManager::_restrictionsUpdated(bool success)
{
_polygonRestrictions.clearAndDeleteContents();
_circleRestrictions.clearAndDeleteContents();
if (success) {
for (const auto& circle : _restrictionsProvider->circles()) {
_circleRestrictions.append(circle);
}
for (const auto& polygon : _restrictionsProvider->polygons()) {
_polygonRestrictions.append(polygon);
}
} else {
// TODO: show error?
}
}
AirspaceManagerPerVehicle::AirspaceManagerPerVehicle(const Vehicle& vehicle)
: _vehicle(vehicle)
{
connect(&_vehicle, &Vehicle::armedChanged, this, &AirspaceManagerPerVehicle::_vehicleArmedChanged);
connect(&_vehicle, &Vehicle::mavlinkMessageReceived, this, &AirspaceManagerPerVehicle::vehicleMavlinkMessageReceived);
}
void AirspaceManagerPerVehicle::_vehicleArmedChanged(bool armed)
{
if (armed) {
startTelemetryStream();
_vehicleWasInMissionMode = _vehicle.flightMode() == _vehicle.missionFlightMode();
} else {
stopTelemetryStream();
// end the flight if we were in mission mode during arming or disarming
// TODO: needs to be improved. for instance if we do RTL and then want to continue the mission...
if (_vehicleWasInMissionMode || _vehicle.flightMode() == _vehicle.missionFlightMode()) {
endFlight();
}
}
}
This diff is collapsed.
......@@ -11,6 +11,7 @@
#include "Vehicle.h"
#include "QmlObjectListModel.h"
#include "ParameterManager.h"
#include "QGCApplication.h"
#include "QGCMapPolygon.h"
#include "QGCMapCircle.h"
......@@ -20,6 +21,7 @@ GeoFenceManager::GeoFenceManager(Vehicle* vehicle)
: _vehicle (vehicle)
, _planManager (vehicle, MAV_MISSION_TYPE_FENCE)
, _firstParamLoadComplete (false)
, _airspaceManager (qgcApp()->toolbox()->airspaceManager())
{
connect(&_planManager, &PlanManager::inProgressChanged, this, &GeoFenceManager::inProgressChanged);
connect(&_planManager, &PlanManager::error, this, &GeoFenceManager::error);
......
......@@ -13,6 +13,7 @@
#include <QObject>
#include <QGeoCoordinate>
#include "AirspaceManagement.h"
#include "QGCLoggingCategory.h"
#include "FactSystem.h"
#include "PlanManager.h"
......@@ -96,6 +97,7 @@ private:
bool _firstParamLoadComplete;
QList<QGCFencePolygon> _sendPolygons;
QList<QGCFenceCircle> _sendCircles;
AirspaceManager* _airspaceManager;
};
#endif
......@@ -78,6 +78,14 @@ void PlanManager::writeMissionItems(const QList<MissionItem*>& missionItems)
return;
}
if (_planType == MAV_MISSION_TYPE_MISSION) {
// upload the flight to the airspace management backend
AirspaceManagerPerVehicle* airspaceManager = _vehicle->airspaceManager();
if (airspaceManager) {
airspaceManager->createFlight(missionItems);
}
}
_clearAndDeleteWriteMissionItems();
bool skipFirstItem = _planType == MAV_MISSION_TYPE_MISSION && !_vehicle->firmwarePlugin()->sendHomePositionToVehicle();
......
......@@ -42,7 +42,7 @@ QGCFlickable {
anchors.left: parent.left
anchors.top: parent.top
text: qsTr("GeoFence")
color: "black"
anchors.leftMargin: ScreenTools.defaultFontPixelWidth
}
Rectangle {
......
This diff is collapsed.
This diff is collapsed.
......@@ -28,7 +28,6 @@ QGCFlickable {
anchors.left: parent.left
anchors.top: parent.top
text: qsTr("Rally Points")
color: "black"
}
Rectangle {
......
This diff is collapsed.
......@@ -84,6 +84,7 @@
#include "CameraCalc.h"
#include "VisualMissionItem.h"
#include "EditPositionDialogController.h"
#include "AirspaceController.h"
#ifndef NO_SERIAL_LINK
#include "SerialLink.h"
......@@ -373,6 +374,7 @@ void QGCApplication::_initCommon(void)
qmlRegisterUncreatableType<ParameterManager> ("QGroundControl.Vehicle", 1, 0, "ParameterManager", "Reference only");
qmlRegisterUncreatableType<QGCCameraManager> ("QGroundControl.Vehicle", 1, 0, "QGCCameraManager", "Reference only");
qmlRegisterUncreatableType<QGCCameraControl> ("QGroundControl.Vehicle", 1, 0, "QGCCameraControl", "Reference only");
qmlRegisterUncreatableType<AirspaceController> ("QGroundControl.Vehicle", 1, 0, "AirspaceController", "Reference only");
qmlRegisterUncreatableType<JoystickManager> ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only");
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
qmlRegisterUncreatableType<QGCPositionManager> ("QGroundControl.QGCPositionManager", 1, 0, "QGCPositionManager", "Reference only");
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -10,6 +10,7 @@ Rectangle {
id: _root
height: pageFlickable.y + pageFlickable.height + _margins
color: qgcPal.window
radius: ScreenTools.defaultFontPixelWidth * 0.5
property var qgcView ///< QGCView to use for showing dialogs
property real maxHeight ///< Maximum height that should be taken, smaller than this is ok
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment