在C#中运行一段代码一段时间?

时间:2010-05-10 13:01:48

标签: c# robot

我正在开发一种能够使用网络摄像头进行运动检测的机器人。我在C#

中这样做

机器人移动得太快,所以我想以很短的时间间隔打开/关闭机器人,以降低速度。

例如,它将启动发动机然后等待0.5秒并将其关闭,此循环每2秒重复一次。这样,它的速度不会太快。我想将它包含在一个名为Move()

的函数中

我只是不知道该怎么做,特别是因为我的动作检测代码每秒运行20次。根据障碍物的位置,我可能需要禁用Move()功能并激活让机器人移动到其他方向的其他功能。

关于我应该从哪里开始的任何想法/建议?

非常感谢!

8 个答案:

答案 0 :(得分:5)

首先,我们需要确定您的程序如何流动。

是执行一个命令,等待,然后执行下一个命令?或者它是否同时执行命令? (例如,移动并做其他事情)

我想你会希望它按顺序执行命令,而不是你的电机系统可能不支持的一些复杂的线程。

为了让你的机器人慢慢移动,我建议创建一个Move()方法,它接受一个参数,你希望它花费多少时间移动,如下所示:

public void Move(int numberOfSeconds)
{
   while (numberOfSeconds > 0)
   {

      myRobot.MotorOn();
      Thread.Sleep(2000);
      myRobot.MotorOff();
      Thread.Sleep(500);

      numberOfSeconds -= 2;
   }
}

这不是确切的,但这是一种做法。

如果你然后调用Move(10),你的机器人将移动10秒钟,并且每2秒暂停半秒钟。

关于您的程序流程问题,您可能希望将其视为指令列表:

向前迈进 停 检查对象 在对象上转向目标 向前迈进 STOP

所以在你的主程序控制循环中,假设调用是同步的(即你的程序在执行命令时停止,就像上面的Move方法一样),你可以简单地拥有一堆IF语句(或者一个开关) )

public void Main()
{

   // What calculations should the robot do?
   If (someCalculations == someValue)
   {
     // Rotate the robot to face the object
     robot.RotateRight(10);
   }
   else if (someOtherCalculation == someValue)
   {
     // We are on course, so move forward
     Move(10);
   }
}

这可能会帮助您入门。

但是,如果您的机器人是异步的,也就是说,代码在机器人正在运行时保持运行(例如您经常从运动传感器获得反馈),则必须以不同方式构建程序。 Move()方法可能仍然有效,但您的程序流程应该略有不同。您可以使用变量来跟踪状态:

public enum RobotStates
{
  Searching,
  Waiting,
  Hunting,
  Busy,
}

然后在主循环中,您可以检查状态:

if (myRobotState != RobotStates.Busy)
{
  // Do something
}

请记住在行动完成后更改状态。

完全有可能您必须使用线程进行异步解决方案,因此从传感器接收反馈的方法不会等待机器人移动,但可以继续轮询。虽然线程超出了这个答案的范围,但是有很多资源。

答案 1 :(得分:3)

您遇到了一个非常常见的问题,即当您的执行器只有ON和OFF状态时,如何控制一个过程。您提出的解决方案是一种常见的解决方案,即通过打开/关闭电机来设置“占空比”。在大多数情况下,您可以购买将为您执行此操作的电机控制器,这样您就不必担心细节。一般来说,您希望脉冲频率更高,因此运动中可观察到的“断断续续”。

如果这是一个教育项目,您可能对Motor Controllers的理论感兴趣。您可能还想阅读Control Theory(特别是PID控制),因为您可以使用其他反馈(您有什么方法来感知速度吗?)来自动控制电机以保持您想要的速度。

答案 2 :(得分:2)

Thread.Sleep()可能不是您想要的,因为如果您的硬件能够,您希望在移动时继续运行传感器等。我想到的第一个解决方案是使用计时器。这样你就可以在需要时继续处理和处理你的动作。

(还没有测试过这段代码,但它得到了这个想法)

System.Timers.Timer Timer = new Timer();
bool Moving;

void init()
{
  Timer.AutoReset = false;
  Timer.Elapsed += OnMoveTimerEvent;
  Moving = false;
}

void MainLoop()
{
   //stuff

   if(should move)
   {
     timer.start();
   }

   if(should stop moving)
   {
     timer.stop();
   }
}


void OnMoveTimerEvent(object source, ElapsedEventArgs e)        
{
  if (!Moving)
  {
    //start motor
    Timer.Interval = 500;
    Moving = true;
    Timer.Start();
  }
  else
  {
    //stop motor
    Moving = true;
    Timer.Interval = 2000;
    Timer.Start();
  }
}

答案 3 :(得分:1)

我建议你研究Microsoft Robotics Studio?从未使用它,但它们实际上可能会解决这类问题。还有其他你还没有遇到的。

另一种选择是使用XNA's timing mechanisms.来编写应用程序而不是渲染到屏幕上,而是渲染给你的机器人。

答案 4 :(得分:0)

您可以尝试使用 -

Thread.Sleep(500);

这段代码将使当前正在运行的线程休眠500毫秒。

答案 5 :(得分:0)

将暂停添加到工作中的一种方法是在呼叫之间添加睡眠。你可以在两次通话之间进行睡眠。放睡是这样的:System.Threading.Thread.Sleep(5000); 5000是5000毫秒。

答案 6 :(得分:0)

听起来您希望主线程定期执行函数。如果您的机器人安装了.NET-Framework,则可以使用线程库。

while(condition)
{
    //Wait a number ms (2000 ms = 2 secons)
    Thread.Sleep(2000); 
    //Do something here, e.g. move

    Thread.Sleep(500);
    //...
}

但是你的问题非常棘手。你能指出你的机器人有哪种操作系统或/和环境(图书馆,框架......)?

答案 7 :(得分:0)

就运动检测和障碍物检测而言,您的代码应使用复杂的线程。对于您的电机速度问题,您是否尝试在单独的线程中执行Move()调用。

并且在for循环中,您可以在每次MotorOff()调用后使用Thread.Sleep(2 * 1000)。

问候。