Non ho ancora elaborato tutte le equazioni per questo, ma ecco alcuni elementi visivi per aiutare a avvolgere la testa attorno al problema. Si riduce a una certa geometria:
( Icone auto via Kenney )
Da qualsiasi dato punto di partenza e orientamento, possiamo disegnare due cerchi con il nostro raggio di sterzata minimo: uno a sinistra, uno a destra. Questi descrivono i punti nel modo più stretto possibile per iniziare il nostro percorso.
Possiamo fare lo stesso per qualsiasi posizione finale e orientamento desiderati. Questi cerchi descrivono la fine più stretta possibile del nostro percorso.
Ora il problema si riduce a trovare un percorso che unisce uno dei cerchi iniziali a uno dei cerchi finali, baciandoli lungo la sua tangente.
(Questo presuppone che non abbiamo bisogno di individuare gli ostacoli nel mezzo, che non è stato menzionato nella domanda. La risposta di Stormwind spiega come possiamo usare le informazioni del grafico di navigazione per questi tipi di problemi. Una volta che abbiamo la sequenza di nodi per passare, possiamo applicare il metodo seguente per ogni segmento del piano.)
Se, per semplicità, usiamo linee rette, otteniamo qualcosa del genere:
Questo ci dà il caso limitante. Una volta trovato un percorso con questo metodo, puoi gonfiare artificialmente uno o entrambi i cerchi di inizio e fine per ottenere un percorso meno diretto ma più fluido, fino al punto in cui i due cerchi si baciano.
Calcolo di questi percorsi
Elaboriamo i casi per una direzione di svolta - diciamo che iniziamo il nostro percorso girando a destra.
Il centro del nostro cerchio di svolta a destra è:
startRightCenter = carStart.position + carStart.right * minRadius
Chiamiamo l'angolo della sezione diritta del nostro percorso (misurato dall'asse x positivo) pathAngle
Se disegniamo un vettore dal rightCenter
punto in cui lasciamo il cerchio di svolta (a quel punto dobbiamo essere rivolti verso pathAngle), allora quel vettore è ...
startOffset = minRadius * (-cos(pathAngle), sin(pathAngle))
Ciò significa che il punto in cui lasciamo il cerchio deve essere ...
departure = startRightCenter + startOffset
Il punto in cui rientriamo in un cerchio di svolta dipende dal fatto che stiamo mirando a terminare con una svolta a sinistra o a destra:
// To end with a right turn:
reentry = endRightCenter + startOffset
// To end with a left turn: (crossover)
reentry = endLeftCenter - startOffset
Ora, se abbiamo fatto bene il nostro lavoro, la linea che unisce departure
al reentry
dovrebbe essere perpendicolare startOffset
:
dot(reentry - departure, startOffset) = 0
E risolvere questa equazione ci fornirà gli angoli in cui questo è vero. (Uso un plurale qui perché tecnicamente ci sono due di questi angoli, ma uno di questi prevede la guida al contrario che di solito non è ciò che vogliamo)
Sostituiamo la svolta a destra con la svolta a destra come esempio:
dot(endRightCenter + startOffset - startRightCenter - startOffset, startOffset) = 0
dot(endRightCenter - startRightCenter, startOffset) = 0
pathAngle = atan2(endRightCenter - startRightCenter)
Il caso crossover è più complicato - è quello per cui non ho ancora studiato tutta la matematica. Pubblicherò la risposta senza per ora, nel caso in cui ti sia utile mentre elaboro i dettagli rimanenti.
Modifica: destinazione all'interno del raggio di sterzata minimo
Si scopre che questo metodo spesso funziona immediatamente anche quando la destinazione è più vicina della nostra distanza minima di svolta. Almeno una parte di uno dei cerchi di rientro finisce fuori dal raggio di virata, permettendoci di trovare un percorso percorribile a condizione che non ci dispiaccia che diventi un po 'pretzel ...
Se non ci piace il percorso che prendiamo in quel modo (o se uno non è fattibile - non ho controllato tutti i casi in modo esaustivo - forse ce ne sono di impossibili), possiamo sempre guidare dritto o indietro fino a quando non ne otteniamo uno adatto baciare il contatto tra un cerchio iniziale e finale, come illustrato sopra.