暂停功能并从机器人运动中的某个点继续

时间:2017-10-15 03:11:07

标签: c++

我有一个关于如何为我的机器人编程某个序列的问题。

让我说如果我想编程让它从位置a运行到b,我有一个传感器附加到它应该检测到x,它会在它检测x的位置执行一个名为y的动作,其中action并没有改变它的立场。

我希望机器人在执行动作y之后从它离开的地方继续前进到b。但是我不知道如何暂停从a到b的序列,并在执行动作y之后从它停止的地方继续。我只控制车轮的电机及其时间,所以我只能在一定时间内设定车轮的速度。

在c ++中是否有一般的暂停功能(不是睡眠)并继续从暂停的位置运行其代码行?

现在我知道如何重置它的动作,但这不是我想要的。

示例(使机器人在10秒内从a移动到b,在3秒内检测物体x,在t = 3秒时在位置执行动作y,在完成动作y后继续运动7秒)

2 个答案:

答案 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秒。