2 votes

fonction de pause et continuer à partir d'un certain point dans un mouvement de robot

J'ai une question sur la façon de programmer une certaine séquence pour mon robot.

Disons que si je veux programmer une machine pour qu'elle se déplace de la position a à la position b, j'ai un capteur attaché à la machine qui, s'il détecte x, exécute une action appelée y à la position où il détecte x, où l'action y ne change pas sa position.

je voudrais que le robot continue à partir de là où il s'est arrêté après avoir effectué l'action y pour aller vers b. cependant, je ne sais pas comment mettre en pause la séquence de a à b et continuer à partir de là où il s'est arrêté après avoir effectué l'action y. je ne contrôle que le moteur des roues et son timing, donc je ne peux régler la vitesse des roues que pendant un certain temps.

existe-t-il une fonction de pause en général( pas sleep) en c++ et de continuer à exécuter ses lignes de code à partir de là où elle s'est arrêtée ?

Pour l'instant, je sais comment réinitialiser son action mais ce n'est pas ce que je veux.

exemple( faire en sorte que le robot se déplace de a à b en 10 secondes, détecter l'objet x à 3 secondes, effectuer l'action y à la position lorsque t =3 secondes, continuer le mouvement pendant les 7 secondes restantes après que l'action y ait été effectuée)

0voto

James Dong Points 364

Vous pouvez essayer d'utiliser une architecture de pilotage des événements (messages) comme le pseudo-code suivant :

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:
       ...
    }
}

0voto

Chris Points 929

La réponse dépendrait de votre code, utilisez-vous la messagerie Windows, utilisez-vous le thread, etc. En supposant que vous n'utilisiez ni l'un ni l'autre, vous pourriez implémenter votre propre fonction de sommeil à laquelle l'appelant transmet une fonction qui est utilisée pour savoir si le sommeil doit être préempté. Si elle est préemptée, la fonction renvoie le temps restant pour que l'action puisse être poursuivie ultérieurement.

Cela permet au code linéaire de gérer votre situation. J'ai mis au point un échantillon. J'expliquerai les détails.

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;
}

La fonction clé ci-dessus, obtient l'heure de début en millisecondes, et ne sortira pas avant que le délai n'expire - ou que la fonction fournie par l'utilisateur ne renvoie vrai.

Cette fonction fournie par l'utilisateur pourrait interroger les dispositifs d'entrée tels que la pression d'un clavier, etc. Pour l'instant, pour répondre à votre question, j'ai ajouté une fonction utilisateur qui renvoie vrai, après 3 secondes :

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;
}

Maintenant nous avons une fonction qui attend pendant N temps et peut sortir, et une fonction utilisateur qui retournera vrai après 3 secondes, maintenant l'appel principal :

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;
}

Dans le code principal, vous voyez que timedPreemptableAction est appelé 3 fois. La première fois, nous passons la fonction utilisateur qui devient vraie après 3 secondes. Ce premier appel se termine après 3 secondes, laissant 7 secondes. La sortie de l'application renvoie :

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

A commencé à avancer à 0 seconde, s'est "arrêté". @3 secondes, restauré @6 et terminé @13.

0->3 + 6->13 = 10 secondes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X