C# 在C中以10-15毫秒的间隔记录来自结构的数据#
我必须准备Logger类,该类将以10-15毫秒的间隔保存3个结构的数据。我解决此问题的方法如下:C# 在C中以10-15毫秒的间隔记录来自结构的数据#,c#,logging,timer,intervals,C#,Logging,Timer,Intervals,我必须准备Logger类,该类将以10-15毫秒的间隔保存3个结构的数据。我解决此问题的方法如下: public class Logger { // Variables private Task loggerTask; public bool IsActive { get; set; } // Constructor public Logger() { } private void Logging() { #i
public class Logger
{
// Variables
private Task loggerTask;
public bool IsActive { get; set; }
// Constructor
public Logger()
{
}
private void Logging()
{
#if DEBUG
System.Diagnostics.Debug.WriteLine("Logging has been started.");
#endif
FileStream fs = new FileStream($"./log {DateTime.Now.ToString("dd.MM HH.mm.ss")}.txt", FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs, Encoding.Default);
try
{
Queue<double> times = new Queue<double>();
Queue<Attitude> attitudes = new Queue<Attitude>();
Queue<LocalPositionNed> positions = new Queue<LocalPositionNed>();
Queue<SetPositionTargetLocalNed> setpoints = new Queue<SetPositionTargetLocalNed>();
// Logs data
DateTime start = DateTime.Now;
DateTime last = start;
DateTime now;
while (IsActive)
{
now = DateTime.Now;
if ((now - last).TotalMilliseconds < 16)
continue;
last = now;
times.Enqueue((now - start).TotalMilliseconds);
attitudes.Enqueue(GCS.Instance.Drone.Attitude);
positions.Enqueue(GCS.Instance.Drone.LocalPositionNed);
setpoints.Enqueue(GCS.Instance.Offboard.SetPoint);
}
// Save data
for(int i = 0; i < times.Count; i++)
{
sw.WriteLine($"{times.ElementAt(i)}\t" +
$"{attitudes.ElementAt(i).Pitch}\t" +
$"{attitudes.ElementAt(i).Roll}\t" +
$"{attitudes.ElementAt(i).Yaw}\t" +
$"{attitudes.ElementAt(i).Pitchspeed}\t" +
$"{attitudes.ElementAt(i).Rollspeed}\t" +
$"{attitudes.ElementAt(i).Yawspeed}\t" +
$"{positions.ElementAt(i).X}\t" +
$"{positions.ElementAt(i).Y}\t" +
$"{positions.ElementAt(i).Z}\t" +
$"{positions.ElementAt(i).Vx}\t" +
$"{positions.ElementAt(i).Vy}\t" +
$"{positions.ElementAt(i).Vz}\t" +
$"{setpoints.ElementAt(i).Vx}\t" +
$"{setpoints.ElementAt(i).Vy}\t" +
$"{setpoints.ElementAt(i).Vz}\t");
}
}
catch (Exception ex)
{
#if DEBUG
System.Diagnostics.Debug.WriteLine($"Logging exception: {ex.Message}");
#endif
}
finally
{
sw.Dispose();
fs.Dispose();
}
#if DEBUG
System.Diagnostics.Debug.WriteLine("Logging has been ended.");
#endif
}
// Static method
public void Start()
{
IsActive = true;
loggerTask = new Task(Logging);
loggerTask.Start();
}
public void Stop()
{
IsActive = false;
}
}
公共类记录器
{
//变数
私有任务日志任务;
公共bool IsActive{get;set;}
//建造师
公共记录器()
{
}
私有无效日志记录()
{
#如果调试
System.Diagnostics.Debug.WriteLine(“日志记录已启动”);
#恩迪夫
FileStream fs=newfilestream($”/log{DateTime.Now.ToString(“dd.MM HH.MM.ss”)}.txt),FileMode.Create,FileAccess.Write);
StreamWriter sw=新StreamWriter(fs,Encoding.Default);
尝试
{
队列时间=新队列();
队列态度=新队列();
队列位置=新队列();
队列设置点=新队列();
//日志数据
DateTime start=DateTime.Now;
DateTime last=开始;
现在是约会时间;
while(IsActive)
{
现在=日期时间。现在;
如果((现在-最后).total毫秒<16)
继续;
最后=现在;
times.Enqueue((now-start).total毫秒);
态度。排队(地面军事系统实例。无人机。态度);
positions.Enqueue(GCS.Instance.Drone.localpositioned);
设置点。排队(GCS.Instance.Offboard.SetPoint);
}
//保存数据
for(int i=0;i
我对时间间隔有问题,因为它们的变化范围约为5-8毫秒。我的项目要求最大变化范围为1-2毫秒。有人知道我如何改进我的方法吗
感谢您的回复。最大的问题可能是使用
日期时间。现在
的分辨率很低,不适合此类任务
一个更合适的简单替代方案是
var延迟=16;
var stopwatch=stopwatch.StartNew();
长电流=0;
很久以前;
var next=秒表.ElapsedMilliseconds+延迟;
对于(int i=0;i<100;i++)
{
while(下一步>秒表。延时百万秒)
{
//旋转
}
next=秒表.ElapsedMilliseconds+延迟;
先前=当前;
当前=秒表。延时毫秒;
var delta=当前-先前;
控制台写入线(“增量:+增量”);
}
如评论中所述,这并没有提供任何有力的保证,只是尽了最大努力。还有更好的方法可以做到这一点,而不浪费整个线程什么也不做,例如使用。但是,只要CPU上的负载很轻,它就足以用于测试/调试目的。因为运行此代码的操作系统很可能不是实时操作系统,所以它无法提供如此严格的定时保证。在任何时候,操作系统都可能决定您的进程\线程有足够的CPU时间,并切换到另一个进程\线程,然后在未知的时间后返回到您的进程。即使5-8毫秒也不能保证—10毫秒的延迟并不罕见,整秒也不未知。在像Windows这样的非实时操作系统上,你根本无法达到这样的精度。好吧,我明白。但还有一个问题。如何检查我的操作系统能保证哪种精度?非实时操作系统不能保证任何精度。对于实时操作系统,请查看文档。例如,RTLinux。一个简单的解决方案是将应用程序的优先级更改为更高的优先级,以便获得更均匀的数据。应用程序以正常优先级运行,因此操作系统任务的优先级高于应用程序,并且响应不均匀。
var delay = 16;
var stopwatch = Stopwatch.StartNew();
long current = 0;
long previous;
var next = stopwatch.ElapsedMilliseconds + delay;
for (int i = 0; i < 100; i++)
{
while (next > stopwatch.ElapsedMilliseconds)
{
// Spin
}
next = stopwatch.ElapsedMilliseconds + delay;
previous = current;
current = stopwatch.ElapsedMilliseconds;
var delta = current - previous;
Console.WriteLine("Delta: " + delta);
}