我正在开发一种能够使用网络摄像头进行运动检测的机器人。我在C#
中这样做机器人移动得太快,所以我想以很短的时间间隔打开/关闭机器人,以降低速度。
例如,它将启动发动机然后等待0.5秒并将其关闭,此循环每2秒重复一次。这样,它的速度不会太快。我想将它包含在一个名为Move()
的函数中我只是不知道该怎么做,特别是因为我的动作检测代码每秒运行20次。根据障碍物的位置,我可能需要禁用Move()功能并激活让机器人移动到其他方向的其他功能。
关于我应该从哪里开始的任何想法/建议?
非常感谢!
答案 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)。
问候。