6

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

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

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

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

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

非常感谢!

4

8 回答 8

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 秒暂停半秒。

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

前移停止 检查物体旋转以瞄准物体 前移停止

等等

因此,在您的主程序控制循环中,假设调用是同步的(即,您的程序在执行命令时停止,就像上面的 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
}

请记住在您的操作完成时更改状态。

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

于 2010-05-10T13:07:28.720 回答
3

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

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

于 2010-05-10T13:52:49.863 回答
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();
  }
}
于 2010-05-10T13:44:50.097 回答
1

我建议你看看微软机器人工作室? 从未使用过它,但他们实际上可能会解决此类问题。可能还有其他你还没有遇到的。

另一种选择是使用XNA 的计时机制编写应用程序。 只是不是渲染到屏幕上,而是渲染到你的机器人,有点。

于 2010-05-10T13:12:40.657 回答
0

您可以尝试使用 -

Thread.Sleep(500);

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

于 2010-05-10T13:06:24.787 回答
0

在工作中添加暂停的一种方法是在通话之间添加睡眠。您可以在通话之间设置睡眠。设置睡眠是这样的:System.Threading.Thread.Sleep(5000);5000 是 5000 毫秒。

于 2010-05-10T13:07:10.863 回答
0

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

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

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

但你的问题是一个非常困难的问题。您能否指定您的机器人拥有什么样的操作系统或/和环境(库、框架等)?

于 2010-05-10T13:11:45.103 回答
0

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

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

问候。

于 2010-05-10T13:12:18.677 回答