Skip to content

Commit cb3eb98

Browse files
authored
Wheelsteering fixes and improvements (#3131)
* Fix `IFlightControlParameter.GetValue` returning vessel throttle for wheelsteering and wheelthrottle managers when they are not active * Make wheelsteering getter return target heading instead of bearing * Fix #2106. Add `wheelsteeringpid` bound variable * Change default proportional term coefficient on wheelsteeringpid from 0.1 to 0.03 This is a breaking change. This doesn't reduce turning speed nearly as much as it reduces oscillations for both rovers and planes. Mostly because of the steering smoothing applied by ksp.
1 parent c1af606 commit cb3eb98

5 files changed

Lines changed: 42 additions & 30 deletions

File tree

doc/source/commands/flight/cooked.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ Like all ``LOCK`` expressions, the steering and throttle continually update on t
203203
It's a very bad idea to ``WAIT`` during the execution of the expression in a
204204
LOCK WHEELSTEERING. See the note in the next section below.
205205

206+
.. global:: WHEELSTEERINGPID
207+
208+
:access: Get/Set
209+
:type: :struct:`PIDLoop`
210+
211+
The PIDLoop used to control wheelsteering. Can be used to optimize
212+
steering performance and eliminate steering oscillations on some vessels.
206213

207214
Don't 'WAIT' or run slow script code during cooked control calculation
208215
----------------------------------------------------------------------

src/kOS/Binding/FlightControlManager.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using kOS.Control;
1313
using kOS.Module;
1414
using kOS.Communication;
15+
using kOS.Safe.Encapsulation;
1516

1617
namespace kOS.Binding
1718
{
@@ -49,6 +50,18 @@ public override void AddTo(SharedObjects shared)
4950

5051
shared.BindingMgr.AddBoundVariable("SASMODE", GetAutopilotModeName, SelectAutopilotMode);
5152
shared.BindingMgr.AddBoundVariable("NAVMODE", GetNavModeName, SetNavMode);
53+
54+
shared.BindingMgr.AddBoundVariable("WHEELSTEERINGPID", () =>
55+
{
56+
return ((WheelSteeringManager)kOSVesselModule.GetInstance(shared.Vessel).GetFlightControlParameter("wheelsteering")).SteeringPID;
57+
}, value =>
58+
{
59+
if (value is PIDLoop pidLoop)
60+
{
61+
((WheelSteeringManager)kOSVesselModule.GetInstance(shared.Vessel).GetFlightControlParameter("wheelsteering")).SteeringPID = pidLoop;
62+
}
63+
else throw new KOSCastException(value.GetType(), typeof(PIDLoop));
64+
});
5265
}
5366

5467
private object GetThrottleValue()

src/kOS/Control/WheelSteeringManager.cs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ internal class WheelSteeringManager : IFlightControlParameter
1616

1717
public bool Enabled { get; private set; }
1818
public float Value { get; set; }
19+
public PIDLoop SteeringPID = new PIDLoop(0.03, 0, 0);
1920

2021
public bool FightsWithSas { get { return false; } }
2122

@@ -90,26 +91,26 @@ Vessel IFlightControlParameter.GetResponsibleVessel()
9091

9192
object IFlightControlParameter.GetValue()
9293
{
93-
if (Enabled)
94-
{
95-
return Value;
96-
}
97-
return internalVessel.ctrlState.mainThrottle;
94+
return Value;
9895
}
9996

10097
void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c, ControlTypes ctrlLock)
10198
{
10299
if (!Enabled) return;
103100

104101
if (!(controlShared.Vessel.horizontalSrfSpeed > 0.1f)) return;
102+
103+
float vesselHeading = VesselUtils.GetHeading(controlShared.Vessel);
104+
float bearing = VesselUtils.AngleDelta(vesselHeading, Value);
105+
float PIDOutput = SteeringPID.Update(controlShared.UpdateHandler.CurrentFixedTime, bearing);
105106

106-
if (Mathf.Abs(VesselUtils.AngleDelta(VesselUtils.GetHeading(controlShared.Vessel), VesselUtils.GetVelocityHeading(controlShared.Vessel))) <= 90)
107+
if (Mathf.Abs(VesselUtils.AngleDelta(vesselHeading, VesselUtils.GetVelocityHeading(controlShared.Vessel))) <= 90)
107108
{
108-
c.wheelSteer = Mathf.Clamp(Value / -10, -1, 1);
109+
c.wheelSteer = Mathf.Clamp(PIDOutput, -1, 1);
109110
}
110111
else
111112
{
112-
c.wheelSteer = -Mathf.Clamp(Value / -10, -1, 1);
113+
c.wheelSteer = -Mathf.Clamp(PIDOutput, -1, 1);
113114
}
114115
}
115116

