3#include <QtPositioning/QGeoPositionInfo>
21 , _gcsMotionReportTimer(new QTimer(this))
25 _gcsMotionReportTimer->setSingleShot(
false);
29 _gcsMotionReportTimer->setInterval(kMotionUpdateInterval);
39 return _followMeInstance();
44 static bool once =
false;
46 (void) connect(_gcsMotionReportTimer, &QTimer::timeout,
this, &FollowMe::_sendGCSMotionReport);
54void FollowMe::_settingsChanged(QVariant value)
56 _currentMode =
static_cast<FollowMode
>(value.toUInt());
58 switch (_currentMode) {
72 _enableIfVehicleInFollow();
77void FollowMe::_enableFollowSend()
79 if (!_gcsMotionReportTimer->isActive()) {
80 _gcsMotionReportTimer->start();
84void FollowMe::_disableFollowSend()
86 if (_gcsMotionReportTimer->isActive()) {
87 _gcsMotionReportTimer->stop();
91void FollowMe::_sendGCSMotionReport()
93 const auto observation =
98 const auto& geoPositionInfo = observation->position;
99 const QGeoCoordinate gcsCoordinate = geoPositionInfo.coordinate();
102 bool needFollowMe =
false;
103 if (_currentMode == MODE_ALWAYS) {
105 }
else if (_currentMode == MODE_FOLLOWME) {
107 for (
int i = 0; i < vehicles->
count(); i++) {
109 if (vehicle && _isFollowFlightMode(vehicle, vehicle->
flightMode())) {
118 GCSMotionReport motionReport{};
119 uint8_t estimationCapabilities = 0;
121 motionReport.lat_int =
static_cast<int>(gcsCoordinate.latitude() * 1e7);
122 motionReport.lon_int =
static_cast<int>(gcsCoordinate.longitude() * 1e7);
123 motionReport.altMetersAMSL = gcsCoordinate.altitude();
124 estimationCapabilities |= (1 <<
POS);
126 if (geoPositionInfo.hasAttribute(QGeoPositionInfo::Direction)) {
127 estimationCapabilities |= (1 <<
HEADING);
128 motionReport.headingDegrees = geoPositionInfo.attribute(QGeoPositionInfo::Direction);
131 if (geoPositionInfo.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) {
132 motionReport.pos_std_dev[0] = motionReport.pos_std_dev[1] = geoPositionInfo.attribute(QGeoPositionInfo::HorizontalAccuracy);
135 if (geoPositionInfo.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) {
136 motionReport.pos_std_dev[2] = geoPositionInfo.attribute(QGeoPositionInfo::VerticalAccuracy);
139 if (geoPositionInfo.hasAttribute(QGeoPositionInfo::VerticalSpeed)) {
140 motionReport.vzMetersPerSec = geoPositionInfo.attribute(QGeoPositionInfo::VerticalSpeed);
143 if (geoPositionInfo.hasAttribute(QGeoPositionInfo::Direction) && geoPositionInfo.hasAttribute(QGeoPositionInfo::GroundSpeed)) {
144 estimationCapabilities |= (1 <<
VEL);
146 const qreal direction = qDegreesToRadians(geoPositionInfo.attribute(QGeoPositionInfo::Direction));
147 const qreal velocity = geoPositionInfo.attribute(QGeoPositionInfo::GroundSpeed);
149 motionReport.vxMetersPerSec = cos(direction) * velocity;
150 motionReport.vyMetersPerSec = sin(direction) * velocity;
152 motionReport.vxMetersPerSec = 0;
153 motionReport.vyMetersPerSec = 0;
158 for (
int i = 0; i < vehicles->
count(); i++) {
160 if (vehicle && ((_currentMode == MODE_ALWAYS) || (_isFollowFlightMode(vehicle, vehicle->
flightMode())))) {
161 qCDebug(FollowMeLog) <<
"sendGCSMotionReport latInt:lonInt:altMetersAMSL" << motionReport.lat_int << motionReport.lon_int << motionReport.altMetersAMSL;
167void FollowMe::_vehicleAdded(
Vehicle *vehicle)
170 _enableIfVehicleInFollow();
173void FollowMe::_vehicleRemoved(
Vehicle *vehicle)
176 _enableIfVehicleInFollow();
179void FollowMe::_enableIfVehicleInFollow()
181 if (_currentMode == MODE_ALWAYS) {
188 for (
int i = 0; i < vehicles->
count(); i++) {
190 if (_isFollowFlightMode(vehicle, vehicle->
flightMode())) {
196 _disableFollowSend();
199bool FollowMe::_isFollowFlightMode(
const Vehicle *vehicle,
const QString &flightMode)
Q_APPLICATION_STATIC(FollowMe, _followMeInstance)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void rawValueChanged(const QVariant &value)
virtual void sendGCSMotionReport(Vehicle *vehicle, const FollowMe::GCSMotionReport &motionReport, uint8_t estimationCapabilities) const
Sends the appropriate mavlink message for follow me support.
static FollowMe * instance()
static GPSManager * instance()
PositionManager * positionManager() const
static MultiVehicleManager * instance()
void vehicleAdded(Vehicle *vehicle)
QmlObjectListModel * vehicles() const
void vehicleRemoved(Vehicle *vehicle)
std::optional< GPSObservation > acceptedObservation(GPSObservation::PositionUse use=GPSObservation::PositionUse::GroundStation, std::optional< std::chrono::milliseconds > maximumAge=std::nullopt) const
int count() const override final
static SettingsManager * instance()
AppSettings * appSettings() const
QString flightMode() const
FirmwarePlugin * firmwarePlugin()
Provides access to the Firmware Plugin for this Vehicle.
QString followFlightMode() const
void flightModeChanged(const QString &flightMode)