agrobot_base/Python/trajetoria-dinamica/test2.py

235 lines
8.9 KiB
Python
Raw Normal View History

import json
import matplotlib.pyplot as plt
from shapely.geometry import shape, Point, LineString
import numpy as np
import paho.mqtt.client as mqtt
import queue
update_queue = queue.Queue()
# Substitua este caminho pelo local onde o seu arquivo GeoJSON está armazenado
geojson_path = "mapa.json"
# Carregar o arquivo GeoJSON
with open(geojson_path, 'r') as file:
geojson_data = json.load(file)
# Extrair as ruas como objetos LineString
ruas = [shape(feature['geometry']) for feature in geojson_data['features']]
# Posição atual do robô (latitude, longitude)
posicao_atual = Point(-47.372138166667, -22.1789853333)
# Converter distância em metros para graus (aproximado)
def metros_para_graus(distancia_metros):
return distancia_metros / 111320 # Aproximadamente 111.32 km por grau na região equatorial
# Função para deslocar o ponto para o espaço central entre duas ruas
def deslocar_para_centro(rua1, rua2, ponto):
ponto_rua1 = rua1.interpolate(rua1.project(ponto))
ponto_rua2 = rua2.interpolate(rua2.project(ponto))
x_central = (ponto_rua1.x + ponto_rua2.x) / 2
y_central = (ponto_rua1.y + ponto_rua2.y) / 2
return Point(x_central, y_central)
# Função para prolongar uma rua adicionando pontos antes e depois
def prolongar_rua(rua, distancia_graus):
# Coordenadas da rua
coords = list(rua.coords)
# Calcular vetor direção no início da rua
inicio = Point(coords[0])
segundo = Point(coords[1])
vetor_inicio = np.array([inicio.x - segundo.x, inicio.y - segundo.y])
vetor_inicio = vetor_inicio / np.linalg.norm(vetor_inicio)
# Calcular vetor direção no final da rua
fim = Point(coords[-1])
penultimo = Point(coords[-2])
vetor_fim = np.array([fim.x - penultimo.x, fim.y - penultimo.y])
vetor_fim = vetor_fim / np.linalg.norm(vetor_fim)
# Criar novos pontos prolongados
novo_inicio = Point(inicio.x + vetor_inicio[0] * distancia_graus, inicio.y + vetor_inicio[1] * distancia_graus)
novo_fim = Point(fim.x + vetor_fim[0] * distancia_graus, fim.y + vetor_fim[1] * distancia_graus)
# Retornar nova linha com os pontos prolongados
nova_coords = [novo_inicio] + coords + [novo_fim]
return LineString(nova_coords)
# Função principal para calcular a trajetória dinâmica
def calcular_trajetoria_dinamica(ruas, posicao_atual, distancia_prolongamento_metros):
distancia_prolongamento_graus = metros_para_graus(distancia_prolongamento_metros)
trajetoria = []
# Função para encontrar o ponto mais próximo de uma posição em uma linha
def ponto_mais_proximo(rua, posicao):
menor_distancia = float("inf")
ponto_mais_proximo = None
for ponto in rua.coords:
p = Point(ponto)
distancia = posicao.distance(p)
if distancia < menor_distancia:
menor_distancia = distancia
ponto_mais_proximo = p
return ponto_mais_proximo
# Iniciar no espaço central entre a posição atual e a primeira rua
if len(ruas) > 1:
ponto_inicial = deslocar_para_centro(ruas[0], ruas[1], posicao_atual)
trajetoria.append(posicao_atual)
trajetoria.append(ponto_inicial)
# Percorrer todas as ruas
for idx in range(len(ruas) - 1):
rua_atual = ruas[idx]
proxima_rua = ruas[idx + 1]
# Prolongar as ruas antes de calcular a trajetória
rua_atual_prolongada = prolongar_rua(rua_atual, distancia_prolongamento_graus)
proxima_rua_prolongada = prolongar_rua(proxima_rua, distancia_prolongamento_graus)
# Usar o último ponto da trajetória dinâmica como referência
ultimo_ponto_trajetoria = trajetoria[-1]
# Encontrar o ponto mais próximo da posição atual no início da rua
ponto_inicio_atual = ponto_mais_proximo(rua_atual_prolongada, ultimo_ponto_trajetoria)
# Filtrar os pontos a partir do ponto mais próximo
indice_inicio = list(rua_atual_prolongada.coords).index((ponto_inicio_atual.x, ponto_inicio_atual.y))
pontos_filtrados = list(rua_atual_prolongada.coords)[indice_inicio + 1:]
if (idx == 0):
# Adicionar os pontos deslocados para o centro na trajetória
for ponto in pontos_filtrados:
ponto_atual = Point(ponto)
deslocado = deslocar_para_centro(rua_atual_prolongada, proxima_rua_prolongada, ponto_atual)
trajetoria.append(deslocado)
# Cálculo dos extremos da próxima rua
ponto_inicio_proxima = Point(proxima_rua.coords[0]) # Primeiro ponto da próxima rua
ponto_fim_proxima = Point(proxima_rua.coords[-1]) # Último ponto da próxima rua
# Calcular as distâncias do último ponto da trajetória aos extremos da próxima rua
dist_inicio = ultimo_ponto_trajetoria.distance(ponto_inicio_proxima)
dist_final = ultimo_ponto_trajetoria.distance(ponto_fim_proxima)
# Verificar qual ponto extremo da próxima rua está mais próximo
if dist_inicio < dist_final:
pontos_proxima_rua = list(proxima_rua_prolongada.coords)
else:
pontos_proxima_rua = list(proxima_rua_prolongada.coords[::-1])
if idx > 0:
# Adicionar os pontos da próxima rua na trajetória dinâmica
for ponto in pontos_proxima_rua:
ponto_atual = Point(ponto)
deslocado = deslocar_para_centro(rua_atual_prolongada, proxima_rua_prolongada, ponto_atual)
trajetoria.append(deslocado)
return trajetoria
# Função para processar mensagens MQTT
def on_message(client, userdata, msg):
global posicao_atual
try:
# Verifique e exiba o payload recebido
print(f"Payload bruto recebido: {msg.payload}")
# Decodifique o payload
payload = json.loads(msg.payload.decode("utf-8"))
if "longitude" in payload and "latitude" in payload:
posicao_atual = Point(payload["longitude"], payload["latitude"])
print(f"Posição atual atualizada: {posicao_atual}")
trajetoria = calcular_trajetoria_dinamica(ruas, posicao_atual, 1.5) # 1.5 metros
print("Trajetória recalculada.")
# Colocar dados na fila para a thread principal processar
update_queue.put((posicao_atual, trajetoria))
else:
print(f"Chaves 'longitude' e 'latitude' ausentes no payload: {payload}")
except json.JSONDecodeError as e:
print(f"Erro ao decodificar JSON: {e}")
print(f"Payload recebido (não formatado): {msg.payload.decode('utf-8')}")
def atualizar_grafico(trajetoria):
global posicao_atual, ruas
# Limpar o gráfico atual
plt.clf()
# Plotar as ruas originais
for idx, rua in enumerate(ruas):
x, y = zip(*rua.coords)
plt.plot(x, y, label=f"Rua {idx + 1}", linewidth=2)
# Plotar a trajetória dinâmica recalculada
if trajetoria:
x_traj, y_traj = zip(*[(p.x, p.y) for p in trajetoria])
plt.plot(x_traj, y_traj, 'y-', label="Trajetória Dinâmica Prolongada", linewidth=2)
# Plotar a posição atual do robô
plt.plot(posicao_atual.x, posicao_atual.y, 'ro', label="Posição Atual do Robô")
# Configurações de exibição
plt.title("Mapa com Trajetória Dinâmica Prolongada", fontsize=14)
plt.xlabel("Longitude")
plt.ylabel("Latitude")
plt.legend()
plt.grid(True)
plt.tight_layout()
# Atualizar o gráfico
plt.pause(0.1) # Pequena pausa para atualizar a interface
# Configuração do MQTT
client = mqtt.Client()
client.on_message = on_message
client.connect("localhost", 1883, 60)
client.subscribe("coordenadas_gps")
# Loop do MQTT
client.loop_start()
# Criar a plotagem inicial
fig, ax = plt.subplots(figsize=(10, 8))
atualizar_grafico([])
# Mantenha o script ativo
while True:
try:
# Processar dados da fila, se houver
if not update_queue.empty():
posicao_atual, nova_trajetoria = update_queue.get()
# Atualizar o gráfico
plt.clf()
# Plotar as ruas originais
for idx, rua in enumerate(ruas):
x, y = zip(*rua.coords)
plt.plot(x, y, label=f"Rua {idx + 1}", linewidth=2)
# Plotar a nova trajetória dinâmica
if nova_trajetoria:
x_traj, y_traj = zip(*[(p.x, p.y) for p in nova_trajetoria])
plt.plot(x_traj, y_traj, 'y-', label="Trajetória Dinâmica Prolongada", linewidth=2)
# Plotar a posição atual do robô
plt.plot(posicao_atual.x, posicao_atual.y, 'ro', label="Posição Atual do Robô")
# Configurações de exibição
plt.title("Mapa com Trajetória Dinâmica Prolongada", fontsize=14)
plt.xlabel("Longitude")
plt.ylabel("Latitude")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.pause(0.1) # Pequena pausa para atualizar o gráfico
except KeyboardInterrupt:
print("Encerrando...")
break