9
votes

Algorithme pour contrôler l'accélération jusqu'à ce qu'une position soit atteinte

J'ai un point qui se déplace (dans une dimension) et j'en ai besoin de bouger en douceur. Je pense donc que sa vitesse doit être une fonction continue et je dois contrôler l'accélération, puis calculer sa vitesse et sa position.

L'algorithme ne semble pas quelque chose d'évident pour moi, mais je suppose que cela doit être un problème commun, je ne trouve tout simplement pas la solution.

Notes:

  • La destination finale de l'objet peut changer lors de sa déménagement et que le mouvement doit être lisse de toute façon.
  • Je suppose qu'une implémentation naïve produirait des rebondissements et je dois éviter cela.

1 commentaires

4 Réponses :


-1
votes

Vous avez besoin d'une formule d'assouplissement, que vous appelleriez à un intervalle défini, passant dans le temps écoulé, point de départ, point final et durée que vous souhaitez que l'animation soit.

Faire des calculs temps basés sur le temps représentera des clients lents et d'autres hochcups aléatoires. Étant donné que cela calcule à temps écoulé contre le temps dans lequel il doit compkete, il représentera des intervalles lents entre les appels lors de leur retour à quel point votre point devrait être dans l'animation.

Le plugin JQuery.asing a une tonne d'assouplissement des fonctions que vous pouvez regarder:

http://gsgd.co.uk/sandbox/jquery/asing/

J'ai trouvé le mieux de passer en 0 et 1 comme mon point de départ et de fin, car il retournera un point flottant entre les deux, vous pouvez facilement l'appliquer à la valeur réelle que vous modifiez à l'aide de la multiplication.


1 commentaires

Une formule d'assouplissement ne fonctionnera pas pour moi car le point de destination peut changer à tout moment. Avec une formule d'assouplissement, je devrais changer le point de départ / fin à ce moment-là et le mouvement ne sera pas lisse puis.



27
votes

Ceci est un candidat parfait pour utiliser un "ressort" de manière critique ".

Conceptuellement, vous attachez le point au point cible avec un ressort ou un morceau d'élastique. Le printemps est amorti de sorte que vous n'obtenez pas de «rebondir». Vous pouvez contrôler la rapidité avec laquelle le système réagit en changeant une constante appelée «SpringConstant». C'est essentiellement à quel point le morceau d'élastique est fort. P>

essentiellement, vous appliquez deux forces à la position, puis intégrez cela au fil du temps. La première force est appliquée par le printemps, FS = SpringConstant * distancestotarget. La seconde est la force d'amortissement, FD = -CurrentVelocity * 2 * sqrt (SpringConstant). P>

La cour que la couronne forme fait partie de l'état du système et peut être initialisé à zéro. P>

Dans chaque étape, vous multipliez la somme de ces deux forces à l'étape chronologique. Cela vous donne le changement de valeur de la courante actuelle. Multipliez-le à nouveau à nouveau et cela vous donnera le déplacement. P>

Nous ajoutons cela à la position réelle du point. P>

en C ++ Code: P>

float CriticallyDampedSpring( float a_Target,
                              float a_Current,
                              float & a_Velocity,
                              float a_TimeStep )
{
    float currentToTarget = a_Target - a_Current;
    float springForce = currentToTarget * SPRING_CONSTANT;
    float dampingForce = -a_Velocity * 2 * sqrt( SPRING_CONSTANT );
    float force = springForce + dampingForce;
    a_Velocity += force * a_TimeStep;
    float displacement = a_Velocity * a_TimeStep;
    return a_Current + displacement;
}


11 commentaires

+1 pour l'explication et la formule. (Et c'était un problème que je réfléchissiez il y a quelque temps)


Semble intéressant, demain je vais tester le code. Merci beaucoup!


Alex, j'ai déjà accepté la réponse, mais je pense: y a-t-il un moyen de faire fonctionner la fonction de vélocité? Donc, cela s'accélérerait aussi vite que cela se dépélère? En ce moment, il est très rapide au début et lentement à la fin.


