Come adattare gli algoritmi di path path ai movimenti limitati?


10

Immagina un movimento simile a un'auto in cui le entità non possono accendere un centesimo. Supponiamo, per motivi di discussione, che quando sono a velocità possono ruotare di 90 gradi al secondo. Ciò in molti casi cambierebbe il percorso ottimale e quindi il pathfinding. Potrebbe persino rendere del tutto impossibili i percorsi "normali".

Esistono algoritmi di pathfinding o algoritmi di pianificazione del movimento che possono tenerlo a mente o esistono modi semplici per adattare quelli popolari?


il pathfinding includerebbe anche i dati di velocità? come, andare da A a B a X km / h (o mph), o sarebbe una velocità costante? inoltre, 90 gradi al secondo a bassa velocità potrebbero finire per essere una curva molto chiusa, probabilmente anche fisicamente impossibile. (a meno che tu non abbia tutte e 4 le ruote che girano xD)
Brian H.

@BrianH. Ecco perché ho detto "ad alta velocità". In circostanze ragionevoli esisterebbero soglie minime e massime. Ma idealmente avrei un algoritmo alla ricerca di un percorso 'ideale', che possa includere variazioni di velocità.
Weckar E.

Trovo che questa sia una domanda molto interessante, ho un +1 da parte mia, non vedo l'ora di vedere alcune risposte chiare :)
Brian H.


Considererei questo come una sorta di muro invisibile. Inoltre, la maggior parte dell'algoritmo di finanziamento del percorso ha un "peso" per ciascun percorso (ad esempio, camminare nell'acqua è più lento di camminare sulla terra) in modo da poter aggiungere ulteriore peso al percorso che è più difficile da ottenere. Tutto questo può essere conosciuto solo con la velocità e la direzione dell'auto.
the_lotus

Risposte:


10

Benvenuti nel meraviglioso mondo della pianificazione del movimento non olonomo . Consiglio di farlo utilizzando un pianificatore di percorso griglia reticolare . Altre alternative includono la RRT cinodinamica e l' ottimizzazione della traiettoria . I sistemi non olonomici includono automobili, barche, monocicli o qualsiasi cosa in cui il veicolo non possa viaggiare nella direzione desiderata. La pianificazione di questi sistemi è molto più difficile dei sistemi olonomi e fino al 2000 era al limite della ricerca accademica. Al giorno d'oggi ci sono molti algoritmi tra cui scegliere decentemente.

inserisci qui la descrizione dell'immagine

Ecco come funziona.

Stato

La configurazione della tua auto q è in realtà uno stato 3D contenente la posizione x, y dell'auto e il suo orientamento t . I nodi dell'algoritmo A * sono in realtà vettori 3D.

class Node
{
    // The position and orientation of the car.
    float x, y, theta;
}

Azioni

E i bordi?

È leggermente più difficile, perché la tua auto potrebbe effettivamente scegliere un numero infinito di modi per girare la ruota. Quindi, possiamo renderlo accessibile a un pianificatore di griglia reticolare limitando il numero di azioni che l'auto può compiere su un set discreto, A . Per semplicità, supponiamo che l'auto non acceleri, ma piuttosto possa cambiare istantaneamente la sua velocità. Nel nostro caso, A può essere come segue:

class Action
{
    // The direction of the steering wheel.
    float wheelDirection;

    // The speed to go at in m/s.
    float speed;

    // The time that it takes to complete an action in seconds.
    float dt;
}

Ora, possiamo creare una serie discreta di azioni che l'auto può intraprendere in qualsiasi momento. Ad esempio, un hard right mentre si preme il gas al massimo per 0,5 secondi sarebbe simile a questo:

Action turnRight;
turnRight.speed = 1;
turnRight.wheelDirection = 1;
turnRight.dt = 0.5;

Mettere l'auto in retromarcia e il backup sarebbe simile a questo:

Action reverse;
reverse.speed = -1;
reverse.wheelDirection = 0;
reverse.dt = 0.5;

E il tuo elenco di azioni sarebbe simile al seguente:

List<Action> actions = { turnRight, turnLeft, goStraight, reverse ...}

È inoltre necessario un modo per definire il modo in cui un'azione intrapresa su un nodo risulta in un nuovo nodo. Questo si chiama il dinamica in avanti del sistema.

// These forward dynamics are for a dubin's car that can change its
// course instantaneously.
Node forwardIntegrate(Node start, Action action) 
{
    // the speed of the car in theta, x and y.
    float thetaDot = action.wheelDirection * TURNING_RADIUS;

    // the discrete timestep in seconds that we integrate at.
    float timestep = 0.001;

    float x = start.x;
    float y = start.y;
    float theta = start.theta;

    // Discrete Euler integration over the length of the action.
    for (float t = 0; t < action.dt; t += timestep)
    {
       theta += timestep * thetaDot;
       float xDot = action.speed * cos(theta);
       float yDot = action.speed * sin(theta);
       x += timestep * xDot;
       y += timestep * yDot;
    }

    return Node(x, y, theta);
}