@@ -123,29 +124,21 @@ void IFlightControlParameter.UpdateValue(object value, SharedObjects shared)
123124
if (!Enabled)
124125
((IFlightControlParameter)this).EnableControl(shared);
125126

126-
float bearing = 0;
127-
128-
if (value is VesselTarget)
127+
if (value is VesselTarget vessel)
129128
{
130-
bearing = VesselUtils.GetTargetBearing(controlShared.Vessel, ((VesselTarget)value).Vessel);
129+
Value = VesselUtils.GetTargetHeading(controlShared.Vessel, vessel.Vessel);
131130
}
132-
else if (value is GeoCoordinates)
131+
else if (value is GeoCoordinates gc)
133132
{
134-
bearing = ((GeoCoordinates)value).GetBearing();
133+
Value = gc.GetHeading();
135134
}
136135
else
137136
{
138137
try
139138
{
140-
double doubleValue = Convert.ToDouble(value);
141-
if (Utils.IsValidNumber(doubleValue))
142-
{
143-
bearing = (float)(Math.Round(doubleValue) - Mathf.Round(FlightGlobals.ship_heading));
144-
if (bearing < -180)
145-
bearing += 360; // i.e. 359 degrees to the left is really 1 degree to the right.
146-
else if (bearing > 180)
147-
bearing -= 360; // i.e. 359 degrees to the right is really 1 degree to the left
148-
}
139+
float heading = Convert.ToSingle(value);
140+
if (!float.IsInfinity(heading) && !float.IsNaN(heading))
141+
Value = heading;
149142
}
150143
catch
151144
{
@@ -157,11 +150,10 @@ void IFlightControlParameter.UpdateValue(object value, SharedObjects shared)
157150
KOSNomenclature.GetKOSName(typeof(VesselTarget)),
158151
KOSNomenclature.GetKOSName(typeof(GeoCoordinates)),
159152
KOSNomenclature.GetKOSName(typeof(ScalarValue))
160-
)
161-
);
153+
)
154+
);
162155
}
163156
}
164-
Value = bearing;
165157
}
166158
}
167159
}

src/kOS/Control/WheelThrottleManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ object IFlightControlParameter.GetValue()
9191
{
9292
return Value;
9393
}
94-
return internalVessel.ctrlState.mainThrottle;
94+
return internalVessel.ctrlState.wheelThrottle;
9595
}
9696

9797
void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c, ControlTypes ctrlLock)

src/kOS/Suffixed/GeoCoordinates.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public static GeoCoordinates CreateFromDump(SafeSharedObjects shared, Dump d)
127127
/// <returns> bearing </returns>
128128
public ScalarValue GetBearing()
129129
{
130-
return VesselUtils.AngleDelta(VesselUtils.GetHeading(Shared.Vessel), (float) GetHeadingFrom());
130+
return VesselUtils.AngleDelta(VesselUtils.GetHeading(Shared.Vessel), (float) GetHeading());
131131
}
132132

133133
/// <summary>
@@ -240,7 +240,7 @@ private bool RaycastForTerrain(Vector3d worldRayCastStart, Vector3d worldRayCast
240240
/// LAT/LANG position on the SOI body's surface.
241241
/// </summary>
242242
/// <returns>compass heading in degrees</returns>
243-
private ScalarValue GetHeadingFrom()
243+
public ScalarValue GetHeading()
244244
{
245245
var up = Shared.Vessel.upAxis;
246246
var north = VesselUtils.GetNorthVector(Shared.Vessel);
@@ -321,7 +321,7 @@ private void GeoCoordsInitializeSuffixes()
321321
AddSuffix("BODY", new Suffix<BodyTarget>(()=> BodyTarget.CreateOrGetExisting(Body, Shared)));
322322
AddSuffix("TERRAINHEIGHT", new Suffix<ScalarValue>(GetTerrainAltitude));
323323
AddSuffix("DISTANCE", new Suffix<ScalarValue>(GetDistanceFrom));
324-
AddSuffix("HEADING", new Suffix<ScalarValue>(GetHeadingFrom));
324+
AddSuffix("HEADING", new Suffix<ScalarValue>(GetHeading));
325325
AddSuffix("BEARING", new Suffix<ScalarValue>(GetBearing));
326326
AddSuffix("POSITION", new Suffix<Vector>(GetPosition,
327327
"Get the 3-D space position relative to the ship center, of this lat/long, " +

0 commit comments

Comments
 (0)