[Python] Comprendre le potentiel_field_planning de Python Robotics

introduction

Connaissez-vous PythonRopbotics? Il s'agit d'un OSS qui écrit des algorithmes de robot en Python, qui est également posté sur arXiv. Il y a aussi son blog. Depuis que j'ai commencé mes recherches sur les robots, je l'ai lu attentivement et je l'ai utilisé comme référence.

Méthode potentielle

Comme je l'ai écrit dans l'article ici, il existe une méthode potentielle dans la méthode de planification de chemin pour les robots. Il est utilisé pour éviter les obstacles des robots, etc. C'est une méthode pour définir une fonction potentielle pour les obstacles et les destinations et pour prendre un itinéraire vers la destination le long du gradient de la fonction potentielle.

Dans cet article, je vais m'expliquer moi-même dans le but de comprendre le programme de méthode potentiel dans Python Robotics.

Document de référence de la méthode potentielle https://www.mhi.co.jp/technology/review/pdf/511/511040.pdf

programme

fonction principale et paramètres

J'importe numpy et matplotlib. En tant que paramètre ・ Poids du potentiel de destination ・ Poids du potentiel d'obstacle ・ Largeur de la zone pour calculer la méthode du potentiel Est spécifié.

Dans la fonction principale, le départ, l'objectif, la position de l'obstacle, la grille de méthode potentielle et la taille du robot sont spécifiés. Vous pouvez le voir dans les commentaires.

import numpy as np
import matplotlib.pyplot as plt

# Parameters
KP = 5.0  # attractive potential gain
ETA = 100.0  # repulsive potential gain
AREA_WIDTH = 30.0  # potential area width [m]

show_animation = True

def main():
    print("potential_field_planning start")

    sx = 0.0  # start x position [m]
    sy = 10.0  # start y positon [m]
    gx = 30.0  # goal x position [m]
    gy = 30.0  # goal y position [m]
    grid_size = 0.5  # potential grid size [m]
    robot_radius = 5.0  # robot radius [m]

    ox = [15.0,  5.0, 20.0, 25.0, 10.0]  # obstacle x position list [m]
    oy = [25.0, 15.0, 26.0, 25.0, 10.0]  # obstacle y position list [m]

    if show_animation:
        plt.grid(True)
        plt.axis("equal")

    # path generation
    _, _ = potential_field_planning(
        sx, sy, gx, gy, ox, oy, grid_size, robot_radius)

    if show_animation:
        plt.show()

fonction calc_potential_field (calcul du champ potentiel)

Cette fonction calcule l'ensemble du champ potentiel.

L'argument de cette fonction est ・ Coordonnées de l'objectif (x, y) ・ Coordonnées d'obstacles (x, y) ·la grille ・ Taille du robot Il est devenu.

ox, oy contient une liste de coordonnées d'obstacles. Par conséquent, minx, y et maxx, y sont les suivants.

minx,y =La plus petite des coordonnées d'obstacle-Largeur de la zone/ 2  \\

maxx,y =La plus grande des coordonnées d'obstacle-Largeur de la zone/ 2

En les utilisant, nous générons «xw, yw» utilisé pour chaque plage de calcul de x et y. Ensuite, préparez un tableau (`` pmap '') qui stocke le potentiel des valeurs et de la grille ci-dessus.

Après cela, le potentiel du but (ug) et le potentiel dû aux obstacles (uo) sont calculés, et le total (uf) d'entre eux est calculé pour chaque coordonnée. Il est stocké dans `` pmap ''.

def calc_potential_field(gx, gy, ox, oy, reso, rr):
    minx = min(ox) - AREA_WIDTH / 2.0
    miny = min(oy) - AREA_WIDTH / 2.0
    maxx = max(ox) + AREA_WIDTH / 2.0
    maxy = max(oy) + AREA_WIDTH / 2.0
    xw = int(round((maxx - minx) / reso))
    yw = int(round((maxy - miny) / reso))

    # calc each potential
    pmap = [[0.0 for i in range(yw)] for i in range(xw)]

    for ix in range(xw):
        x = ix * reso + minx

        for iy in range(yw):
            y = iy * reso + miny
            ug = calc_attractive_potential(x, y, gx, gy)
            uo = calc_repulsive_potential(x, y, ox, oy, rr)
            uf = ug + uo
            pmap[ix][iy] = uf

    return pmap, minx, miny