Celle a griglia discrete

Ora, per costruire la griglia reticolare, tutto ciò che dobbiamo fare è l' hash degli stati della macchina in celle a griglia discrete. Questo li trasforma in nodi discreti che possono essere seguiti da A *. Questo è estremamente importante perché altrimenti A * non avrebbe modo di sapere se due stati delle auto sono effettivamente gli stessi per confrontarli. Effettuando l'hashing su valori di celle di griglia interi, questo diventa banale.

GridCell hashNode(Node node)
{
    GridCell cell;
    cell.x = round(node.x / X_RESOLUTION);
    cell.y = round(node.y / Y_RESOLUTION);
    cell.theta = round(node.theta / THETA_RESOLUTION);
    return cell; 
}

Ora, possiamo fare un piano A * in cui GridCells sono i nodi, Actions sono i bordi tra i nodi e Start e Goal sono espressi in termini di GridCells. L'euristica tra due griglie è la distanza in xey più la distanza angolare in theta.

Seguendo il percorso

Ora che abbiamo un percorso in termini di GridCells e Actions tra di loro, possiamo scrivere un follower di percorso per l'auto. Poiché le celle della griglia sono discrete, l'auto salta tra le celle. Quindi dovremo appianare il movimento della macchina lungo il percorso. Se il tuo gioco utilizza un motore fisico, questo può essere realizzato scrivendo un controller di sterzo che cerca di mantenere l'auto il più vicino possibile al percorso. Altrimenti, puoi animare il percorso usando curve di Bezier o semplicemente facendo la media dei pochi punti più vicini nel percorso.


Post eccellente (e anche breve! Faccio qualcosa di simile per le barche - scivoloso :-). Otoh, c'è più spazio,
Stormwind

4

La maggior parte degli algoritmi di ricerca del percorso funzionano su un grafico arbitrario senza restrizioni di geometria.

Quindi, ciò che devi fare è aggiungere l'orientamento dell'auto a ciascun nodo esplorato e limitare quali nodi sono effettivamente connessi.


Il problema è che l'auto potrebbe visitare lo stesso nodo avvicinandosi da direzioni diverse, il che pone restrizioni diverse sulle connessioni che possono essere attraversate da lì.
Weckar E.

6
@WeckarE. Ma l'auto non visita lo stesso nodo. Visita 2 nodi che hanno la stessa posizione ma orientamento diverso
maniaco del cricchetto

3
@WeckarE. Tratta quelli come due nodi separati. Il grafico fisico e il grafico logico non devono necessariamente essere gli stessi.
BlueRaja - Danny Pflughoeft

1

I miei pensieri, non li ho mai testati!

  1. Eseguire A * dall'inizio alla destinazione, restituire il percorso.
  2. Passa attraverso il percorso, quando rilevi una svolta, usa un bezier algoritmo più (o qualsiasi altro simile) che utilizza la velocità corrente del cercatore per prevedere i nodi che creeranno una svolta regolare. Assicurarsi che tenti di tornare al nodo percorso più vicino.
  3. Se il turno può essere fatto, ottimo, in caso contrario, ripetere con una velocità più lenta, facendo una svolta più acuta.
  4. Una volta creato il percorso corretto, tornare indietro attraverso il percorso regolando la velocità del cercatore prima che venga svolta la svolta in modo che rallenti alla velocità corretta prima di iniziare la svolta.
  5. Se non è possibile effettuare il turno, esegui di nuovo il tutto. Assicurati solo che tutti i nodi gestiti della svolta che non possono essere fatti siano nella lista chiusa, quindi vengono ignorati. E potresti iniziare dal punto in cui è iniziata la svolta in modo da poter saltare la parte di successo del percorso, tuttavia, in alcuni casi ciò potrebbe comportare un percorso non ottimale.

Dovresti anche essere in grado di farlo senza dover prima completare il percorso, ergo: gestire le curve durante A *, che probabilmente sarà molto meglio ottimizzato, ma potrebbe anche rivelarsi problematico e glitch, non lo saprei davvero e sfortunatamente non ho il tempo di provarlo da solo.

pathfinding


0

Se il tuo agente ha il pieno controllo dell'auto, fallo al contrario. Collegare prima una linea dall'inizio alla fine, quindi capire a quale velocità è possibile navigare ogni turno, in modo simile alla risposta di Dennis.

Tuttavia, non disegnare curve di Bezier da punti fissi. Per ridurre al minimo la perdita di velocità è necessario spostare l'intera linea, quindi iniziare inserendo nodi extra a una distanza più o meno uniforme e quindi spostarsi per ridurre al minimo l'energia o strategie simili. Per i dettagli è necessario esaminare la generazione della linea AI nei giochi di corse (preferibilmente sim o semi-sim).

Una volta che hai il sistema di linea AI in esecuzione, esegui la tua ricerca A * e per ogni percorso vai almeno un angolo in avanti, quindi calcola la linea AI che ti dà una stima del tempo. Questa sarebbe la tua funzione di costo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.