我有一个关于如何为我的机器人编程某个序列的问题。
让我说如果我想编程让它从位置a运行到b,我有一个传感器附加到它应该检测到x,它会在它检测x的位置执行一个名为y的动作,其中action并没有改变它的立场。
我希望机器人在执行动作y之后从它离开的地方继续前进到b。但是我不知道如何暂停从a到b的序列,并在执行动作y之后从它停止的地方继续。我只控制车轮的电机及其时间,所以我只能在一定时间内设定车轮的速度。
在c ++中是否有一般的暂停功能(不是睡眠)并继续从暂停的位置运行其代码行?
现在我知道如何重置它的动作,但这不是我想要的。
示例(使机器人在10秒内从a移动到b,在3秒内检测物体x,在t = 3秒时在位置执行动作y,在完成动作y后继续运动7秒)
答案 0 :(得分:0)
您可以尝试使用某些事件(消息)驱动架构,如下面的伪代码:
vector<action> action_sequence={do_a,do_b,do_c};
int i=0;
while(1)
{
e = WaitForMessage();
switch(e.code)
{
case do_action:
action_sequence[i].run();//perform an action
...//some code to have a scheduler thread to send next
//do_action message in certain seconds to this thread.
i++;
default:
...
}
}
答案 1 :(得分:0)
答案取决于您的代码,您使用的是Windows消息,是否使用了线程等等。假设您不使用线程代码,只需线性代码即可实现自己的睡眠功能,该功能由调用者传递给函数。如果应该抢占睡眠,则用于访问。如果被抢占,则该函数返回剩余的时间,以便稍后继续操作。
这允许线性代码处理您的情况。我敲了一个样本。将解释这些内容。
typedef bool (*preempt)(void);
DWORD timedPreemptableAction (DWORD msTime, preempt fn)
{
DWORD startTick = GetTickCount();
DWORD endTick = startTick + msTime;
DWORD currentTick;
do
{
currentTick = GetTickCount();
}
while (fn () == false && currentTick < endTick);
return currentTick > endTick ? 0 : endTick-currentTick;
}
上面的关键函数,以毫秒为单位获取开始时间,并且在超时到期之前不会退出 - 或者用户提供的函数返回true。
这个用户提供的功能可以轮询输入设备,如键盘按等。现在为了匹配你的问题,我添加了一个用户函数,在3秒后返回true:
DWORD startToTurnTicks = 0;
bool startToTurn (void)
{
bool preempt = false;
// TODO Implement method of preemption. For now
// just use a static timer, yep a little hacky
//
// 0 = uninitialized
// 1 = complete, no more interruptions
// >1 = starting tick count
if (startToTurnTicks == 0)
{
startToTurnTicks = GetTickCount();
}
else
{
if (startToTurnTicks != 1)
{
if ((startToTurnTicks + 3000) < GetTickCount())
{
startToTurnTicks = 1;
preempt = true;
}
}
}
return preempt;
}
现在我们有一个等待N次并且可以退出的功能,以及一个在3秒后返回true的用户功能,现在是主要的呼叫:
bool neverPreempt (void)
{
return false;
}
int main (void)
{
int appResult = 0;
DWORD moveForwardTime = 1000*10;
DWORD turnTime = 1000*3;
DWORD startTicks = GetTickCount();
printf ("forward : %d seconds in\n",
(GetTickCount()-startTicks)/1000);
moveForwardTime = timedPreemptableAction (moveForwardTime, &startToTurn);
printf ("turn : %d seconds in\n",
(GetTickCount()-startTicks)/1000);
turnTime = timedPreemptableAction (turnTime, &neverPreempt);
printf ("turn complete : %d seconds in\n",
(GetTickCount()-startTicks)/1000);
if (moveForwardTime > 0)
{
printf ("forward again : %d seconds in\n",
(GetTickCount()-startTicks)/1000);
moveForwardTime = timedPreemptableAction (moveForwardTime, &neverPreempt);
printf ("forward complete : %d seconds in\n",
(GetTickCount()-startTicks)/1000);
}
return appResult;
}
在主代码中,您会看到timedPreemptableAction被调用3次。我们第一次通过3秒后变为真的用户功能。第一个呼叫在返回7秒后三秒钟后退出。应用程序的输出返回:
f:\projects\cmake_test\build\Debug>main
forward : 0 seconds in
turn : 3 seconds in
turn complete : 6 seconds in
forward again : 6 seconds in
forward complete : 13 seconds in
开始前进@ 0秒,&#34;暂停&#34; @ 3秒,恢复@ 6并完成@ 13。
0-> 3 + 6-> 13 = 10秒。