Fonctions calc_attractive_potential et calc_repulsive_potential (calcul du potentiel attractif / répulsif)

fonction calc_attractive_potential (calcul du potentiel attractif)

Cette fonction est une fonction qui calcule le potentiel de force attractive du but. Il utilise simplement l'hypot de numpy pour calculer la distance entre les deux points et les pondérer.

fonction calc_repulsive_potential (calcul du potentiel répulsif)

Cette fonction est une fonction permettant de calculer le potentiel de force répulsive dû aux obstacles. Pour chacun des éléments ox et oy, utilisez l'hypot de numpy pour calculer la distance entre les deux points, et pour le plus petit élément (ici lié par l'indice ( minid '')) La distance entre deux points ( `` dq```) est calculée.

Et si `` dq '' est inférieur ou égal à la taille du robot S'il est inférieur ou égal à 0,1, définissez-le sur 0,1 et remplacez-le par la formule suivante. La valeur de retour de cette équation est le potentiel dû aux obstacles.

0.5 × ETA(Poids potentiel) × (\frac{1}{dq} - \frac{1}{rr})^2

De plus, si `` dq '' est plus grand que la taille du robot, le potentiel dû aux obstacles sera de 0.

def calc_attractive_potential(x, y, gx, gy):
    return 0.5 * KP * np.hypot(x - gx, y - gy)


def calc_repulsive_potential(x, y, ox, oy, rr):
    # search nearest obstacle
    minid = -1
    dmin = float("inf")
    for i, _ in enumerate(ox):
        d = np.hypot(x - ox[i], y - oy[i])
        if dmin >= d:
            dmin = d
            minid = i

    # calc repulsive potential
    dq = np.hypot(x - ox[minid], y - oy[minid])

    if dq <= rr:
        if dq <= 0.1:
            dq = 0.1

        return 0.5 * ETA * (1.0 / dq - 1.0 / rr) ** 2
    else:
        return 0.0

fonction potential_field_planning

C'est la fonction qui calcule la partie planification de chemin de la méthode potentielle.

Recevez pmap, minx, miny de la fonction potential_field_planning ci-dessus.

Dans la partie directement sous le # chemin de recherche du commentaire, la distance entre le début et le but d et les coordonnées calculées ʻix, iy, gix, giy sont calculées. (Je ne comprends pas parfaitement les formules pour ʻix, iy, gix, giy ... je vais le réparer plus tard)

Après cela, il y a une boucle de la partie de while d> = reso pour atteindre l'objectif en définissant une animation. La fonction get_motiobn_model est une fonction qui renvoie un tableau de mouvements, et se déplace vers le haut, le bas, la gauche et la droite sur les coordonnées x et y. La partie suivante.

inx = int(ix + motion[i][0])
iny = int(iy + motion[i][1])

Le potentiel de ces coordonnées «inx, iny» est obtenu à partir de «pmap», et où aller vers le haut, le bas, la gauche et la droite pour trouver le plus petit potentiel est obtenu, et le processus consiste à procéder dans cette direction. La distance entre les coordonnées et le but après le déplacement est calculée et répétée jusqu'à ce que la distance devienne inférieure à la valeur de la grille.

C'est tout pour l'explication des pièces mobiles.

def potential_field_planning(sx, sy, gx, gy, ox, oy, reso, rr):

    # calc potential field
    pmap, minx, miny = calc_potential_field(gx, gy, ox, oy, reso, rr)

    # search path
    d = np.hypot(sx - gx, sy - gy)
    ix = round((sx - minx) / reso)
    iy = round((sy - miny) / reso)
    gix = round((gx - minx) / reso)
    giy = round((gy - miny) / reso)

    if show_animation:
        draw_heatmap(pmap)
        # for stopping simulation with the esc key.
        plt.gcf().canvas.mpl_connect('key_release_event',
                lambda event: [exit(0) if event.key == 'escape' else None])
        plt.plot(ix, iy, "*k")
        plt.plot(gix, giy, "*m")

    rx, ry = [sx], [sy]
    motion = get_motion_model()
    while d >= reso:
        minp = float("inf")
        minix, miniy = -1, -1
        for i, _ in enumerate(motion):
            inx = int(ix + motion[i][0])
            iny = int(iy + motion[i][1])
            if inx >= len(pmap) or iny >= len(pmap[0]):
                p = float("inf")  # outside area
            else:
                p = pmap[inx][iny]
            if minp > p:
                minp = p
                minix = inx
                miniy = iny
        ix = minix
        iy = miniy
        xp = ix * reso + minx
        yp = iy * reso + miny
        d = np.hypot(gx - xp, gy - yp)
        rx.append(xp)
        ry.append(yp)

        if show_animation:
            plt.plot(ix, iy, ".r")
            plt.pause(0.01)

    print("Goal!!")

    return rx, ry

à la fin

Il y a certaines parties que je n'ai pas encore complètement comprises, mais j'ai essayé de les comprendre ainsi. Si vous trouvez quelque chose qui ne va pas, je vous serais reconnaissant de bien vouloir commenter.

référence

Page de robotique Python https://github.com/AtsushiSakai/PythonRobotics

Le texte complet de potential_field_planning peut être trouvé ici. https://github.com/AtsushiSakai/PythonRobotics/blob/master/PathPlanning/PotentialFieldPlanning/potential_field_planning.py

↑ Le blog que la personne fait https://myenigma.hatenablog.com/

Recommended Posts

[Python] Comprendre le potentiel_field_planning de Python Robotics
le zen de Python
[Python] Une compréhension approximative du module de journalisation
Vers la retraite de Python2
À propos des fonctionnalités de Python
Compréhension complète du débogage Python
Le pouvoir des pandas: Python
L'histoire de Python et l'histoire de NaN
[Python] La pierre d'achoppement de l'importation
Existence du point de vue de Python
Revue des bases de Python (FizzBuzz)
À propos de la liste de base des bases de Python
Apprenez les bases de Python ① Débutants élémentaires
Mémorandum de l'outil de gestion de paquets Python ez_setup
Changer la longueur des chaînes csv Python
[Comprendre en 3 minutes] Le début de Linux
Vérifiez le comportement du destroyer en Python
[Python3] Comprendre les bases de Beautiful Soup
Passez le chemin du module python importé
Notes d'apprentissage depuis le début de Python 1
Vérifier l'existence du fichier avec python
À propos de l'environnement virtuel de Python version 3.7
[Python3] Réécrire l'objet code de la fonction
Je ne connaissais pas les bases de Python
Le résultat de l'installation de python sur Anaconda
[Python] Essayez pydash de la version Python de lodash
[python] Vérifier la consommation de mémoire des variables
Vérifiez le chemin du module importé Python
L'histoire de la manipulation des variables globales Python
[python] [meta] Le type de python est-il un type?
Principes de base pour exécuter NoxPlayer en Python
Pandas du débutant, par le débutant, pour le débutant [Python]
Le modèle de projet Python auquel je pense.
À la recherche du FizzBuzz le plus rapide en Python
Cours de base Python (à la fin de 15)
Définissez le nom du processus du programme Python
[Python] Récupère le code de caractère du fichier
L'histoire du traitement A du blackjack (python)
Apprenez intuitivement la refonte de Python np
Note Python: le rôle secret de Kamma
Compréhension complète du threading Python et du multitraitement
Notes d'apprentissage depuis le début de Python 2
Traduction japonaise: PEP 20 - Le Zen de Python
[Python3] Comprendre les bases des opérations sur les fichiers
Comprendre Python Coroutine
Les bases de Python ①
Bases de python ①
Copie de python
Comprendre l'auto python
Introduction de Python
Récupérer le contenu de git diff depuis python
Sortie du nombre de cœurs de processeur en Python
[Python] Lire le code source de Bottle Part 2
Essai du parseur d'emacs-org orgparse pour python
L'histoire selon laquelle le coût d'apprentissage de Python est faible
[Python] Trier la liste de pathlib.Path dans l'ordre naturel