11using System ;
2- using System . Collections ;
32using System . Collections . Generic ;
43using System . Collections . ObjectModel ;
54using System . ComponentModel ;
5+ using System . Diagnostics ;
66using System . Linq ;
77using System . Runtime . CompilerServices ;
8- using InteractiveDataDisplay . WPF ;
98using ServoPIDControl . Annotations ;
109
1110namespace ServoPIDControl . Model
1211{
1312 public class ServoPidModel : INotifyPropertyChanged
1413 {
14+ public static float TimeSeriesLengthSec = 5.0f ;
15+
1516 private float _p ;
1617 private float _i ;
1718 private float _d ;
@@ -24,24 +25,33 @@ public class ServoPidModel : INotifyPropertyChanged
2425 private float _integrator ;
2526 private float _dFiltered ;
2627
28+ private readonly Stopwatch _stopWatch = Stopwatch . StartNew ( ) ;
29+ private readonly object _timeSeriesLock = new object ( ) ;
30+
2731 public ServoPidModel ( int id )
2832 {
2933 Id = id ;
3034
3135#if DEBUG
32- Times = new ObservableCollection < float > ( Enumerable . Range ( 0 , 500 ) . Select ( i => i / 100.0f ) ) ;
33- SetPoints = new ObservableCollection < float > ( Enumerable . Range ( id * 100 , 500 )
34- . Select ( i => i / 100 % 2 == 0 ? 80.0f : 100.0f ) ) ;
35- Inputs = new ObservableCollection < float > ( Enumerable . Range ( id * 100 , 500 )
36- . Select ( i => 90 + ( float ) Math . Sin ( i / 50.0f ) ) ) ;
37- Outputs = new ObservableCollection < float > ( Enumerable . Range ( id * 100 , 500 )
38- . Select ( i => 90 + ( float ) Math . Cos ( i / 50.0f ) ) ) ;
36+ lock ( _timeSeriesLock )
37+ {
38+ const int ts = 500 ;
39+
40+ Times = Enumerable . Range ( 0 , ts )
41+ . Select ( i => i / 100.0f ) . ToList ( ) ;
42+ SetPoints = Enumerable . Range ( id * 100 , ts )
43+ . Select ( i => i / 100 % 2 == 0 ? 80.0f : 100.0f ) . ToList ( ) ;
44+ Inputs = Enumerable . Range ( id * 100 , ts )
45+ . Select ( i => 90 + ( float ) Math . Cos ( i / 20.0f ) * 9 ) . ToList ( ) ;
46+ Outputs = Enumerable . Range ( id * 100 , ts )
47+ . Select ( i => 90 + ( float ) Math . Sin ( i / 20.0f ) * 5 ) . ToList ( ) ;
48+ }
3949#endif
4050 }
4151
4252 public int Id { get ; }
4353
44- public float P
54+ public float P
4555 {
4656 get => _p ;
4757 set
@@ -163,26 +173,35 @@ internal set
163173 }
164174
165175 // ReSharper disable MemberInitializerValueIgnored
166- public ObservableCollection < float > Times { get ; } = new ObservableCollection < float > ( ) ;
167- public ObservableCollection < float > SetPoints { get ; } = new ObservableCollection < float > ( ) ;
168- public ObservableCollection < float > Inputs { get ; } = new ObservableCollection < float > ( ) ;
169- public ObservableCollection < float > Outputs { get ; } = new ObservableCollection < float > ( ) ;
176+ public List < float > Times { get ; } = new List < float > ( ) ;
177+ public List < float > SetPoints { get ; } = new List < float > ( ) ;
178+ public List < float > Inputs { get ; } = new List < float > ( ) ;
179+
180+ public List < float > Outputs { get ; } = new List < float > ( ) ;
170181 // ReSharper restore MemberInitializerValueIgnored
171182
172183 public struct TimeSeries
173184 {
174- public ObservableCollection < float > X ;
175- public ObservableCollection < float > Y ;
185+ public float [ ] X ;
186+ public float [ ] Y ;
176187 public string Name ;
177188 }
178189
179190 public IEnumerable < TimeSeries > AllTimeSeries
180191 {
181192 get
182193 {
183- yield return new TimeSeries { X = Times , Y = SetPoints , Name = "SetPoint" } ;
184- yield return new TimeSeries { X = Times , Y = Inputs , Name = "Input" } ;
185- yield return new TimeSeries { X = Times , Y = Outputs , Name = "Output" } ;
194+ lock ( _timeSeriesLock )
195+ {
196+ if ( ! Times . Any ( ) )
197+ yield break ;
198+
199+ var timeArray = Times . ToArray ( ) ;
200+
201+ yield return new TimeSeries { X = timeArray , Y = SetPoints . ToArray ( ) , Name = "SetPoint" } ;
202+ yield return new TimeSeries { X = timeArray , Y = Inputs . ToArray ( ) , Name = "Input" } ;
203+ yield return new TimeSeries { X = timeArray , Y = Outputs . ToArray ( ) , Name = "Output" } ;
204+ }
186205 }
187206 }
188207
@@ -193,5 +212,24 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
193212 {
194213 PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( propertyName ) ) ;
195214 }
215+
216+ public void RecordTimePoint ( )
217+ {
218+ lock ( _timeSeriesLock )
219+ {
220+ Times . Add ( ( float ) _stopWatch . Elapsed . TotalSeconds ) ;
221+ SetPoints . Add ( SetPoint ) ;
222+ Inputs . Add ( Input ) ;
223+ Outputs . Add ( Output ) ;
224+
225+ var lastTime = Times . Last ( ) ;
226+ var removeCount = Times . TakeWhile ( t => lastTime - t > TimeSeriesLengthSec ) . Count ( ) ;
227+
228+ Times . RemoveRange ( 0 , removeCount ) ;
229+ SetPoints . RemoveRange ( 0 , removeCount ) ;
230+ Inputs . RemoveRange ( 0 , removeCount ) ;
231+ Outputs . RemoveRange ( 0 , removeCount ) ;
232+ }
233+ }
196234 }
197235}
0 commit comments