diff --git a/PlaneGcsSdk.Contract_Shared/Copters/ICopterActionsSharedByCopterManager.cs b/PlaneGcsSdk.Contract_Shared/Copters/ICopterActionsSharedByCopterManager.cs index 90f82b5..0e073fb 100644 --- a/PlaneGcsSdk.Contract_Shared/Copters/ICopterActionsSharedByCopterManager.cs +++ b/PlaneGcsSdk.Contract_Shared/Copters/ICopterActionsSharedByCopterManager.cs @@ -32,7 +32,8 @@ namespace Plane.Copters /// 相对于解锁点的高度。 /// 表示此命令异步发送操作的 实例。 /// flytime =飞行时间 秒 - Task FlyToAsync(double lat, double lng, float alt,float flytime=0); + /// flytype 0;匀速 1;加减速 2;单加速 3;单减速 + Task FlyToAsync(double lat, double lng, float alt,float flytime=0,int flytype = 0); /// /// 切换到 并悬停。此操作需要使用 GPS 定位,卫星数不足导致定位不准时非常危险。 diff --git a/PlaneGcsSdk.Contract_Shared/Copters/ICopterAttribute.cs b/PlaneGcsSdk.Contract_Shared/Copters/ICopterAttribute.cs index e66a729..6507432 100644 --- a/PlaneGcsSdk.Contract_Shared/Copters/ICopterAttribute.cs +++ b/PlaneGcsSdk.Contract_Shared/Copters/ICopterAttribute.cs @@ -16,5 +16,11 @@ namespace Plane.Copters float RetainInt{ get; } //模拟飞行更新间隔 int sim_update_int { get; set; } + float maxspeed_xy { get; set; } + float maxspeed_up { get; set; } + float maxspeed_down { get; set; } + float acc_z { get; set; } + float acc_xy { get; set; } + } } diff --git a/PlaneGcsSdk_Shared/CopterControllers/GuidController.cs b/PlaneGcsSdk_Shared/CopterControllers/GuidController.cs new file mode 100644 index 0000000..bc7de4f --- /dev/null +++ b/PlaneGcsSdk_Shared/CopterControllers/GuidController.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Plane.CopterControllers +{ + class GuidController + { + + static float fabsf(float vvalue) + { + return Math.Abs(vvalue); + + } + static float sqrt(float vvalue) + { + return (float)Math.Sqrt(vvalue); + + } + + + /// + /// 计算小航点飞行 + /// + /// + /// + /// + /// + + //单算减速,不算加速的最小飞行时间 + static float getMinfligthtime_v2(float Distance, float fc_acc, float fc_maxspeed) + { + float fDis = fabsf(Distance); // 总距离 + float facc = fabsf(fc_acc); // 减速度 + + // 物体开始时即以最大速度运动,不考虑加速过程 + float vel = fc_maxspeed; + + // 计算减速所需的时间和距离 + // 减速时间 (从最大速度减速到0) + float dectime = vel / facc; + // 减速阶段覆盖的距离 + float decdis = (vel * dectime) - (0.5f * facc * dectime * dectime); + + // 判断是否有足够的距离进行减速 + if (decdis >= fDis) + { + // 如果减速所需距离已经超过或等于总距离,调整最大速度 + // 使用公式 v^2 = u^2 + 2as 解出 v + vel = (float)Math.Sqrt(2 * facc * fDis); + // 重新计算减速时间 + dectime = vel / facc; + } + + // 计算匀速阶段时间 + float unftime = 0.0f; + if (decdis < fDis) + { + // 如果有剩余距离进行匀速运动 + unftime = (fDis - decdis) / vel; + } + + // 总飞行时间 = 匀速阶段时间 + 减速阶段时间 + return unftime + dectime; + } + + //单算减速,不算加速的最大飞行速度 + public static float CalculateMaximumVelocity(float distance, float time, float acceleration) + { + // 二次方程系数 + float a_coeff = 1; + float b_coeff = -2 * time; + float c_coeff = (2 * distance) / acceleration; + + // 计算判别式 + float discriminant = b_coeff * b_coeff - 4 * a_coeff * c_coeff; + + if (discriminant < 0) + { + return -1; // 无实数解 + } + + // 计算二次方程的根 + float t1_root1 = (-b_coeff + (float)Math.Sqrt(discriminant)) / (2 * a_coeff); + float t1_root2 = (-b_coeff - (float)Math.Sqrt(discriminant)) / (2 * a_coeff); + + // 选择合理的根作为 t1 + float t1 = Math.Min(t1_root1, t1_root2); + if (t1 < 0 || t1 > time) + { + return -1; // 无合理解 + } + + // 计算最大速度 v + return acceleration * t1; + } + + //单算加速,不算减速的距离速度计算 + static float getspeeddist_V2(float flight_time, float Distance, float curr_time, float fc_acc, float fc_maxspeed, out float vdist, out float vspeed) + { + vdist = 0; + vspeed = 0; + float desV = CalculateMaximumVelocity(Distance, flight_time, fc_acc); + if ((desV == -1) || (desV > fc_maxspeed)) //飞不到 + { + vspeed = Distance / flight_time; + vdist = vspeed * curr_time; //匀速距离 + return 0; + + } + float dect = desV / fc_acc; // 总加速时间 + float unit = flight_time - dect; //匀速段时间 + float decD = (fc_acc * dect * dect) / 2; //总加速距离 + + if (dect > flight_time) dect = flight_time;//约束时间 + if (curr_time > dect) //大于加速段时间--匀速 + { + vspeed = (Distance - decD) / (flight_time - dect); + vdist = vspeed * (curr_time - dect); + vdist = vdist + decD; //总距离=匀速距离+减速距离 + if (vdist > Distance) vdist = Distance; //约束距离 + + } + else //加速段 + { + vspeed = fc_acc * curr_time; + vdist = (fc_acc * curr_time * curr_time) / 2; //加速距离 + } + return 0; + } + + //单算减速,不算加速的距离速度计算 + static float getspeeddist_V3(float flight_time, float Distance, float curr_time, float fc_acc, float fc_maxspeed, out float vdist, out float vspeed) + { + vdist = 0; + vspeed = 0; + float desV = CalculateMaximumVelocity(Distance, flight_time, fc_acc); + if ((desV == -1) || (desV > fc_maxspeed)) //飞不到 + { + vspeed = Distance / flight_time; + vdist = vspeed * curr_time; //匀速距离 + return 0; + + } + float dect = desV / fc_acc; // 总减速时间 + float unit = flight_time - dect; //匀速段时间 + float decD = desV * dect - (fc_acc * dect * dect) / 2; //总减速距离 + + if (dect > flight_time) dect = flight_time;//约束时间 + //匀速时间内 + if (curr_time < unit) + { + vspeed = (Distance - decD) / (flight_time - dect); + vdist = vspeed * curr_time; + } + else + { + if (((flight_time - dect) * unit) == 0) + vdist = 0; + else + vdist = (Distance - decD) / (flight_time - dect) * unit; //匀速距离 + float currdect = curr_time - unit; //减速时间 + if (currdect >= 0) + { + vspeed = desV - fc_acc * currdect; + decD = desV * currdect - (fc_acc * currdect * currdect) / 2; //减速距离 + } + vdist = vdist + decD; //总距离=匀速距离+减速距离 + if (vdist > Distance) vdist = Distance; //约束距离 + } + return 0; + } + + + + static float getMinfligthtime(float Distance, float fc_acc, float fc_maxspeed) + { + float fDis = fabsf(Distance); + float facc = fabsf(fc_acc); + + float realflytime = 0.0f; + //计算一半的距离 + float hafdis = (fDis / 2); + //计算最大速度 + float vel = (float)sqrt(2 * facc * hafdis); + //如果速度超过最大速度 + if (vel > fc_maxspeed) + //使用最大速度 + vel = fc_maxspeed; + //加速时间 + float acctim = vel / facc; + //加速距离 + float accdis = vel * vel / (2 * facc); + //匀速段时间 + float vtime = (hafdis - accdis) / vel; + //到一半的时间 + float haftime = acctim + vtime; + realflytime = haftime * 2; + return realflytime; + } + + ///计算飞行距离和速度 单位--米,秒---- + //返回 整个距离最大飞行速度 + ///flight_time 总飞行时间 Distance 飞行总距离 curr_time 当前飞行时间 fc_acc加速度, fc_maxspeed最大速度 vdist 计算的应该飞的距离 vspeed 计算的当前时间应该速度 + //========这是飞控正在使用的算法======== + static float getspeeddist_V1(float flight_time, float Distance, float curr_time, float fc_acc, float fc_maxspeed, out float vdist, out float vspeed) + { + //计划飞行时间 + float plan_flytime = flight_time; + //计算距离用绝对值 + float fDis = fabsf(Distance); + if (curr_time < 0) + { + vdist = 0; + vspeed = 0; + return 0.0f; + } + //导航加速度 米/秒*秒 ---不使用导航库 + float wpacc = fabsf(fc_acc);// g.fc_acc_xy;//1.5; + + //最大目标速度---米/秒 + float desired_velocity = 0; + float dist = 0; + // + float speed = 0; + + //计算最小飞行时间 + float minflytime = getMinfligthtime(Distance, fc_acc, fc_maxspeed); + if (flight_time < minflytime) + plan_flytime = minflytime;// + 0.1f; + + + //根据总飞行时间和总距离计算飞行速度----起始和结束速度都是0,中间按匀加速和匀减速计算,没考虑加加速度 + float delta = (0.5f * plan_flytime) * (0.5f * plan_flytime) - fDis / wpacc; + if (delta >= 0) + { + desired_velocity = (0.5f * plan_flytime - sqrt(delta)) / (1 / wpacc); + if (desired_velocity > fc_maxspeed) + { + plan_flytime = minflytime; + desired_velocity = fc_maxspeed; + } + } + else + { + desired_velocity = (0.5f * plan_flytime) / (1 / wpacc); + } + if (desired_velocity < 0.2f) desired_velocity = 0.2f; //限制最小速度0.2米/秒 + if (desired_velocity > fc_maxspeed) desired_velocity = fc_maxspeed;//限制最大速度10米/秒,应该参数化 + + //计算实时速度 + if (curr_time <= (plan_flytime / 2.0)) + speed = curr_time * wpacc; + else + //需要减速 + speed = (plan_flytime - curr_time) * wpacc; + //不能大于目标速度 + if (speed > desired_velocity) + speed = desired_velocity; + if (speed <= 0) + speed = 0; + vspeed = speed; + //计算实时距离 + float V_start = 0.0f; + float V_end = 0.0f; + //加速段 + float t1 = (desired_velocity - V_start) / wpacc; + //减速段 + float t3 = (desired_velocity - V_end) / wpacc; + //平飞段 + float t2 = plan_flytime - t1 - t3; + if (curr_time < t1) + { + dist = 0.5f * wpacc * curr_time * curr_time + curr_time * V_start; + } + else if (curr_time < t1 + t2) + { + dist = -0.5f * wpacc * t1 * t1 + (curr_time) * desired_velocity; + } + else + { + float t = curr_time - t1 - t2; + dist = -0.5f * wpacc * t1 * t1 + curr_time * desired_velocity - 0.5f * wpacc * t * t; + } + + if (fabsf(dist) > fabsf(Distance)) + vdist = Distance; + else + { + if (Distance < 0) + vdist = -dist; + else vdist = dist; + } + + return desired_velocity; + } + + public static float getspeeddist(int flytype, float flight_time, float Distance, float curr_time, float fc_acc, float fc_maxspeed, out float vdist, out float vspeed) + { + switch (flytype) + { + case 0: //匀速 + //case 1: //匀速 + vspeed = Distance / flight_time; + vdist = vspeed * curr_time; + return 0; + case 1: //同时计算加减速 + return getspeeddist_V1(flight_time, Distance, curr_time, fc_acc, fc_maxspeed, out vdist, out vspeed); + case 2: //单加速 + return getspeeddist_V2(flight_time, Distance, curr_time, fc_acc, fc_maxspeed, out vdist, out vspeed); + case 3: //单减速 + return getspeeddist_V3(flight_time, Distance, curr_time, fc_acc, fc_maxspeed, out vdist, out vspeed); + default: + vspeed = 0; + vdist = 0; + return 0; + } + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + } diff --git a/PlaneGcsSdk_Shared/CopterManagement/SingleCopterManager.cs b/PlaneGcsSdk_Shared/CopterManagement/SingleCopterManager.cs index a90a3a2..365954c 100644 --- a/PlaneGcsSdk_Shared/CopterManagement/SingleCopterManager.cs +++ b/PlaneGcsSdk_Shared/CopterManagement/SingleCopterManager.cs @@ -104,7 +104,7 @@ namespace Plane.CopterManagement return Copter.FlyToAsync(lat, lng); } - public Task FlyToAsync(double lat, double lng, float alt, float flytime = 0) + public Task FlyToAsync(double lat, double lng, float alt, float flytime = 0, int flytype = 0) { return Copter.FlyToAsync(lat, lng, alt); } diff --git a/PlaneGcsSdk_Shared/Copters/CopterImplSharedPart.cs b/PlaneGcsSdk_Shared/Copters/CopterImplSharedPart.cs index bb6e956..5b0aca5 100644 --- a/PlaneGcsSdk_Shared/Copters/CopterImplSharedPart.cs +++ b/PlaneGcsSdk_Shared/Copters/CopterImplSharedPart.cs @@ -180,6 +180,12 @@ namespace Plane.Copters private bool _DisplayID = true; + private float _maxspeed_xy=3; + private float _maxspeed_down=3; + private float _maxspeed_up = 3; + private float _acc_z=1f; + private float _acc_xy=2.5f; + #endregion Backing Fields public CopterImplSharedPart(SynchronizationContext uiSyncContext) : base(uiSyncContext) @@ -683,6 +689,48 @@ namespace Plane.Copters } + public float maxspeed_xy { + get { return _maxspeed_xy; } + set + { + Set(nameof(maxspeed_xy), ref _maxspeed_xy, value); + } + } + + public float maxspeed_up + { + get { return _maxspeed_up; } + set + { + Set(nameof(maxspeed_up), ref _maxspeed_up, value); + } + } + public float maxspeed_down + { + get { return _maxspeed_down; } + set + { + Set(nameof(maxspeed_down), ref _maxspeed_down, value); + } + } + public float acc_z + { + get { return _acc_z; } + set + { + Set(nameof(acc_z), ref _acc_z, value); + } + } + public float acc_xy + { + get { return _acc_xy; } + set + { + Set(nameof(acc_xy), ref _acc_xy, value); + } + } + + public byte[] Retain { @@ -865,11 +913,11 @@ namespace Plane.Copters return FlyToAsync(lat, lng, Altitude); } - public Task FlyToAsync(double lat, double lng, float alt, float flytime = 0) + public Task FlyToAsync(double lat, double lng, float alt, float flytime = 0, int flytype = 0) { _shouldFollow = false; //State = CopterState.CommandMode; - return FlyToCoreAsync(lat, lng, alt, flytime); + return FlyToCoreAsync(lat, lng, alt, flytime, flytype); } public void Follow(IVisibleStatus target, bool keepYawDifference = false, bool keepFacingTarget = true, bool keep3DRelativeLocations = false) @@ -1125,7 +1173,7 @@ namespace Plane.Copters /// 经度。 /// 高度。 /// 表示此异步发送操作的 实例。 - protected abstract Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0); + protected abstract Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0, int flytype = 0); protected void RaiseAltitudeChanged() => AltitudeChanged?.Invoke(this, EventArgs.Empty); diff --git a/PlaneGcsSdk_Shared/Copters/EmptyCopter.cs b/PlaneGcsSdk_Shared/Copters/EmptyCopter.cs index e54d73d..9c55c68 100644 --- a/PlaneGcsSdk_Shared/Copters/EmptyCopter.cs +++ b/PlaneGcsSdk_Shared/Copters/EmptyCopter.cs @@ -144,7 +144,7 @@ namespace Plane.Copters return Task.FromResult(true); } - protected override Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0) + protected override Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0, int flytype = 0) { return TaskUtils.CompletedTask; } diff --git a/PlaneGcsSdk_Shared/Copters/FakeCopter.cs b/PlaneGcsSdk_Shared/Copters/FakeCopter.cs index 256c545..240748c 100644 --- a/PlaneGcsSdk_Shared/Copters/FakeCopter.cs +++ b/PlaneGcsSdk_Shared/Copters/FakeCopter.cs @@ -7,6 +7,8 @@ using System.Threading; using System.Threading.Tasks; using static Plane.Copters.Constants; using System.Windows.Media; +using Plane.CopterControllers; + namespace Plane.Copters { /// @@ -89,8 +91,9 @@ namespace Plane.Copters private float _distance_xy; private float _distance_z; - private float _distance_xy_delta; - private float _distance_z_delta; + private float _xy_speed; + private float _z_speed; + private int _flytype; private float currflytime; // 根据飞行时间计算飞行距离。 private float currdis_xy; @@ -274,7 +277,7 @@ namespace Plane.Copters return TaskUtils.CompletedTask; } - protected override Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0) + protected override Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0, int flytype = 0) { if (!IsEmergencyHoverActive) { @@ -298,10 +301,9 @@ namespace Plane.Copters _distance_z = alt - Altitude; Console.WriteLine($"{this.Id}d:{_distance_xy},lat{this.Latitude},lng{this.Longitude },tlat:{lat}tlng:{lng}"); - _distance_xy_delta = _distance_xy / _flytime; - _distance_z_delta = _distance_z / _flytime; - - + _flytype = flytype; + // _xy_speed = _distance_xy / _flytime; + // _z_speed = _distance_z / _flytime; Mode = FlightMode.GUIDED; @@ -674,6 +676,7 @@ namespace Plane.Copters break; case FlightMode.AUTO: + /* // 暂时只管起飞。以最大速度上升,直到达到目标高度。 if (Altitude < _takeOffTargetAltitude) { @@ -683,6 +686,7 @@ namespace Plane.Copters { Mode = FlightMode.LOITER; } + */ break; case FlightMode.GUIDED: @@ -888,8 +892,18 @@ namespace Plane.Copters //if (currflytime > 13000) // return; // 根据飞行时间计算飞行距离 - currdis_xy = _distance_xy_delta * currflytime; - currdis_z = _distance_z_delta * currflytime; + + float vspeed = 0; + + GuidController.getspeeddist(_flytype, _flytime / 1000, _distance_xy, currflytime / 1000, acc_xy,maxspeed_xy , out currdis_xy, out vspeed); + + if (alt> Altitude) + GuidController.getspeeddist(_flytype, _flytime / 1000, _distance_z, currflytime / 1000, acc_z,maxspeed_up, out currdis_z, out vspeed); + else + GuidController.getspeeddist(_flytype, _flytime / 1000, _distance_z, currflytime / 1000, acc_z,maxspeed_down, out currdis_z, out vspeed); + + Console.WriteLine($"{this.Id}:time:{currflytime / 1000} to {currdis_z}"); + // 距离已经很近,直接移动到目标点。 if ((Math.Abs(_distance_xy-currdis_xy) < 0.1)&& (Math.Abs(_distance_z - currdis_z) < 0.1)) { diff --git a/PlaneGcsSdk_Shared/Copters/PLCopter.cs b/PlaneGcsSdk_Shared/Copters/PLCopter.cs index 2203513..2bbcf84 100644 --- a/PlaneGcsSdk_Shared/Copters/PLCopter.cs +++ b/PlaneGcsSdk_Shared/Copters/PLCopter.cs @@ -418,7 +418,7 @@ namespace Plane.Copters return !anotherSetModeActionCalled && Mode == mode; } - protected override async Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0) + protected override async Task FlyToCoreAsync(double lat, double lng, float alt, float flytime = 0, int flytype = 0) { if (!IsEmergencyHoverActive) { diff --git a/PlaneGcsSdk_Shared/PlaneGcsSdk_Shared.projitems b/PlaneGcsSdk_Shared/PlaneGcsSdk_Shared.projitems index ceddaef..b0f95b8 100644 --- a/PlaneGcsSdk_Shared/PlaneGcsSdk_Shared.projitems +++ b/PlaneGcsSdk_Shared/PlaneGcsSdk_Shared.projitems @@ -34,6 +34,7 @@ +