|
|
|
@ -40,7 +40,7 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
@@ -40,7 +40,7 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
|
|
|
|
|
, _dirty(false) |
|
|
|
|
, _landingCoordSet(false) |
|
|
|
|
, _ignoreRecalcSignals(false) |
|
|
|
|
, _loiterToLandDistanceFact (0, _loiterToLandDistanceName, FactMetaData::valueTypeDouble) |
|
|
|
|
, _landingDistanceFact (0, _loiterToLandDistanceName, FactMetaData::valueTypeDouble) |
|
|
|
|
, _loiterAltitudeFact (0, _loiterAltitudeName, FactMetaData::valueTypeDouble) |
|
|
|
|
, _loiterRadiusFact (0, _loiterRadiusName, FactMetaData::valueTypeDouble) |
|
|
|
|
, _landingHeadingFact (0, _landingHeadingName, FactMetaData::valueTypeDouble) |
|
|
|
@ -55,13 +55,13 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
@@ -55,13 +55,13 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
|
|
|
|
|
_metaDataMap = FactMetaData::createMapFromJsonFile(QStringLiteral(":/json/FWLandingPattern.FactMetaData.json"), NULL /* metaDataParent */); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_loiterToLandDistanceFact.setMetaData (_metaDataMap[_loiterToLandDistanceName]); |
|
|
|
|
_landingDistanceFact.setMetaData (_metaDataMap[_loiterToLandDistanceName]); |
|
|
|
|
_loiterAltitudeFact.setMetaData (_metaDataMap[_loiterAltitudeName]); |
|
|
|
|
_loiterRadiusFact.setMetaData (_metaDataMap[_loiterRadiusName]); |
|
|
|
|
_landingHeadingFact.setMetaData (_metaDataMap[_landingHeadingName]); |
|
|
|
|
_landingAltitudeFact.setMetaData (_metaDataMap[_landingAltitudeName]); |
|
|
|
|
|
|
|
|
|
_loiterToLandDistanceFact.setRawValue (_loiterToLandDistanceFact.rawDefaultValue()); |
|
|
|
|
_landingDistanceFact.setRawValue (_landingDistanceFact.rawDefaultValue()); |
|
|
|
|
_loiterAltitudeFact.setRawValue (_loiterAltitudeFact.rawDefaultValue()); |
|
|
|
|
_loiterRadiusFact.setRawValue (_loiterRadiusFact.rawDefaultValue()); |
|
|
|
|
_landingHeadingFact.setRawValue (_landingHeadingFact.rawDefaultValue()); |
|
|
|
@ -69,10 +69,15 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
@@ -69,10 +69,15 @@ FixedWingLandingComplexItem::FixedWingLandingComplexItem(Vehicle* vehicle, QObje
|
|
|
|
|
|
|
|
|
|
connect(&_loiterAltitudeFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_updateLoiterCoodinateAltitudeFromFact); |
|
|
|
|
connect(&_landingAltitudeFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_updateLandingCoodinateAltitudeFromFact); |
|
|
|
|
connect(&_loiterToLandDistanceFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcLoiterCoordFromFacts); |
|
|
|
|
connect(&_landingHeadingFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcLoiterCoordFromFacts); |
|
|
|
|
connect(this, &FixedWingLandingComplexItem::loiterCoordinateChanged, this, &FixedWingLandingComplexItem::_recalcFactsFromCoords); |
|
|
|
|
connect(this, &FixedWingLandingComplexItem::landingCoordinateChanged, this, &FixedWingLandingComplexItem::_recalcFactsFromCoords); |
|
|
|
|
|
|
|
|
|
connect(&_landingDistanceFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcFromHeadingAndDistanceChange); |
|
|
|
|
connect(&_landingHeadingFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcFromHeadingAndDistanceChange); |
|
|
|
|
|
|
|
|
|
connect(&_loiterRadiusFact, &Fact::valueChanged, this, &FixedWingLandingComplexItem::_recalcFromRadiusChange); |
|
|
|
|
connect(this, &FixedWingLandingComplexItem::loiterClockwiseChanged, this, &FixedWingLandingComplexItem::_recalcFromRadiusChange); |
|
|
|
|
|
|
|
|
|
connect(this, &FixedWingLandingComplexItem::loiterCoordinateChanged, this, &FixedWingLandingComplexItem::_recalcFromCoordinateChange); |
|
|
|
|
connect(this, &FixedWingLandingComplexItem::landingCoordinateChanged, this, &FixedWingLandingComplexItem::_recalcFromCoordinateChange); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int FixedWingLandingComplexItem::lastSequenceNumber(void) const |
|
|
|
@ -168,7 +173,7 @@ bool FixedWingLandingComplexItem::load(const QJsonObject& complexObject, int seq
@@ -168,7 +173,7 @@ bool FixedWingLandingComplexItem::load(const QJsonObject& complexObject, int seq
|
|
|
|
|
_landingAltitudeRelative = complexObject[_jsonLandingAltitudeRelativeKey].toBool(); |
|
|
|
|
|
|
|
|
|
_landingCoordSet = true; |
|
|
|
|
_recalcFactsFromCoords(); |
|
|
|
|
_recalcFromHeadingAndDistanceChange(); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -253,7 +258,7 @@ void FixedWingLandingComplexItem::setLandingCoordinate(const QGeoCoordinate& coo
@@ -253,7 +258,7 @@ void FixedWingLandingComplexItem::setLandingCoordinate(const QGeoCoordinate& coo
|
|
|
|
|
emit landingCoordinateChanged(coordinate); |
|
|
|
|
_ignoreRecalcSignals = false; |
|
|
|
|
_landingCoordSet = true; |
|
|
|
|
_recalcLoiterCoordFromFacts(); |
|
|
|
|
_recalcFromHeadingAndDistanceChange(); |
|
|
|
|
emit landingCoordSetChanged(true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -268,29 +273,81 @@ void FixedWingLandingComplexItem::setLoiterCoordinate(const QGeoCoordinate& coor
@@ -268,29 +273,81 @@ void FixedWingLandingComplexItem::setLoiterCoordinate(const QGeoCoordinate& coor
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FixedWingLandingComplexItem::_recalcLoiterCoordFromFacts(void) |
|
|
|
|
double FixedWingLandingComplexItem::_mathematicAngleToHeading(double angle) |
|
|
|
|
{ |
|
|
|
|
if (!_ignoreRecalcSignals && _landingCoordSet) { |
|
|
|
|
double north, east, down; |
|
|
|
|
QGeoCoordinate tangentOrigin = _landingCoordinate; |
|
|
|
|
double heading = (angle - 90) * -1; |
|
|
|
|
if (heading < 0) { |
|
|
|
|
heading += 360; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return heading; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double FixedWingLandingComplexItem::_headingToMathematicAngle(double heading) |
|
|
|
|
{ |
|
|
|
|
return heading - 90 * -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FixedWingLandingComplexItem::_recalcFromRadiusChange(void) |
|
|
|
|
{ |
|
|
|
|
// Fixed:
|
|
|
|
|
// land
|
|
|
|
|
// loiter tangent
|
|
|
|
|
// distance
|
|
|
|
|
// radius
|
|
|
|
|
// heading
|
|
|
|
|
// Adjusted:
|
|
|
|
|
// loiter
|
|
|
|
|
|
|
|
|
|
if (!_ignoreRecalcSignals) { |
|
|
|
|
// These are our known values
|
|
|
|
|
double radius = _loiterRadiusFact.rawValue().toDouble(); |
|
|
|
|
double landToTangentDistance = _landingDistanceFact.rawValue().toDouble(); |
|
|
|
|
double heading = _landingHeadingFact.rawValue().toDouble(); |
|
|
|
|
|
|
|
|
|
double landToLoiterDistance = qSqrt(qPow(radius, 2) + qPow(landToTangentDistance, 2)); |
|
|
|
|
double angleLoiterToTangent = qRadiansToDegrees(qAsin(radius/landToLoiterDistance)) * (_loiterClockwise ? -1 : 1); |
|
|
|
|
|
|
|
|
|
_loiterCoordinate = _landingCoordinate.atDistanceAndAzimuth(landToLoiterDistance, heading + 180 + angleLoiterToTangent); |
|
|
|
|
|
|
|
|
|
_ignoreRecalcSignals = true; |
|
|
|
|
emit loiterCoordinateChanged(_loiterCoordinate); |
|
|
|
|
_ignoreRecalcSignals = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
convertGeoToNed(_landingCoordinate, tangentOrigin, &north, &east, &down); |
|
|
|
|
void FixedWingLandingComplexItem::_recalcFromHeadingAndDistanceChange(void) |
|
|
|
|
{ |
|
|
|
|
// Fixed:
|
|
|
|
|
// land
|
|
|
|
|
// heading
|
|
|
|
|
// distance
|
|
|
|
|
// radius
|
|
|
|
|
// Adjusted:
|
|
|
|
|
// loiter
|
|
|
|
|
// loiter tangent
|
|
|
|
|
|
|
|
|
|
// Heading is from loiter to land, so we need to rotate angle 180 degrees and go the opposite direction
|
|
|
|
|
if (!_ignoreRecalcSignals && _landingCoordSet) { |
|
|
|
|
// These are our known values
|
|
|
|
|
double radius = _loiterRadiusFact.rawValue().toDouble(); |
|
|
|
|
double landToTangentDistance = _landingDistanceFact.rawValue().toDouble(); |
|
|
|
|
double heading = _landingHeadingFact.rawValue().toDouble(); |
|
|
|
|
heading += 180.0; |
|
|
|
|
heading *= -1.0; |
|
|
|
|
|
|
|
|
|
QPointF originPoint(east, north); |
|
|
|
|
north += _loiterToLandDistanceFact.rawValue().toDouble(); |
|
|
|
|
QPointF loiterPoint(east, north); |
|
|
|
|
QPointF rotatedLoiterPoint = _rotatePoint(loiterPoint, originPoint, heading); |
|
|
|
|
// Calculate loiter tangent coordinate
|
|
|
|
|
_loiterTangentCoordinate = _landingCoordinate.atDistanceAndAzimuth(landToTangentDistance, heading + 180); |
|
|
|
|
|
|
|
|
|
// Calculate the distance and angle to the loiter coordinate
|
|
|
|
|
QGeoCoordinate tangent = _landingCoordinate.atDistanceAndAzimuth(landToTangentDistance, 0); |
|
|
|
|
QGeoCoordinate loiter = tangent.atDistanceAndAzimuth(radius, 90); |
|
|
|
|
double loiterDistance = _landingCoordinate.distanceTo(loiter); |
|
|
|
|
double loiterAzimuth = _landingCoordinate.azimuthTo(loiter) * (_loiterClockwise ? -1 : 1); |
|
|
|
|
|
|
|
|
|
convertNedToGeo(rotatedLoiterPoint.y(), rotatedLoiterPoint.x(), down, tangentOrigin, &_loiterCoordinate); |
|
|
|
|
// Use those values to get the new loiter point which takes heading into acount
|
|
|
|
|
_loiterCoordinate = _landingCoordinate.atDistanceAndAzimuth(loiterDistance, heading + 180 + loiterAzimuth); |
|
|
|
|
|
|
|
|
|
_ignoreRecalcSignals = true; |
|
|
|
|
emit loiterTangentCoordinateChanged(_loiterTangentCoordinate); |
|
|
|
|
emit loiterCoordinateChanged(_loiterCoordinate); |
|
|
|
|
emit coordinateChanged(_loiterCoordinate); |
|
|
|
|
_ignoreRecalcSignals = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -306,42 +363,34 @@ QPointF FixedWingLandingComplexItem::_rotatePoint(const QPointF& point, const QP
@@ -306,42 +363,34 @@ QPointF FixedWingLandingComplexItem::_rotatePoint(const QPointF& point, const QP
|
|
|
|
|
return rotated; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FixedWingLandingComplexItem::_recalcFactsFromCoords(void) |
|
|
|
|
void FixedWingLandingComplexItem::_recalcFromCoordinateChange(void) |
|
|
|
|
{ |
|
|
|
|
if (!_ignoreRecalcSignals && _landingCoordSet) { |
|
|
|
|
|
|
|
|
|
// Prevent signal recursion
|
|
|
|
|
_ignoreRecalcSignals = true; |
|
|
|
|
|
|
|
|
|
// Calc new distance
|
|
|
|
|
// Fixed:
|
|
|
|
|
// land
|
|
|
|
|
// loiter
|
|
|
|
|
// radius
|
|
|
|
|
// Adjusted:
|
|
|
|
|
// loiter tangent
|
|
|
|
|
// heading
|
|
|
|
|
// distance
|
|
|
|
|
|
|
|
|
|
double northLand, eastLand, down; |
|
|
|
|
double northLoiter, eastLoiter; |
|
|
|
|
QGeoCoordinate tangentOrigin = _landingCoordinate; |
|
|
|
|
|
|
|
|
|
convertGeoToNed(_landingCoordinate, tangentOrigin, &northLand, &eastLand, &down); |
|
|
|
|
convertGeoToNed(_loiterCoordinate, tangentOrigin, &northLoiter, &eastLoiter, &down); |
|
|
|
|
if (!_ignoreRecalcSignals && _landingCoordSet) { |
|
|
|
|
// These are our known values
|
|
|
|
|
double radius = _loiterRadiusFact.rawValue().toDouble(); |
|
|
|
|
double landToLoiterDistance = _landingCoordinate.distanceTo(_loiterCoordinate); |
|
|
|
|
double landToLoiterHeading = _landingCoordinate.azimuthTo(_loiterCoordinate); |
|
|
|
|
|
|
|
|
|
double newDistance = sqrt(pow(eastLoiter - eastLand, 2.0) + pow(northLoiter - northLand, 2.0)); |
|
|
|
|
_loiterToLandDistanceFact.setRawValue(newDistance); |
|
|
|
|
double loiterToTangentAngle = qRadiansToDegrees(qAsin(radius/landToLoiterDistance)) * (_loiterClockwise ? 1 : -1); |
|
|
|
|
double landToTangentDistance = qSqrt(qPow(landToLoiterDistance, 2) - qPow(radius, 2)); |
|
|
|
|
|
|
|
|
|
// Calc new heading
|
|
|
|
|
_loiterTangentCoordinate = _landingCoordinate.atDistanceAndAzimuth(landToTangentDistance, landToLoiterHeading + loiterToTangentAngle); |
|
|
|
|
|
|
|
|
|
QPointF vector(eastLand - eastLoiter, northLand - northLoiter); |
|
|
|
|
double radians = atan2(vector.y(), vector.x()); |
|
|
|
|
double degrees = qRadiansToDegrees(radians); |
|
|
|
|
// Change angle to north up = 0 degrees
|
|
|
|
|
degrees -= 90; |
|
|
|
|
// Reverse the angle direction to go from mathematic angle (counter-clockwise) to compass heading (clockwise)
|
|
|
|
|
degrees *= -1.0; |
|
|
|
|
// Bring with 0-360 range
|
|
|
|
|
if (degrees < 0.0) { |
|
|
|
|
degrees += 360.0; |
|
|
|
|
} else if (degrees > 360.0) { |
|
|
|
|
degrees -= 360.0; |
|
|
|
|
} |
|
|
|
|
_landingHeadingFact.setRawValue(degrees); |
|
|
|
|
double heading = _loiterTangentCoordinate.azimuthTo(_landingCoordinate); |
|
|
|
|
|
|
|
|
|
_ignoreRecalcSignals = true; |
|
|
|
|
_landingHeadingFact.setRawValue(heading); |
|
|
|
|
_landingDistanceFact.setRawValue(landToTangentDistance); |
|
|
|
|
emit loiterTangentCoordinateChanged(_loiterTangentCoordinate); |
|
|
|
|
_ignoreRecalcSignals = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|