Holonomik olmayan hareket planlamanın harika dünyasına hoş geldiniz . Bunu bir kafes ızgara yolu planlayıcısı kullanarak yapmanızı öneririm . Diğer alternatifler arasında kinodinamik RRT ve yörünge optimizasyonu bulunur . Holonomik olmayan sistemler arasında otomobiller, tekneler, tek bisikletler veya aracın istediği herhangi bir yönde seyahat edemediği her şey bulunur. Bu sistemlerin planlanması holonomik sistemlerden çok daha zordur ve ~ 2000 yılına kadar akademik araştırmaların kenarındaydı. Günümüzde hangisinin terbiyeli çalışacağını seçebileceğiniz birçok algoritma var.
İşte böyle.
Durum
Arabanızın konfigürasyonu q aslında arabanın x, y konumunu ve yönünü t içeren bir 3D durumdur . A * algoritmanızdaki düğümler aslında 3B vektörlerdir.
class Node
{
// The position and orientation of the car.
float x, y, theta;
}
Hareketler
Peki ya kenarlar?
Bu biraz daha zor, çünkü arabanız tekerleği çevirmek için sonsuz sayıda yol seçebilir . Yani, biz araba ayrı bir set, için yapabileceğiniz işlemlerin sayısını kısıtlayarak bir kafes ızgara planlayıcısı için bu erişilebilir hale A . Basitlik uğruna, otomobilin hızlanmadığını, ancak hızını anlık olarak değiştirebileceğini varsayalım. Bizim durumumuzda, A aşağıdaki gibi olabilir:
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;
}
Şimdi, arabanın herhangi bir zamanda yapabileceği ayrı bir dizi eylem oluşturabiliriz. Örneğin, gazı 0,5 saniye boyunca tam basarken sert bir hak şu şekilde görünecektir:
Action turnRight;
turnRight.speed = 1;
turnRight.wheelDirection = 1;
turnRight.dt = 0.5;
Arabayı geri takıp yedeklemek şu şekilde görünecektir:
Action reverse;
reverse.speed = -1;
reverse.wheelDirection = 0;
reverse.dt = 0.5;
Ve eylem listeniz şöyle görünecektir:
List<Action> actions = { turnRight, turnLeft, goStraight, reverse ...}
Ayrıca, bir düğümde yapılan eylemin yeni bir düğüme nasıl yol açtığını tanımlamanın bir yoluna ihtiyacınız vardır. Buna sistemin ileri dinamikleri denir .
// 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);
}
Ayrık Izgara Hücreleri
Şimdi, kafes ızgara oluşturmak için, yapmamız gereken tek şey karma ayrık ızgara hücrelerine arabanın devletleri. Bu onları A * ile takip edilebilecek ayrı düğümlere dönüştürür. Bu çok önemlidir, aksi takdirde A * 'nın iki araba durumunun bunları karşılaştırmak için gerçekten aynı olup olmadığını bilmesinin bir yolu yoktur. Tamsayı ızgara hücre değerlerine hashederek bu önemsiz hale gelir.
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;
}
Şimdi, GridCells'in düğüm olduğu, Eylemler'in düğümler arasındaki kenarlar olduğu ve Başlangıç ve Hedef'in GridCells olarak ifade edildiği bir A * planı yapabiliriz. İki GridCell arasındaki buluşsal yöntem, x ve y cinsinden uzaklık artı tetadaki açısal mesafedir.
Yolu Takip Etmek
Artık aralarındaki GridCells ve Eylemler açısından bir yolumuz olduğuna göre, araba için bir yol takipçisi yazabiliriz. Izgara hücreleri ayrık olduğundan, araç hücreler arasında atlar. Bu yüzden arabanın yol boyunca hareketini düzeltmemiz gerekecek. Oyununuz bir fizik motoru kullanıyorsa, bu, aracı yola mümkün olduğunca yakın tutmaya çalışan bir direksiyon kontrolörü yazarak yapılabilir. Aksi takdirde, çerçeve eğrilerini kullanarak veya yoldaki en yakın birkaç noktanın ortalamasını alarak yolu canlandırabilirsiniz.