En haut de ma tête, il ne sonne pas juste qu'il devrait être beaucoup plus rapide au début. Initialisez-vous la vélocité à zéro?


(J'allais poster quelque chose plus tôt, mais hésitait.) Quand j'ai lu cette réponse, j'étais très proche de "-1" - à-suivre, car même si c'est bien pensé, cela n'est pas approprié pour la planification de la trajectoire.


Je suis peut-être un peu en retard à la fête , mais le 2 n'est-ce pas la masse?


Pour moi, cela a également travaillé pour suivre un objet (au lieu d'atteindre simplement une position). Pour ce faire, je n'avais que de passer une vitesse relative (vélocité d'objet actuelle - vélocité d'objet cible) au lieu de vélocité d'objet actuelle.


J'ai essayé de mettre en œuvre cela en 2D à l'aide de JavaScript pour suivre le curseur de la souris. Vous pouvez le voir ici: jsfiddle.net/bflah/3170 mais cela ne semble pas être Travailler entièrement bien, parfois l'objet devient plus proche au lieu de plus près et de sorte de diagonale. Peut-être qu'il y a une erreur dans mon code.


@brunodeleo Le problème avec votre code est que vous ne suivez pas la vitesse de chaque dimension séparément. C'est-à-dire que vous avez besoin d'une vélocityx et d'une vélocité.


Excellent! Merci@alexdeem :)


Parfait! Merci !



0
votes

Ce n'est pas tout à fait clair exactement ce que vous êtes après, mais je vais supposer ce qui suit:

  1. Il y a une accélération maximale; li>
  2. vous voulez que l'objet ait cessé de bouger lorsqu'il atteigne la destination; Li>
  3. Contrairement à la vitesse, vous n'avez pas besoin d'accélération pour être continue. LI> ol>

    laisse un em> l'accélération maximale (par laquelle je veux dire que l'accélération est toujours comprise entre - a em> et a em>). p>

    l'équation que vous voulez est p> xxx pré>

    v_f em> = 0 est la vélocité finale, v_i em > Est la vitesse initiale (actuelle) et d em> est la distance à la destination (lorsque vous passez d'accélération a em> à accélération - a em> - - c'est-à-dire d'accélérer pour ralentir; ici, je suppose d em> est positif). p>

    Résolution: p>

    new_position = old_position + old_velocity * t_step + (1/2)a(t_step)^2
    new_velocity = old_velocity + a * t_step.
    


2 commentaires

@Damain A est une constante que vous pouvez définir quelque chose. Des valeurs plus élevées d'une moyenne L'objet (de) accélère plus rapidement. Vous devrez expérimenter de déterminer quelle valeur pour obtenir des résultats dans le comportement souhaité. L'algorithme décrit ci-dessus vous dit quand définir A = A ou A = -A, où "A" est l'accélération de l'objet. J'ai mis à jour ma réponse pour expliquer comment calculer la position de cela. En outre, cela aboutira à la vitesse / ralentissement symétrique que vous avez demandé dans un autre poste.


Le problème avec juste définir new_position = destination à la fin est-il peut provoquer une picture en accélération au dernier point pouvant dépasser l'accélération maximale (il slams dans la finale position; la vitesse est faible, mais la décélération peut être assez élevée en raison de la vitesse discontinue du calcul précédent).



0
votes

Je ferais quelque chose comme la réponse de Alex Deem pour la planification de la trajectoire, mais avec des limites de force et de vitesse:

dans pseudocode: xxx

où ki et kp sont Les constantes de syntonisation, Fmax et Vmax sont une force et une vitesse maximales. Cela devrait fonctionner pour des situations 1-D, 2-D ou 3D (magnitude (Y) = ABS (Y) en 1-D, sinon utilisez la magnitude de vecteur).


0 commentaires