diff options
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/PhysicsModules/BulletS/BSMotors.cs (renamed from OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs) | 246 |
1 files changed, 175 insertions, 71 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/PhysicsModules/BulletS/BSMotors.cs index 817a5f7..2faf2d4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSMotors.cs | |||
@@ -31,7 +31,7 @@ using System.Text; | |||
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | 33 | ||
34 | namespace OpenSim.Region.Physics.BulletSPlugin | 34 | namespace OpenSim.Region.PhysicsModule.BulletS |
35 | { | 35 | { |
36 | public abstract class BSMotor | 36 | public abstract class BSMotor |
37 | { | 37 | { |
@@ -59,22 +59,17 @@ public abstract class BSMotor | |||
59 | { | 59 | { |
60 | if (PhysicsScene != null) | 60 | if (PhysicsScene != null) |
61 | { | 61 | { |
62 | if (PhysicsScene.VehicleLoggingEnabled) | 62 | PhysicsScene.DetailLog(msg, parms); |
63 | { | ||
64 | PhysicsScene.DetailLog(msg, parms); | ||
65 | } | ||
66 | } | 63 | } |
67 | } | 64 | } |
68 | } | 65 | } |
69 | 66 | ||
70 | // Motor which moves CurrentValue to TargetValue over TimeScale seconds. | 67 | // Motor which moves CurrentValue to TargetValue over TimeScale seconds. |
71 | // The TargetValue decays in TargetValueDecayTimeScale and | 68 | // The TargetValue decays in TargetValueDecayTimeScale. |
72 | // the CurrentValue will be held back by FrictionTimeScale. | ||
73 | // This motor will "zero itself" over time in that the targetValue will | 69 | // This motor will "zero itself" over time in that the targetValue will |
74 | // decay to zero and the currentValue will follow it to that zero. | 70 | // decay to zero and the currentValue will follow it to that zero. |
75 | // The overall effect is for the returned correction value to go from large | 71 | // The overall effect is for the returned correction value to go from large |
76 | // values (the total difference between current and target minus friction) | 72 | // values to small and eventually zero values. |
77 | // to small and eventually zero values. | ||
78 | // TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. | 73 | // TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. |
79 | 74 | ||
80 | // For instance, if something is moving at speed X and the desired speed is Y, | 75 | // For instance, if something is moving at speed X and the desired speed is Y, |
@@ -91,7 +86,6 @@ public class BSVMotor : BSMotor | |||
91 | 86 | ||
92 | public virtual float TimeScale { get; set; } | 87 | public virtual float TimeScale { get; set; } |
93 | public virtual float TargetValueDecayTimeScale { get; set; } | 88 | public virtual float TargetValueDecayTimeScale { get; set; } |
94 | public virtual Vector3 FrictionTimescale { get; set; } | ||
95 | public virtual float Efficiency { get; set; } | 89 | public virtual float Efficiency { get; set; } |
96 | 90 | ||
97 | public virtual float ErrorZeroThreshold { get; set; } | 91 | public virtual float ErrorZeroThreshold { get; set; } |
@@ -100,10 +94,13 @@ public class BSVMotor : BSMotor | |||
100 | public virtual Vector3 CurrentValue { get; protected set; } | 94 | public virtual Vector3 CurrentValue { get; protected set; } |
101 | public virtual Vector3 LastError { get; protected set; } | 95 | public virtual Vector3 LastError { get; protected set; } |
102 | 96 | ||
103 | public virtual bool ErrorIsZero | 97 | public virtual bool ErrorIsZero() |
104 | { get { | 98 | { |
105 | return (LastError == Vector3.Zero || LastError.LengthSquared() <= ErrorZeroThreshold); | 99 | return ErrorIsZero(LastError); |
106 | } | 100 | } |
101 | public virtual bool ErrorIsZero(Vector3 err) | ||
102 | { | ||
103 | return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)); | ||
107 | } | 104 | } |
108 | 105 | ||
109 | public BSVMotor(string useName) | 106 | public BSVMotor(string useName) |
@@ -111,16 +108,14 @@ public class BSVMotor : BSMotor | |||
111 | { | 108 | { |
112 | TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; | 109 | TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; |
113 | Efficiency = 1f; | 110 | Efficiency = 1f; |
114 | FrictionTimescale = BSMotor.InfiniteVector; | ||
115 | CurrentValue = TargetValue = Vector3.Zero; | 111 | CurrentValue = TargetValue = Vector3.Zero; |
116 | ErrorZeroThreshold = 0.001f; | 112 | ErrorZeroThreshold = 0.001f; |
117 | } | 113 | } |
118 | public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) | 114 | public BSVMotor(string useName, float timeScale, float decayTimeScale, float efficiency) |
119 | : this(useName) | 115 | : this(useName) |
120 | { | 116 | { |
121 | TimeScale = timeScale; | 117 | TimeScale = timeScale; |
122 | TargetValueDecayTimeScale = decayTimeScale; | 118 | TargetValueDecayTimeScale = decayTimeScale; |
123 | FrictionTimescale = frictionTimeScale; | ||
124 | Efficiency = efficiency; | 119 | Efficiency = efficiency; |
125 | CurrentValue = TargetValue = Vector3.Zero; | 120 | CurrentValue = TargetValue = Vector3.Zero; |
126 | } | 121 | } |
@@ -138,7 +133,8 @@ public class BSVMotor : BSMotor | |||
138 | CurrentValue = TargetValue = Vector3.Zero; | 133 | CurrentValue = TargetValue = Vector3.Zero; |
139 | } | 134 | } |
140 | 135 | ||
141 | // Compute the next step and return the new current value | 136 | // Compute the next step and return the new current value. |
137 | // Returns the correction needed to move 'current' to 'target'. | ||
142 | public virtual Vector3 Step(float timeStep) | 138 | public virtual Vector3 Step(float timeStep) |
143 | { | 139 | { |
144 | if (!Enabled) return TargetValue; | 140 | if (!Enabled) return TargetValue; |
@@ -148,9 +144,9 @@ public class BSVMotor : BSMotor | |||
148 | 144 | ||
149 | Vector3 correction = Vector3.Zero; | 145 | Vector3 correction = Vector3.Zero; |
150 | Vector3 error = TargetValue - CurrentValue; | 146 | Vector3 error = TargetValue - CurrentValue; |
151 | if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) | 147 | if (!ErrorIsZero(error)) |
152 | { | 148 | { |
153 | correction = Step(timeStep, error); | 149 | correction = StepError(timeStep, error); |
154 | 150 | ||
155 | CurrentValue += correction; | 151 | CurrentValue += correction; |
156 | 152 | ||
@@ -163,44 +159,43 @@ public class BSVMotor : BSMotor | |||
163 | TargetValue *= (1f - decayFactor); | 159 | TargetValue *= (1f - decayFactor); |
164 | } | 160 | } |
165 | 161 | ||
166 | // The amount we can correct the error is reduced by the friction | ||
167 | Vector3 frictionFactor = Vector3.Zero; | ||
168 | if (FrictionTimescale != BSMotor.InfiniteVector) | ||
169 | { | ||
170 | // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; | ||
171 | // Individual friction components can be 'infinite' so compute each separately. | ||
172 | frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X); | ||
173 | frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y); | ||
174 | frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z); | ||
175 | frictionFactor *= timeStep; | ||
176 | CurrentValue *= (Vector3.One - frictionFactor); | ||
177 | } | ||
178 | |||
179 | MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", | 162 | MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", |
180 | BSScene.DetailLogZero, UseName, origCurrVal, origTarget, | 163 | BSScene.DetailLogZero, UseName, origCurrVal, origTarget, |
181 | timeStep, error, correction); | 164 | timeStep, error, correction); |
182 | MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", | 165 | MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}", |
183 | BSScene.DetailLogZero, UseName, | 166 | BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue); |
184 | TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor, | ||
185 | TargetValue, CurrentValue); | ||
186 | } | 167 | } |
187 | else | 168 | else |
188 | { | 169 | { |
189 | // Difference between what we have and target is small. Motor is done. | 170 | // Difference between what we have and target is small. Motor is done. |
171 | if (TargetValue.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) | ||
172 | { | ||
173 | // The target can step down to nearly zero but not get there. If close to zero | ||
174 | // it is really zero. | ||
175 | TargetValue = Vector3.Zero; | ||
176 | } | ||
190 | CurrentValue = TargetValue; | 177 | CurrentValue = TargetValue; |
191 | MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", | 178 | MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}", |
192 | BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); | 179 | BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue); |
193 | } | 180 | } |
181 | LastError = error; | ||
194 | 182 | ||
195 | return CurrentValue; | 183 | return correction; |
184 | } | ||
185 | // version of step that sets the current value before doing the step | ||
186 | public virtual Vector3 Step(float timeStep, Vector3 current) | ||
187 | { | ||
188 | CurrentValue = current; | ||
189 | return Step(timeStep); | ||
196 | } | 190 | } |
197 | public virtual Vector3 Step(float timeStep, Vector3 error) | 191 | // Given and error, computer a correction for this step. |
192 | // Simple scaling of the error by the timestep. | ||
193 | public virtual Vector3 StepError(float timeStep, Vector3 error) | ||
198 | { | 194 | { |
199 | if (!Enabled) return Vector3.Zero; | 195 | if (!Enabled) return Vector3.Zero; |
200 | 196 | ||
201 | LastError = error; | ||
202 | Vector3 returnCorrection = Vector3.Zero; | 197 | Vector3 returnCorrection = Vector3.Zero; |
203 | if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) | 198 | if (!ErrorIsZero(error)) |
204 | { | 199 | { |
205 | // correction = error / secondsItShouldTakeToCorrect | 200 | // correction = error / secondsItShouldTakeToCorrect |
206 | Vector3 correctionAmount; | 201 | Vector3 correctionAmount; |
@@ -222,57 +217,155 @@ public class BSVMotor : BSMotor | |||
222 | // maximum number of outputs to generate. | 217 | // maximum number of outputs to generate. |
223 | int maxOutput = 50; | 218 | int maxOutput = 50; |
224 | MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); | 219 | MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); |
225 | MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}", | 220 | MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},eff={4},curr={5},tgt={6}", |
226 | BSScene.DetailLogZero, UseName, | 221 | BSScene.DetailLogZero, UseName, |
227 | TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, | 222 | TimeScale, TargetValueDecayTimeScale, Efficiency, |
228 | CurrentValue, TargetValue); | 223 | CurrentValue, TargetValue); |
229 | 224 | ||
230 | LastError = BSMotor.InfiniteVector; | 225 | LastError = BSMotor.InfiniteVector; |
231 | while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) | 226 | while (maxOutput-- > 0 && !ErrorIsZero()) |
232 | { | 227 | { |
233 | Vector3 lastStep = Step(timeStep); | 228 | Vector3 lastStep = Step(timeStep); |
234 | MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}", | 229 | MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}", |
235 | BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); | 230 | BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); |
236 | } | 231 | } |
237 | MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); | 232 | MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); |
238 | 233 | ||
239 | 234 | ||
240 | } | 235 | } |
241 | 236 | ||
242 | public override string ToString() | 237 | public override string ToString() |
243 | { | 238 | { |
244 | return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", | 239 | return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>", |
245 | UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); | 240 | UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale); |
246 | } | 241 | } |
247 | } | 242 | } |
248 | 243 | ||
244 | // ============================================================================ | ||
245 | // ============================================================================ | ||
249 | public class BSFMotor : BSMotor | 246 | public class BSFMotor : BSMotor |
250 | { | 247 | { |
251 | public float TimeScale { get; set; } | 248 | public virtual float TimeScale { get; set; } |
252 | public float DecayTimeScale { get; set; } | 249 | public virtual float TargetValueDecayTimeScale { get; set; } |
253 | public float Friction { get; set; } | 250 | public virtual float Efficiency { get; set; } |
254 | public float Efficiency { get; set; } | 251 | |
252 | public virtual float ErrorZeroThreshold { get; set; } | ||
253 | |||
254 | public virtual float TargetValue { get; protected set; } | ||
255 | public virtual float CurrentValue { get; protected set; } | ||
256 | public virtual float LastError { get; protected set; } | ||
255 | 257 | ||
256 | public float Target { get; private set; } | 258 | public virtual bool ErrorIsZero() |
257 | public float CurrentValue { get; private set; } | 259 | { |
260 | return ErrorIsZero(LastError); | ||
261 | } | ||
262 | public virtual bool ErrorIsZero(float err) | ||
263 | { | ||
264 | return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold); | ||
265 | } | ||
258 | 266 | ||
259 | public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency) | 267 | public BSFMotor(string useName, float timeScale, float decayTimescale, float efficiency) |
260 | : base(useName) | 268 | : base(useName) |
261 | { | 269 | { |
270 | TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; | ||
271 | Efficiency = 1f; | ||
272 | CurrentValue = TargetValue = 0f; | ||
273 | ErrorZeroThreshold = 0.01f; | ||
262 | } | 274 | } |
263 | public void SetCurrent(float target) | 275 | public void SetCurrent(float current) |
264 | { | 276 | { |
277 | CurrentValue = current; | ||
265 | } | 278 | } |
266 | public void SetTarget(float target) | 279 | public void SetTarget(float target) |
267 | { | 280 | { |
281 | TargetValue = target; | ||
282 | } | ||
283 | public override void Zero() | ||
284 | { | ||
285 | base.Zero(); | ||
286 | CurrentValue = TargetValue = 0f; | ||
268 | } | 287 | } |
288 | |||
269 | public virtual float Step(float timeStep) | 289 | public virtual float Step(float timeStep) |
270 | { | 290 | { |
271 | return 0f; | 291 | if (!Enabled) return TargetValue; |
292 | |||
293 | float origTarget = TargetValue; // DEBUG | ||
294 | float origCurrVal = CurrentValue; // DEBUG | ||
295 | |||
296 | float correction = 0f; | ||
297 | float error = TargetValue - CurrentValue; | ||
298 | if (!ErrorIsZero(error)) | ||
299 | { | ||
300 | correction = StepError(timeStep, error); | ||
301 | |||
302 | CurrentValue += correction; | ||
303 | |||
304 | // The desired value reduces to zero which also reduces the difference with current. | ||
305 | // If the decay time is infinite, don't decay at all. | ||
306 | float decayFactor = 0f; | ||
307 | if (TargetValueDecayTimeScale != BSMotor.Infinite) | ||
308 | { | ||
309 | decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; | ||
310 | TargetValue *= (1f - decayFactor); | ||
311 | } | ||
312 | |||
313 | MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", | ||
314 | BSScene.DetailLogZero, UseName, origCurrVal, origTarget, | ||
315 | timeStep, error, correction); | ||
316 | MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}", | ||
317 | BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue); | ||
318 | } | ||
319 | else | ||
320 | { | ||
321 | // Difference between what we have and target is small. Motor is done. | ||
322 | if (Util.InRange<float>(TargetValue, -ErrorZeroThreshold, ErrorZeroThreshold)) | ||
323 | { | ||
324 | // The target can step down to nearly zero but not get there. If close to zero | ||
325 | // it is really zero. | ||
326 | TargetValue = 0f; | ||
327 | } | ||
328 | CurrentValue = TargetValue; | ||
329 | MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", | ||
330 | BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); | ||
331 | } | ||
332 | LastError = error; | ||
333 | |||
334 | return CurrentValue; | ||
272 | } | 335 | } |
336 | |||
337 | public virtual float StepError(float timeStep, float error) | ||
338 | { | ||
339 | if (!Enabled) return 0f; | ||
340 | |||
341 | float returnCorrection = 0f; | ||
342 | if (!ErrorIsZero(error)) | ||
343 | { | ||
344 | // correction = error / secondsItShouldTakeToCorrect | ||
345 | float correctionAmount; | ||
346 | if (TimeScale == 0f || TimeScale == BSMotor.Infinite) | ||
347 | correctionAmount = error * timeStep; | ||
348 | else | ||
349 | correctionAmount = error / TimeScale * timeStep; | ||
350 | |||
351 | returnCorrection = correctionAmount; | ||
352 | MDetailLog("{0}, BSFMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}", | ||
353 | BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount); | ||
354 | } | ||
355 | return returnCorrection; | ||
356 | } | ||
357 | |||
358 | public override string ToString() | ||
359 | { | ||
360 | return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>", | ||
361 | UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale); | ||
362 | } | ||
363 | |||
273 | } | 364 | } |
274 | 365 | ||
275 | // Proportional, Integral, Derivitive Motor | 366 | // ============================================================================ |
367 | // ============================================================================ | ||
368 | // Proportional, Integral, Derivitive ("PID") Motor | ||
276 | // Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors. | 369 | // Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors. |
277 | public class BSPIDVMotor : BSVMotor | 370 | public class BSPIDVMotor : BSVMotor |
278 | { | 371 | { |
@@ -281,6 +374,11 @@ public class BSPIDVMotor : BSVMotor | |||
281 | public Vector3 integralFactor { get; set; } | 374 | public Vector3 integralFactor { get; set; } |
282 | public Vector3 derivFactor { get; set; } | 375 | public Vector3 derivFactor { get; set; } |
283 | 376 | ||
377 | // The factors are vectors for the three dimensions. This is the proportional of each | ||
378 | // that is applied. This could be multiplied through the actual factors but it | ||
379 | // is sometimes easier to manipulate the factors and their mix separately. | ||
380 | public Vector3 FactorMix; | ||
381 | |||
284 | // Arbritrary factor range. | 382 | // Arbritrary factor range. |
285 | // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct. | 383 | // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct. |
286 | public float EfficiencyHigh = 0.4f; | 384 | public float EfficiencyHigh = 0.4f; |
@@ -295,6 +393,7 @@ public class BSPIDVMotor : BSVMotor | |||
295 | proportionFactor = new Vector3(1.00f, 1.00f, 1.00f); | 393 | proportionFactor = new Vector3(1.00f, 1.00f, 1.00f); |
296 | integralFactor = new Vector3(1.00f, 1.00f, 1.00f); | 394 | integralFactor = new Vector3(1.00f, 1.00f, 1.00f); |
297 | derivFactor = new Vector3(1.00f, 1.00f, 1.00f); | 395 | derivFactor = new Vector3(1.00f, 1.00f, 1.00f); |
396 | FactorMix = new Vector3(0.5f, 0.25f, 0.25f); | ||
298 | RunningIntegration = Vector3.Zero; | 397 | RunningIntegration = Vector3.Zero; |
299 | LastError = Vector3.Zero; | 398 | LastError = Vector3.Zero; |
300 | } | 399 | } |
@@ -310,20 +409,24 @@ public class BSPIDVMotor : BSVMotor | |||
310 | set | 409 | set |
311 | { | 410 | { |
312 | base.Efficiency = Util.Clamp(value, 0f, 1f); | 411 | base.Efficiency = Util.Clamp(value, 0f, 1f); |
412 | |||
313 | // Compute factors based on efficiency. | 413 | // Compute factors based on efficiency. |
314 | // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot. | 414 | // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot. |
315 | // If efficiency is low (0f), use a factor value that overcorrects. | 415 | // If efficiency is low (0f), use a factor value that overcorrects. |
316 | // TODO: might want to vary contribution of different factor depending on efficiency. | 416 | // TODO: might want to vary contribution of different factor depending on efficiency. |
317 | float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f; | 417 | // float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f; |
318 | // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow; | 418 | float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow; |
419 | |||
319 | proportionFactor = new Vector3(factor, factor, factor); | 420 | proportionFactor = new Vector3(factor, factor, factor); |
320 | integralFactor = new Vector3(factor, factor, factor); | 421 | integralFactor = new Vector3(factor, factor, factor); |
321 | derivFactor = new Vector3(factor, factor, factor); | 422 | derivFactor = new Vector3(factor, factor, factor); |
423 | |||
424 | MDetailLog("{0}, BSPIDVMotor.setEfficiency,eff={1},factor={2}", BSScene.DetailLogZero, Efficiency, factor); | ||
322 | } | 425 | } |
323 | } | 426 | } |
324 | 427 | ||
325 | // Ignore Current and Target Values and just advance the PID computation on this error. | 428 | // Advance the PID computation on this error. |
326 | public override Vector3 Step(float timeStep, Vector3 error) | 429 | public override Vector3 StepError(float timeStep, Vector3 error) |
327 | { | 430 | { |
328 | if (!Enabled) return Vector3.Zero; | 431 | if (!Enabled) return Vector3.Zero; |
329 | 432 | ||
@@ -331,15 +434,16 @@ public class BSPIDVMotor : BSVMotor | |||
331 | RunningIntegration += error * timeStep; | 434 | RunningIntegration += error * timeStep; |
332 | 435 | ||
333 | // A simple derivitive is the rate of change from the last error. | 436 | // A simple derivitive is the rate of change from the last error. |
334 | Vector3 derivFactor = (error - LastError) * timeStep; | 437 | Vector3 derivitive = (error - LastError) * timeStep; |
335 | LastError = error; | 438 | |
439 | // Correction = (proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) | ||
440 | Vector3 ret = error / TimeScale * timeStep * proportionFactor * FactorMix.X | ||
441 | + RunningIntegration / TimeScale * integralFactor * FactorMix.Y | ||
442 | + derivitive / TimeScale * derivFactor * FactorMix.Z | ||
443 | ; | ||
336 | 444 | ||
337 | // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) | 445 | MDetailLog("{0}, BSPIDVMotor.step,ts={1},err={2},lerr={3},runnInt={4},deriv={5},ret={6}", |
338 | Vector3 ret = -( | 446 | BSScene.DetailLogZero, timeStep, error, LastError, RunningIntegration, derivitive, ret); |
339 | error * proportionFactor | ||
340 | + RunningIntegration * integralFactor | ||
341 | + derivFactor * derivFactor | ||
342 | ); | ||
343 | 447 | ||
344 | return ret; | 448 | return ret; |
345 | } | 449 | } |