Planejamento de Tragetória » Histórico » Versão 7
Rebeca Reis, 25/02/2019 02:00 h
1 | 5 | Luciano Barreira | # Planejamento de Trajetória |
---|---|---|---|
2 | 1 | Nicolas Oliveira | |
3 | 5 | Luciano Barreira | Nos utilizamos do algoritmo RRT (Rapidly-Exploring Random Tree) para calcular nossa trajetória. Ele busca uma trajetória a partir de um estado inicial até o objetivo expandindo uma árvore de busca. |
4 | 2 | Nicolas Oliveira | Para isso necessitamos de 3 funções básicas: |
5 | 1 | Nicolas Oliveira | |
6 | * Extend(env:enviroment,current:state,target:state,Step:real):state |
||
7 | |||
8 | Essa função dado um estado atual extende dando um passo em direção ao objetivo, ou em uma direção aleatória. Caso uma colisão ocorra ela retorna um estado vazio (EmptyState). |
||
9 | Pseudo código: |
||
10 | |||
11 | 3 | Nicolas Oliveira | ```c |
12 | r = (Target - Current)/||Targe-Current|| ; //vetor unitário na direção do target |
||
13 | NewState = r*Step + Current ; |
||
14 | if (Colision(NewState)) NewState = EmptyState; //confere se o novo estado vai colidir com algum obstáculo. |
||
15 | return NewState; |
||
16 | ``` |
||
17 | 1 | Nicolas Oliveira | |
18 | * Distance(current:state,target:state):real |
||
19 | |||
20 | Calcula a distância do estado atual ao objetivo, utilizamos a euclidiana nessa implementação. |
||
21 | |||
22 | * RandomState():state |
||
23 | |||
24 | Retorna um novo estado uniformemente distribuído no ambiente. |
||
25 | |||
26 | 3 | Nicolas Oliveira | ```c |
27 | float random_x; |
||
28 | float random_y; |
||
29 | random_x = fiel_length*(rand()-0.5); //Random gera um número aleatório uniformemente aleatório distribuído entre 0 e 1 |
||
30 | random_y = fiel_length*(rand()-0.5); |
||
31 | ``` |
||
32 | 1 | Nicolas Oliveira | |
33 | Basicamente a função estender pode utilizar como target o objetivo ou um ponto aleátório, o que garante que o algoritmo pode encontrar um caminho sem colidir com nenhum obstáculo. Como na figura abaixo: |
||
34 | |||
35 | ![](rrt.PNG) |
||
36 | |||
37 | A implementação seguiu o pseudo código abaixo: |
||
38 | |||
39 | ![](pseudocódigo.PNG) |
||
40 | |||
41 | ***A função Nearest garante que sempre extendemos a árvore do nó mais próximo do objetivo, porém ela também demanda muito processamento, já que tem q varrer a árvore toda a cada iteração. Vamos estudar um jeito para resolver isso.*** |
||
42 | 5 | Luciano Barreira | Definimos uma árvore de pontos como uma matriz de 4 colunas, onde a primeira é o id do ponto, a segunda a coordenada x, a terceira a coordenada y e a quarta o id do pai. Dessa forma os nós são adicionados com o id sendo incrementado de 1 a cada nó. O id do pai é o id do nó da onde aquale novo ramo foi gerado. Assim quando encontramos um solução podemos fazer o backtracking nessa árvore para reconstruir a trajetória. |
43 | 1 | Nicolas Oliveira | |
44 | 5 | Luciano Barreira | O próximo passo foi implentar a extenção do RRT (ERRT), com memória da última trajetória. Assim na hora de escolhermos um target podemos ir em direção ao objetivo, em uma direção aleatória ou em direção a algum ponto da última trajetória, como na imagem e código abaixo. |
45 | 1 | Nicolas Oliveira | |
46 | ![](errt.PNG) |
||
47 | ![](choose.PNG) |
||
48 | |||
49 | 5 | Luciano Barreira | Por último implementamos a suavização da trajetória que segue o algoritmo abaixo descrito. Ela auxilia muito na rapidez com que o robô será capaz de seguir a trajetóra. |
50 | 1 | Nicolas Oliveira | |
51 | ![](suavização.png) |
||
52 | |||
53 | 6 | Nicolas Oliveira | ## Raio dos Obstáculos |
54 | |||
55 | ### Robôs Inimigos |
||
56 | |||
57 | Para os robôs inimigos agora é considerada a influência da velocidade relativa. Assim o raio do obstáculo é dado por: |
||
58 | |||
59 | ```c |
||
60 | radius_enemy + radius_our + bound(0, |speed_enemy-speed_our|*100, 100) |
||
61 | ``` |
||
62 | E caso o goal esteja dentro de um obstáculo esse raio é reduzido o suficiente para que um trajetória válida possa ser gerada. O mesmo acontece quando o ponto inicial da trajetória está dentro de um obstáculo, o raio é reduzido afim de ser possível a geração da trajetória. |
||
63 | |||
64 | 1 | Nicolas Oliveira | ## Implementações futuras e problemas atuais |
65 | 6 | Nicolas Oliveira | |
66 | * Tornar os nossos robôs obstáculos, porém com um raio menor. |
||
67 | * Tornar as áreas dos goleiros e a parte de trás do gol em obstáculos |
||
68 | * Colocar a bola como obstáculo na situação de stop |
||
69 | * Tornar o RRT otimizado para diferentes personalidades |
||
70 | 7 | Rebeca Reis | |
71 | # Otimização feita (RRT apenas nos obstáculos) |
||
72 | |||
73 | Conversando com outras equipes na RoboCup 2018, nos deram uma dica de como poderíamos otimizar nosso planejamento de trajetória. A ideia consiste em traçar uma linha reta entre o ponto atual e o final (objetivo) do robô, identificar possíveis obstáculos que cruzam essa reta e aplicar o RRT apenas na região em que ocorrem esses conflitos, mantendo a linha reta onde não houver problema. Isso é essencial para diminuir o custo de processamento e reduzir os cálculos para gerar nosso path, já que o algoritmo é aplicado numa região muito menor. |
||
74 | |||
75 | Pesquisamos o TDP de outras equipes para procurar alguma referência dessa implementação, mas não foi encontrada essa ideia de fazer o RRT apenas nos obstáculos escrita em nenhum deles. Todos os TDPs se baseavam naquele mesmo artigo (autores James Bruce e Manuela Veloso) por onde estudamos o RRT, e não foi encontrado nada diferente daquilo. |
||
76 | |||
77 | A respeito da implementação: |
||
78 | |||
79 | * Criei a VI FindColisionPoints, para encontrar a posição dos obstáculos que cruzam a trajetória reta mais simples entre os pontos inicial e final (Simple Path). Ela retorna um vetor com todas as posições de obstáculos nesse caminho. |
||
80 | |||
81 | * Criei a VI FindStartEndPointsRRT, que serve para encontrar a posição do obstáculo mais distante e do mais próximo do ponto inicial, dentre os que estao no vetor dos pontos de colisão. Em seguida aplica-se um range (por enquanto escolhi o tamanho 200mm pra cada lado) em volta dessas duas extremidades de obstaculos. Essa área interna ao range aplicado é a que será percorrida usando o RRT, e as de fora por uma linha reta. Verifica-se após aplicar o range se o novo ponto cai fora do simple path, o que significa que está muito perto do ponto inicial (ou final) da trajetória, e nesse caso trocamos o ponto gerado que deu problema pelo ponto inicial ou final correspondente. Ou seja, se os pontos encontrados para iniciar ou acabar o RRT forem muito próximos da extremidade (usei um valor de comparação <200mm por enquanto), ou se caírem fora daquele segmento, entao ignora-se a linha reta nesse pequeno caminho e aplica-se o RRT diretamente desde o ponto inicial ou até o ponto destino diretamente. |
||
82 | |||
83 | * Adaptei a VI RRTPlan para essas modificações. Primeiro, modularizei um grande pedaço onde se fazia o algoritmo do RRT de fato, criando uma subVI chamada RRTAlgorithm, para facilitar a visualização da escolha dos pontos inicial e final de onde aplicaríamos o RRT. Em seguida usei as duas VIs anteriores para gerar os pontos de obstáculos e encontrar os pontos iniciais e finais convenientes no algoritmo, gerando o novo path. |
||
84 | |||
85 | Durante a implementação, foi perguntado como ficaria o algoritmo quando existem vários obstáculos em sequência ou um outro obstáculo no end point. |
||
86 | |||
87 | Resposta: primeiramente eu fiz da forma mais simples, fazendo o RRT em toda a extensão dos obstáculos, desde o primeiro (mais próximo do ponto inicial) até o último (mais perto do ponto final). Optei por essa implementação mais simples a princípio pra verificar se daria certo e observar a trajetória gerada. Depois de debugar e testar dessa maneira, finalmente consegui obter a trajetória desejada pensada dessa forma, e agora posso partir pra implementação mais otimizada ainda: de fazer o rrt em cada obstáculo separadamente (basta fazer um loop no vetor dos obstáculos que eu gerei e tratar os casos de os obstáculos estarem muito próximos e serem aglutinados em apenas 1). |
||
88 | |||
89 | Seguem agora imagens de como ficou a trajetória gerada nessa implementação mais simples. Vejam que com dois ou mais robôs a trajetória ainda não é a ótima, pois ele calcula o rrt em todo o espaço entre os obstáculos também, e isso é ruim no caso deles estarem muito longes um do outro. |
||
90 | |||
91 | ![](rrt1.png) |
||
92 | |||
93 | ![](rrt2.png) |
||
94 | |||
95 | Em seguida, foi finalizada a implementação mais otimizada, com o RRT aplicado apenas nos obstáculos e em cada um por vez. Obtive as seguintes trajetórias: |
||
96 | |||
97 | ![](novorrt1.png) |
||
98 | |||
99 | ![](novorrt3.png) |
||
100 | |||
101 | Veja que, quando dois obstáculos estão muito próximos um do outro, de forma que não é possível executar a trajetória reta entre eles, estes são algutinados em 1 só, e é aplicado o RRT sobre aquela extensão: |
||
102 | |||
103 | ![](novorrt2.png) |
||
104 | |||
105 | Iniciou-se a partir daí os testes para medir o tempo que demora para a execução de todo o cálculo e comparar com a implementação anterior para saber se está mais rápido ou não. Foi decidido como seriam os testes: a ideia é que faremos diversos zig zags com um robô e vou medir o tempo máximo de execução da VI RRTPlan pra cada teste desse. Em seguida vou replicar os mesmos zig zags para a outra implementação do RRT e vamos comparar os tempos. As variações entre os zig zags vão ser apenas nas posições e no número dos obstáculos que vão atrapalhar o robô nessa tarefa. Vou deixar cada zig zag rodando por um tempo determinado (Ex: 1 min) e anotar o tempo máximo de execução obtido nesse período. |
||
106 | |||
107 | Fiz os testes do RRT novo e antigo, para comparar os tempos de execução da VI RRT Plan, que contém todo o cálculo da trajetória e também a parte de suavização. Fiz os testes nas mesmas condições (apenas um robô ligado e posicionamento preciso no grsim com o set position), e obtive os seguintes resultados de tempo e fps durante o tempo de observação (1 min para cada zig zag feito): |
||
108 | |||
109 | 1º) Zig Zag entre os pontos (0,2000) e (0,-2000) SEM obstáculos. |
||
110 | |||
111 | | RRT antigo | RRT novo | |
||
112 | |--- | --- | |
||
113 | |t=0,0225756s|t=0,000511674s| |
||
114 | |fps=45 |fps=57 | |
||
115 | |||
116 | 2º) Zig Zag entre os pontos (-4000,0) e (4000,0) SEM obstáculos. |
||
117 | |||
118 | | RRT antigo | RRT novo | |
||
119 | |--- | --- | |
||
120 | |t=0,0558839s|t=0,000469714s| |
||
121 | |fps=43 |fps=57 | |
||
122 | |||
123 | 3º) Zig Zag entre os pontos (0,2000) e (0,-2000) |
||
124 | Obstáculo (robô) no ponto (0,0) |
||
125 | |||
126 | | RRT antigo | RRT novo | |
||
127 | |--- | --- | |
||
128 | |t=0,070037s |t=0,0809514s | |
||
129 | |fps=50 |fps=57 | |
||
130 | |||
131 | |||
132 | 4º) Zig Zag entre os pontos (-3000,0) e (3000,-0) |
||
133 | Obstáculos (robôs) nos pontos (-1000,0) e (1000,0) |
||
134 | |||
135 | | RRT antigo | RRT novo | |
||
136 | |--- | --- | |
||
137 | |t=0,0533753s|t=0,0781024s | |
||
138 | |fps=50 |fps=57 | |
||
139 | |||
140 | |||
141 | 5º) Zig Zag entre os pontos (-3000,0) e (3000,-0) |
||
142 | Obstáculos (robôs) nos pontos (-2000,0) e (2000,0) |
||
143 | |||
144 | | RRT antigo | RRT novo | |
||
145 | |--- | --- | |
||
146 | |t=0,0809107s|t=0,0846672s | |
||
147 | |fps=50 |fps=57 | |
||
148 | |||
149 | |||
150 | Conclusões dos testes: |
||
151 | |||
152 | * Quando não há obstáculos, o RRT novo é na ordem de 100 vezes mais rápido. |
||
153 | * Quando há obstáculos, os dois tempos são de mesma ordem de grandeza, sendo que o RRT antigo é ligeiramente mais rápido: no teste de maior diferença (teste 4), a diferença de tempos foi de 0,0247271s. |
||
154 | * Em todos os testes, o código se manteve com fps mais alto no RRT novo. Nos testes em que não havia obstáculos e a trajetória simples podia ser usada, o fps do RRT antigo se mostrou ainda mais baixo que nos outros casos. |