ajustes no controle direcional pid
This commit is contained in:
parent
a2af1edd77
commit
68c4042bf5
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -461,6 +461,7 @@
|
|||
<Compile Include="Models\Modules\SensoriamentoModel.cs" />
|
||||
<Compile Include="Models\MotorComum.cs" />
|
||||
<Compile Include="Models\MPCController.cs" />
|
||||
<Compile Include="Models\MPCControllerAprimorado.cs" />
|
||||
<Compile Include="Models\MPCControllerSimple.cs" />
|
||||
<Compile Include="Models\OAKCameraModel.cs" />
|
||||
<Compile Include="Models\OIDModel.cs" />
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ namespace AgroBase.Forms.IHM
|
|||
);
|
||||
if (res == DialogResult.Yes)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
await Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
if (Variaveis.OperacaoEmAndamento.Modo == Enums.ModoOperacao.Manual)
|
||||
{
|
||||
this.Close();
|
||||
|
|
|
|||
|
|
@ -84,12 +84,12 @@ namespace AgroBase.Forms.Operacoes
|
|||
private void frmOperacaoManual_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
tmrLeitura.Dispose();
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
|
||||
Variaveis.OperacaoEmAndamento.DesligarCameras();
|
||||
KinectService.picRGB = null;
|
||||
}
|
||||
|
||||
private async void btnIniciarOperacao_Click(object sender, EventArgs e)
|
||||
private void btnIniciarOperacao_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (btnIniciarOperacao.Text == "Finalizar Operação")
|
||||
{
|
||||
|
|
@ -101,7 +101,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
});
|
||||
|
||||
// Executa a finalização da operação
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
|
||||
|
||||
// Atualiza a UI novamente na thread principal
|
||||
btnIniciarOperacao.Invoke((MethodInvoker)delegate
|
||||
|
|
@ -123,7 +123,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
if (Variaveis.OperacaoEmAndamento.OperacaoLiberada)
|
||||
{
|
||||
// Inicia a operação de forma assíncrona
|
||||
await Variaveis.OperacaoEmAndamento.IniciarOperacao();
|
||||
Task.Run(async () => await Variaveis.OperacaoEmAndamento.IniciarOperacao());
|
||||
|
||||
// Atualiza a UI após o início da operação
|
||||
btnIniciarOperacao.Invoke((MethodInvoker)delegate
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
private void frmOperacaoMapaGPS_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
tmrLeituras.Dispose();
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
|
||||
Variaveis.OperacaoEmAndamento.DesligarCameras();
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
if (btnIniciarOperacao.Text == "Finalizar Operação")
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
await Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1565,7 +1565,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
private void pnlOrientacaoDif_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
var Logs = LogsOperacao.Where(x => x.Momento == MomentoAtual).ToList();
|
||||
double Angulo = Logs.Any() ? Logs.Average(x => x.AnguloDif) : 0;
|
||||
double Angulo = Logs.Any() ? Logs.Average(x => x.Trajetoria.ErroOrientacaoAngularProximoPonto) : 0;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, 90);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ namespace AgroBase
|
|||
{
|
||||
if (Variaveis.OperacaoEmAndamento.Iniciado)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
|
||||
|
||||
btnIniciarOperacao.Text = "Abrir Operação";
|
||||
cmbModoOperacao.Enabled = true;
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ namespace AgroBase.Forms
|
|||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.SimulacaoAnguloControle;
|
||||
double dif = Variaveis.OperacaoEmAndamento.OpMapaGPS.Sensoriamento.AnguloDif;
|
||||
double dif = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria.ErroOrientacaoAngularProximoPonto;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)dif);
|
||||
}
|
||||
catch { }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using static AgroBase.Models.Enums;
|
||||
|
||||
namespace AgroBase.Models
|
||||
|
|
@ -404,6 +405,45 @@ namespace AgroBase.Models
|
|||
return decimalDegrees;
|
||||
}
|
||||
|
||||
public static double MisturarAngulosPorDistancia(double anguloFrente, double anguloMovimento, double distanciaMetros, double distanciaMaxima, double distanciaMinima = 0.05, double pesoMinFrente = 0.2)
|
||||
{
|
||||
// Se robô praticamente não se moveu, confia só na orientação
|
||||
if (distanciaMetros < distanciaMinima)
|
||||
return anguloFrente;
|
||||
|
||||
double fator = Math.Min(distanciaMetros / distanciaMaxima, 1.0);
|
||||
|
||||
double pesoFrente = (1.0 - fator) * (1.0 - pesoMinFrente) + pesoMinFrente;
|
||||
|
||||
return MisturarAngulos(anguloFrente, anguloMovimento, pesoFrente);
|
||||
}
|
||||
|
||||
public static double MisturarAngulos(double angulo1, double angulo2, double pesoAngulo1 = 0.5)
|
||||
{
|
||||
// Converte os ângulos para vetores unitários no plano
|
||||
double rad1 = angulo1 * Math.PI / 180.0;
|
||||
double rad2 = angulo2 * Math.PI / 180.0;
|
||||
|
||||
double x = Math.Cos(rad1) * pesoAngulo1 + Math.Cos(rad2) * (1.0 - pesoAngulo1);
|
||||
double y = Math.Sin(rad1) * pesoAngulo1 + Math.Sin(rad2) * (1.0 - pesoAngulo1);
|
||||
|
||||
double resultado = Math.Atan2(y, x) * 180.0 / Math.PI;
|
||||
|
||||
return GPSUtils.NormalizarAngulo(resultado);
|
||||
}
|
||||
|
||||
public static (GPSModel ponto, int index) PontoMaisProximoTrechoComIndice(GPSModel pontoRef, List<GPSModel> trecho)
|
||||
{
|
||||
if (trecho == null || trecho.Count == 0)
|
||||
return (null, -1);
|
||||
|
||||
var resultado = trecho
|
||||
.Select((p, i) => (ponto: p, index: i, dist: DistanciaEntrePontos(pontoRef, p)))
|
||||
.OrderBy(x => x.dist)
|
||||
.First();
|
||||
|
||||
return (resultado.ponto, resultado.index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,5 +37,16 @@
|
|||
_valorEstimado = novoValorEstimado;
|
||||
_erroEstimado = 1;
|
||||
}
|
||||
|
||||
public KalmanFilter Clone()
|
||||
{
|
||||
return new KalmanFilter()
|
||||
{
|
||||
_erroEstimado = _erroEstimado,
|
||||
_erroMedicao = _erroMedicao,
|
||||
_erroProcesso = _erroProcesso,
|
||||
_valorEstimado = _valorEstimado
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
using AgroBase.Models;
|
||||
using AgroBase.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class MPCControllerAprimorado
|
||||
{
|
||||
private double distanciaPrevisao = 2.0;
|
||||
private int horizonte;
|
||||
private double maxAnguloDirecao;
|
||||
private double maxAngulo4Rodas;
|
||||
private double velocidadeMin;
|
||||
private double velocidadeMax;
|
||||
|
||||
private double pesoOrientacao = 2.5;
|
||||
private double pesoLateral = 1.5;
|
||||
private double pesoDistancia = 0.8;
|
||||
private double pesoSuavidade = 0.5;
|
||||
private double limiteErroOrientacao = 45.0;
|
||||
private double limiteErroLateral = 2.5; // metros
|
||||
|
||||
private DateTime ultimaAtualizacao = DateTime.MinValue;
|
||||
|
||||
public MPCControllerAprimorado()
|
||||
{
|
||||
this.maxAnguloDirecao = Variaveis.OperacaoEmAndamento?.Controle?.Angulo_Max ?? 30.0;
|
||||
this.maxAngulo4Rodas = this.maxAnguloDirecao * 0.8;
|
||||
this.velocidadeMin = Variaveis.OperacaoEmAndamento?.Controle?.PercentualVelocidadeMin ?? 20.0;
|
||||
this.velocidadeMax = Variaveis.OperacaoEmAndamento?.Controle?.PercentualVelocidadeMax ?? 100.0;
|
||||
}
|
||||
|
||||
public (double anguloControle, Enums.TipoMovimentoDirecional modo) CalcularControle(GPSModel posicalAtual, double velocidadeAtual, List<GPSModel> proximaTrajetoria, Enums.TipoMovimentoDirecional[] modosPermitidos)
|
||||
{
|
||||
if (proximaTrajetoria == null || proximaTrajetoria.Count < 2)
|
||||
return (0, Enums.TipoMovimentoDirecional.RodasDianteiras);
|
||||
|
||||
if (proximaTrajetoria.Count > 3)
|
||||
{
|
||||
proximaTrajetoria = new List<GPSModel>(proximaTrajetoria.Take(3));
|
||||
}
|
||||
|
||||
if (ultimaAtualizacao == DateTime.MinValue)
|
||||
{
|
||||
ultimaAtualizacao = DateTime.Now.AddMilliseconds(-(1.0 / GPSService.TaxaAmostragemHz));
|
||||
}
|
||||
|
||||
double dt = (DateTime.Now - ultimaAtualizacao).TotalSeconds;
|
||||
double tempoMax = (1.0 / GPSService.TaxaAmostragemHz) * 1.5;
|
||||
dt = Math.Max(0.5, Math.Min(dt, tempoMax));
|
||||
|
||||
double velMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(velocidadeAtual);
|
||||
double passoDist = velMs * dt;
|
||||
|
||||
horizonte = Math.Min(Convert.ToInt32(distanciaPrevisao / passoDist), proximaTrajetoria.Count);
|
||||
|
||||
var candidatos = GerarCandidatos(modosPermitidos);
|
||||
double melhorCusto = double.MaxValue;
|
||||
(double angulo, Enums.TipoMovimentoDirecional modo) melhorControle = (0, Enums.TipoMovimentoDirecional.RodasDianteiras);
|
||||
|
||||
foreach (var candidato in candidatos)
|
||||
{
|
||||
double custo = SimularTrajetoriaComReavaliacao(posicalAtual, proximaTrajetoria, posicalAtual.AnguloCarroDefinido, candidato.angulo, candidato.modo, velMs, dt);
|
||||
//Console.WriteLine($"Candidato: {candidato.angulo}, Custo: {custo.ToString()}");
|
||||
if (custo < melhorCusto)
|
||||
{
|
||||
melhorCusto = custo;
|
||||
melhorControle = candidato;
|
||||
}
|
||||
}
|
||||
|
||||
ultimaAtualizacao = DateTime.Now;
|
||||
return melhorControle;
|
||||
}
|
||||
|
||||
private List<(double angulo, Enums.TipoMovimentoDirecional modo)> GerarCandidatos(Enums.TipoMovimentoDirecional[] modos)
|
||||
{
|
||||
var candidatos = new List<(double, Enums.TipoMovimentoDirecional)>();
|
||||
|
||||
foreach (var modo in modos)
|
||||
{
|
||||
double maxAng = (modo == Enums.TipoMovimentoDirecional.MovimentoArco || modo == Enums.TipoMovimentoDirecional.MovimentoDiagonal)
|
||||
? maxAngulo4Rodas : maxAnguloDirecao;
|
||||
|
||||
for (double ang = -maxAng; ang <= maxAng; ang += 5.0)
|
||||
{
|
||||
candidatos.Add((ang, modo));
|
||||
}
|
||||
}
|
||||
|
||||
return candidatos;
|
||||
}
|
||||
|
||||
private double SimularTrajetoriaComReavaliacao(GPSModel posicaoInicial, List<GPSModel> trajeto, double anguloInicial, double anguloControleInicial, Enums.TipoMovimentoDirecional modoInicial, double velocidadeMs, double dt)
|
||||
{
|
||||
double custoTotal = 0;
|
||||
GPSModel posAtual = posicaoInicial;
|
||||
double anguloAtual = anguloInicial;
|
||||
double anguloControle = anguloControleInicial;
|
||||
Enums.TipoMovimentoDirecional modo = modoInicial;
|
||||
|
||||
posAtual = VariaveisEquipamento.SimularNovaPosicao(modoInicial, anguloControleInicial, velocidadeMs, dt, anguloAtual, posAtual);
|
||||
anguloAtual = posAtual.OrientacaoReal;
|
||||
|
||||
for (int i = 0; i < horizonte; i++)
|
||||
{
|
||||
double melhorCustoIteracao = double.MaxValue;
|
||||
|
||||
foreach (var candidato in GerarCandidatos(new[] { modo }))
|
||||
{
|
||||
var novaPos = VariaveisEquipamento.SimularNovaPosicao(candidato.modo, candidato.angulo, velocidadeMs, dt, anguloAtual, posAtual);
|
||||
var pontoAlvo = trajeto[Math.Min(i + 1, trajeto.Count - 1)];
|
||||
|
||||
double orientacaoAlvo = GPSUtils.CalcularOrientacao(posAtual, pontoAlvo);
|
||||
|
||||
double d0 = GPSUtils.DistanciaEntrePontos(posAtual, novaPos);
|
||||
double a0 = GPSUtils.CalcularOrientacao(posAtual, novaPos);
|
||||
|
||||
double d1 = GPSUtils.DistanciaEntrePontos(posAtual, pontoAlvo);
|
||||
double a1 = GPSUtils.CalcularOrientacao(posAtual, pontoAlvo);
|
||||
|
||||
double d2 = GPSUtils.DistanciaEntrePontos(novaPos, pontoAlvo);
|
||||
double a2 = GPSUtils.CalcularOrientacao(novaPos, pontoAlvo);
|
||||
|
||||
double erroDist = d2 - d1;
|
||||
double erroOri = Math.Abs(GPSUtils.CalcularDiferencaAngulo(novaPos.OrientacaoReal, orientacaoAlvo));
|
||||
|
||||
(GPSModel ponto, int idx) = GPSUtils.PontoMaisProximoTrechoComIndice(posAtual, trajeto);
|
||||
int idxNovoPonto = Variaveis.OperacaoEmAndamento.Trajetoria.PontoAtual.idxPonto + idx;
|
||||
PontoTrajetoriaModel pontoAtual = Variaveis.OperacaoEmAndamento.Trajetoria._TrajetoriaFixa[idxNovoPonto].Clone();
|
||||
|
||||
int idxRuaEsquerda = Variaveis.OperacaoEmAndamento.Trajetoria._Corredores[pontoAtual.idxCorredor].idxRuaEsquerda;
|
||||
double distEsq = Variaveis.OperacaoEmAndamento.Trajetoria.CalcularDistanciaLateral(true, posAtual, idxRuaEsquerda, pontoAtual.Direcao);
|
||||
|
||||
int idxRuaDireita = Variaveis.OperacaoEmAndamento.Trajetoria._Corredores[pontoAtual.idxCorredor].idxRuaDireita;
|
||||
double distDir = Variaveis.OperacaoEmAndamento.Trajetoria.CalcularDistanciaLateral(false, posAtual, idxRuaDireita, pontoAtual.Direcao);
|
||||
|
||||
double erroLat = Math.Abs(distEsq - distDir);
|
||||
|
||||
double deltaAngulo = Math.Abs(GPSUtils.CalcularDiferencaAngulo(novaPos.OrientacaoReal, anguloAtual));
|
||||
|
||||
//Console.WriteLine($"Angulo Inicial: {anguloControleInicial}, Passo: {i}, Candidato: {candidato.angulo}, Erro lateral: {erroLat}, Erro orientacao: {erroOri}");
|
||||
|
||||
if (false && (erroOri > limiteErroOrientacao || erroLat > limiteErroLateral))
|
||||
{
|
||||
continue; // Ignora este candidato
|
||||
}
|
||||
|
||||
double custo = (erroOri * pesoOrientacao) + (erroLat * pesoLateral) + (erroDist * pesoDistancia) + (deltaAngulo * pesoSuavidade);
|
||||
|
||||
if (custo < melhorCustoIteracao)
|
||||
{
|
||||
melhorCustoIteracao = custo;
|
||||
posAtual = novaPos;
|
||||
anguloAtual = novaPos.OrientacaoReal;
|
||||
anguloControle = candidato.angulo;
|
||||
modo = candidato.modo;
|
||||
|
||||
//Console.WriteLine($"Angulo Inicial: {anguloControleInicial}, Passo: {i}, Candidato: {candidato.angulo}, Custo: {custo}, Erro lateral: {erroLat}, Erro orientacao: {erroOri}, Erro distancia: {erroDist}");
|
||||
}
|
||||
}
|
||||
|
||||
custoTotal += melhorCustoIteracao;
|
||||
|
||||
if (melhorCustoIteracao == double.MaxValue)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return custoTotal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -414,7 +414,7 @@ namespace AgroBase.Models.Modules
|
|||
|
||||
RPM_SP = Convert.ToInt32(RPM_SP * FatorCompensacaoCurvas);
|
||||
|
||||
Variaveis.OperacaoEmAndamento.SimulacaoRpmControle = (RPM_SP / VariaveisEquipamento.RelacaoRPM);
|
||||
Variaveis.OperacaoEmAndamento.SimulacaoRpmControle = Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.Average(x => x.MovMotor.RPM_SP) / VariaveisEquipamento.RelacaoRPM;
|
||||
|
||||
switch (DirecaoAtual)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,16 +37,13 @@ namespace AgroBase.Models.Operacoes
|
|||
}
|
||||
case TiposControladorDirecional.MPC:
|
||||
{
|
||||
var MPC = Controle.ControladorMPC;
|
||||
var Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
|
||||
|
||||
(double steeringAngle, Enums.TipoMovimentoDirecional mode) = MPC.ComputeControl(
|
||||
GPSService.UltimaLeitura.Latitude, GPSService.UltimaLeitura.Longitude, Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido,
|
||||
Trajetoria.ProximoPonto.Posicao.Latitude, Trajetoria.ProximoPonto.Posicao.Longitude, Trajetoria.ProximoPonto.Orientacao,
|
||||
Controle.PercentualVelocidadeSP, Trajetoria.DistanciaEsquerda, Trajetoria.DistanciaDireita, new List<Obstaculo>());
|
||||
var MPC_A = new MPCControllerAprimorado();
|
||||
(double angulo, TipoMovimentoDirecional tipoControle) = MPC_A.CalcularControle(GPSService.UltimaLeitura, Controle.PercentualVelocidadeSP, Trajetoria.TrajetoriaDinamica, new TipoMovimentoDirecional[] { TipoMovimentoDirecional.RodasDianteiras });
|
||||
|
||||
Controle.Angulo = steeringAngle;
|
||||
Controle.TipoMovimento = mode;
|
||||
Controle.Angulo = angulo;
|
||||
Controle.TipoMovimento = tipoControle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -61,15 +58,17 @@ namespace AgroBase.Models.Operacoes
|
|||
|
||||
private void DefinirTipoMovimento()
|
||||
{
|
||||
var Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
|
||||
var Trajetoria = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria;
|
||||
var Controle = Variaveis.OperacaoEmAndamento.Controle;
|
||||
|
||||
bool arcoNecessario =
|
||||
Trajetoria.ManobrandoEntreRuas ||
|
||||
Trajetoria.StatusAtual == StatusCarroMapa.SaindoRua ||
|
||||
Trajetoria.StatusAtual == StatusCarroMapa.EntrandoRua ||
|
||||
Math.Abs(Variaveis.OperacaoEmAndamento.OpMapaGPS.Sensoriamento.AnguloDif) >= Variaveis.OperacaoEmAndamento.Controle.Angulo_Max;
|
||||
Trajetoria.StatusCarro == StatusCarroMapa.SaindoRua ||
|
||||
Trajetoria.StatusCarro == StatusCarroMapa.EntrandoRua ||
|
||||
(Trajetoria.CorredorAtual.Dentro && Math.Abs(Trajetoria.ErroOrientacaoAngularCaminho) >= Controle.Angulo_Max) ||
|
||||
(!Trajetoria.CorredorAtual.Dentro && Math.Abs(Trajetoria.ErroOrientacaoAngularProximoPonto) >= Controle.Angulo_Max);
|
||||
|
||||
Variaveis.OperacaoEmAndamento.Controle.TipoMovimento =
|
||||
Controle.TipoMovimento =
|
||||
arcoNecessario ? TipoMovimentoDirecional.MovimentoArco :
|
||||
TipoMovimentoDirecional.RodasDianteiras;
|
||||
}
|
||||
|
|
@ -79,35 +78,21 @@ namespace AgroBase.Models.Operacoes
|
|||
var _Trajetoria = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria;
|
||||
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
||||
|
||||
double erroOrientacao = 0.0;
|
||||
double anguloCamera = Variaveis.OperacaoEmAndamento.Sensoriamento.AnguloRuaCamera;
|
||||
double anguloCarro = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
double anguloRua = _Trajetoria.ProximoPonto.OrientacaoAtual;
|
||||
bool consideraAnguloCorredor =
|
||||
(_Trajetoria.CorredorAtual.Dentro && Math.Abs(_Trajetoria.ErroLateralAngular) < 30.0 && _Trajetoria.PontoAtual.Tipo != TipoPontoRua.BordaSaida) ||
|
||||
_Trajetoria.PontoAtual.Tipo == TipoPontoRua.BordaEntrada ||
|
||||
_Trajetoria.PontoAtual.Tipo == TipoPontoRua.LigacaoEntrada;
|
||||
|
||||
// Calcula a diferença de ângulo entre o carro e a rua
|
||||
double diferencaAngulo = GPSUtils.CalcularDiferencaAngulo(anguloCarro, anguloRua);
|
||||
|
||||
erroOrientacao = diferencaAngulo;
|
||||
|
||||
Variaveis.OperacaoEmAndamento.OpMapaGPS.Sensoriamento.AnguloDif = erroOrientacao;
|
||||
|
||||
// Calcule o erro lateral baseado nas distâncias entre as ruas do mapa atraves do GPS
|
||||
double erroLateral =
|
||||
!_Trajetoria.CorredorAtual.Dentro ? 0 :
|
||||
(_Trajetoria.DistanciaEsquerda - _Trajetoria.DistanciaDireita);
|
||||
|
||||
double distanciaProximoPonto = _Trajetoria.ProximoPonto.DistanciaAtual;
|
||||
|
||||
double erroUltrassom = UltrasonicA05Helper.CalcularErroUltrassons();
|
||||
|
||||
double erroCombinado = CalcularErroCombinado(erroLateral, erroOrientacao, erroUltrassom, distanciaProximoPonto);
|
||||
|
||||
AjustarGanhosPID(_Controle.PercentualVelocidadeSP);
|
||||
double erroCombinado =
|
||||
consideraAnguloCorredor ? _Trajetoria.ErroOrientacaoAngularCombinado :
|
||||
_Trajetoria.ErroOrientacaoAngularProximoPonto;
|
||||
|
||||
var PID = _Controle.PIDdirecional;
|
||||
// Atualiza o PID com o erro combinado
|
||||
if (_Trajetoria.StatusCarro != StatusCarroMapa.Parado)
|
||||
{
|
||||
// Atualiza o PID com o erro combinado
|
||||
AjustarGanhosPID(_Controle);
|
||||
|
||||
PID.LimiteSaida = _Controle.Angulo_Max;
|
||||
PID.Atualizar(erroCombinado, 0);
|
||||
}
|
||||
|
|
@ -122,79 +107,23 @@ namespace AgroBase.Models.Operacoes
|
|||
_Controle.Angulo = correcaoAngulo;
|
||||
}
|
||||
|
||||
private double CalcularErroCombinado(double erroLateral, double erroOrientacao, double erroUltrassons, double distanciaProximoPonto)
|
||||
private void AjustarGanhosPID(OperacaoControleModel Controle)
|
||||
{
|
||||
bool carroDentroRua = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria.CorredorAtual.Dentro;
|
||||
bool naMargeRua = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria.NaMargemDoCorredor;
|
||||
var PID = Controle.PIDdirecional;
|
||||
double velocidadePercnt = (Controle.PercentualVelocidadeMax - Controle.PercentualVelocidadeMin) * Controle.PercentualVelocidadeSP / 100.0;
|
||||
|
||||
// Quando o robô está dentro do corredor, queremos priorizar a centralização primeiro
|
||||
double pesoLateral;
|
||||
double pesoOrientacao;
|
||||
double pesoUltrassons = 0; // Por enquanto, ultrassons desativados
|
||||
double v = FuncoesMatematicas.Clamp(velocidadePercnt / 100.0, 0.0, 1.0);
|
||||
|
||||
// Converte erro lateral (metros) para graus
|
||||
double erroLateralEmGraus = Math.Atan2(erroLateral, distanciaProximoPonto) * (180.0 / Math.PI);
|
||||
// 🔹 Kp reduz suavemente com o quadrado da velocidade (menos agressivo em alta)
|
||||
PID.Kp = PID.KpBase * (1.0 - 0.4 * Math.Pow(v, 2));
|
||||
|
||||
if (carroDentroRua)
|
||||
{
|
||||
// Normaliza os erros para um intervalo entre 0 e 1
|
||||
double erroOrientacaoNormalizado = Math.Min(Math.Abs(erroOrientacao) / 5.0, 1.0); // Assume 10° como erro máximo
|
||||
// 🔹 Ki cai mais rápido e zera a partir de 60%
|
||||
PID.Ki = v >= 0.6 ? 0.0 : PID.KiBase * (1.0 - Math.Pow(v, 1.5));
|
||||
|
||||
// Usa a mesma regra de peso dinâmica
|
||||
pesoOrientacao = Math.Max(0.3, erroOrientacaoNormalizado); // Quanto maior o erro de orientação, maior seu peso
|
||||
// 🔹 Kd cresce suavemente (forte amortecimento em alta velocidade)
|
||||
PID.Kd = PID.KdBase * (1.0 + 1.2 * Math.Pow(v, 1.2));
|
||||
|
||||
pesoOrientacao = 1.0;
|
||||
pesoLateral = 1.0 - pesoOrientacao; // Quanto menor o erro de orientação, maior o peso lateral
|
||||
}
|
||||
else
|
||||
{
|
||||
// Quando está fora do corredor, prioriza a orientação
|
||||
pesoLateral = 0;
|
||||
pesoOrientacao = 1;
|
||||
}
|
||||
|
||||
// Garante que os pesos somem exatamente 1
|
||||
pesoUltrassons = Math.Max(0, 1 - pesoLateral - pesoOrientacao);
|
||||
|
||||
// Calcula o erro combinado ponderado pelos pesos
|
||||
double erroCombinado =
|
||||
(erroOrientacao * pesoOrientacao) +
|
||||
(erroLateralEmGraus * pesoLateral) +
|
||||
(erroUltrassons * pesoUltrassons);
|
||||
|
||||
return erroCombinado;
|
||||
}
|
||||
|
||||
/*private void AjustarGanhosPID(double velocidadePercnt)
|
||||
{
|
||||
var PID = Variaveis.OperacaoEmAndamento.Controle.PIDdirecional;
|
||||
|
||||
// Fração da velocidade atual em relação à velocidade máxima (0 a 1)
|
||||
double fatorVelocidade = Math.Min(velocidadePercnt / 100.0, 1.0);
|
||||
|
||||
// Ajuste dinâmico dos ganhos PID com curva exponencial para Kp e Kd
|
||||
PID.Kp = PID.KpBase - (0.5 * Math.Pow(fatorVelocidade, 2)); // Reduz Kp mais agressivamente em altas velocidades
|
||||
PID.Ki = fatorVelocidade > 0.8 ? 0.0 : PID.KiBase - (0.01 * fatorVelocidade); // Desativa Ki em altas velocidades
|
||||
PID.Kd = PID.KdBase + (0.05 * Math.Pow(fatorVelocidade, 2)); // Aumenta Kd exponencialmente para amortecer oscilações
|
||||
}*/
|
||||
|
||||
private void AjustarGanhosPID(double velocidadePercnt)
|
||||
{
|
||||
var PID = Variaveis.OperacaoEmAndamento.Controle.PIDdirecional;
|
||||
|
||||
double fatorVelocidade = Math.Min(velocidadePercnt / 100.0, 1.0);
|
||||
|
||||
// 🔹 Redução mais suave de Kp
|
||||
PID.Kp = PID.KpBase - (0.4 * Math.Pow(fatorVelocidade, 1.5)); // Ajuste menos agressivo
|
||||
|
||||
// 🔹 Redução mais controlada do Ki
|
||||
PID.Ki = fatorVelocidade > 0.7 ? 0.0 : PID.KiBase - (0.005 * fatorVelocidade); // Ki desativa mais cedo
|
||||
|
||||
// 🔹 Aumento um pouco mais forte do Kd
|
||||
PID.Kd = PID.KdBase + (0.07 * Math.Pow(fatorVelocidade, 2)); // Amortecimento mais forte
|
||||
|
||||
// 🔹 Log opcional para monitorar ajustes (remover depois de testes)
|
||||
Console.WriteLine($"PID Ajustado: Kp={PID.Kp:F3}, Ki={PID.Ki:F3}, Kd={PID.Kd:F3}");
|
||||
Console.WriteLine($"[PID ADAPT] Vel={velocidadePercnt:F1}% | Kp={PID.Kp:F3}, Ki={PID.Ki:F3}, Kd={PID.Kd:F3}");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -214,11 +143,10 @@ namespace AgroBase.Models.Operacoes
|
|||
if (Variaveis.OperacaoEmAndamento.StatusAtual != StatusOperacao.EmAndamento)
|
||||
{
|
||||
Controle.PercentualVelocidadeSP = 0;
|
||||
Controle.FiltroVelocidade.Reset(Controle.PercentualVelocidadeSP);
|
||||
return;
|
||||
}
|
||||
|
||||
Controle.PercentualVelocidadeSP = CalcularVelocidadeRelativa(Controle);
|
||||
|
||||
switch (Variaveis.OperacaoEmAndamento.Trajetoria.StatusAtual)
|
||||
{
|
||||
case StatusCarroMapa.Parado:
|
||||
|
|
@ -232,7 +160,11 @@ namespace AgroBase.Models.Operacoes
|
|||
bool DesvioSonar = (KinectService.Iniciado && Variaveis.OperacaoEmAndamento.Sensoriamento.SonarFrontal_Kinect.DesvioNecessario);
|
||||
if (Manobrando || DesvioSonar)
|
||||
{
|
||||
Controle.PercentualVelocidadeSP = Math.Min(20.0, Controle.PercentualVelocidadeMin);
|
||||
Controle.PercentualVelocidadeSP = Controle.PercentualVelocidadeMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
Controle.PercentualVelocidadeSP = CalcularVelocidadeRelativa(Controle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -252,6 +184,10 @@ namespace AgroBase.Models.Operacoes
|
|||
{
|
||||
Controle.PercentualVelocidadeSP = Controle.PercentualVelocidadeMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
Controle.PercentualVelocidadeSP = CalcularVelocidadeRelativa(Controle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case StatusCarroMapa.Manobrando:
|
||||
|
|
@ -260,42 +196,41 @@ namespace AgroBase.Models.Operacoes
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Controle.PercentualVelocidadeSP = Math.Max(Controle.PercentualVelocidadeMin, Controle.PercentualVelocidadeSP);
|
||||
Controle.PercentualVelocidadeSP = Math.Min(Controle.PercentualVelocidadeMax, Controle.PercentualVelocidadeSP);
|
||||
|
||||
if (Controle.PercentualVelocidadeSP == Controle.PercentualVelocidadeMin)
|
||||
{
|
||||
Controle.FiltroVelocidade.Reset(Controle.PercentualVelocidadeSP);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Velocidade SP: {Controle.PercentualVelocidadeSP}, ms: {FuncoesMatematicas.CalculaVelocidadeMsPercentual(Controle.PercentualVelocidadeSP)}, km/h: {FuncoesMatematicas.ConverteMsParaKmh(FuncoesMatematicas.CalculaVelocidadeMsPercentual(Controle.PercentualVelocidadeSP))}");
|
||||
|
||||
//double velocidadeFiltrada = Controle.FiltroVelocidade.Filtrar(Controle.PercentualVelocidadeSP);
|
||||
//Controle.PercentualVelocidadeSP = Math.Max(Controle.PercentualVelocidadeMin, velocidadeFiltrada);
|
||||
}
|
||||
|
||||
private double CalcularVelocidadeRelativa(OperacaoControleModel Controle)
|
||||
{
|
||||
double limiteAnguloMax = Controle.Angulo_Max; // Ângulo máximo permitido (ex.: 30 graus)
|
||||
double anguloAtual = Math.Abs(Controle.Angulo); // Ângulo de controle atual em módulo
|
||||
double percentualReduzido = anguloAtual / limiteAnguloMax; // Percentual do ângulo de controle usado (0 a 1)
|
||||
double erroCombinado = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria.ErroOrientacaoAngularCombinado;
|
||||
|
||||
// Obtém os ângulos do carro e da rua
|
||||
double anguloCarro = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
double anguloCorredor = Variaveis.OperacaoEmAndamento.Trajetoria.AnguloMedioCorredor;
|
||||
// Converte erro para uma penalização de velocidade (até 1.5x mais severa em curvas)
|
||||
double severidade = Math.Min(Math.Abs(erroCombinado) / 30.0, 1.0); // Normaliza até 30°
|
||||
double penalidade = severidade * 0.85; // até 85% de penalização
|
||||
|
||||
// **Erro de orientação agora é a diferença real entre os ângulos**
|
||||
double erroOrientacao = Math.Abs(anguloCarro - anguloCorredor); // Diferenca real de ângulos
|
||||
erroOrientacao = Math.Min(erroOrientacao, 30.0); // Limita a 90° para normalização
|
||||
// Calcula velocidade proporcional
|
||||
double faixaVel = Controle.PercentualVelocidadeMax - Controle.PercentualVelocidadeMin;
|
||||
double velocidadeFinal = Controle.PercentualVelocidadeMax - (faixaVel * penalidade);
|
||||
|
||||
// **Peso dinâmico baseado no desalinhamento**
|
||||
// Se o erro for grande, reduz mais a velocidade. Se for pequeno, mantém velocidade alta
|
||||
double pesoErro = erroOrientacao / 30.0; // Normaliza erro para 0 (perfeito) a 1 (erro de 90°)
|
||||
double velocidadeRelativa = Math.Round(Math.Max(Controle.PercentualVelocidadeMin, velocidadeFinal), 2);
|
||||
|
||||
// **Ajusta a influência do ângulo de controle na velocidade**
|
||||
double pesoAnguloControle = 1 - pesoErro; // Quanto maior o erro, menor a influência do ângulo de controle
|
||||
double velocidadeFiltrada = Controle.FiltroVelocidade.Filtrar(velocidadeRelativa);
|
||||
|
||||
// **Redução dinâmica da velocidade baseada no desalinhamento**
|
||||
double reducaoPorErroOrientacao = pesoErro * 0.8; // Quanto maior o erro, maior a penalização (ajustável)
|
||||
|
||||
// **Calcula a velocidade proporcional combinando os dois efeitos com pesos dinâmicos**
|
||||
double percentualVelocidadeRelativo = Controle.PercentualVelocidadeMin +
|
||||
(1 - (pesoAnguloControle * percentualReduzido) - reducaoPorErroOrientacao) * (Controle.PercentualVelocidadeMax - Controle.PercentualVelocidadeMin);
|
||||
|
||||
// **Garante que a velocidade fique dentro dos limites aceitáveis (0 a 100%)**
|
||||
percentualVelocidadeRelativo = Math.Round(Math.Max(Controle.PercentualVelocidadeMin, Math.Min(Controle.PercentualVelocidadeMax, percentualVelocidadeRelativo)), 2);
|
||||
|
||||
return percentualVelocidadeRelativo;
|
||||
return velocidadeFiltrada;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region ATUADOR
|
||||
|
|
@ -325,7 +260,6 @@ namespace AgroBase.Models.Operacoes
|
|||
public int ErvasNoRadar { get; set; } = 0;
|
||||
public double HerbicidaConsumido { get; set; } = 0;
|
||||
public double HerbicidaPorErva { get; set; } = 0;
|
||||
public double AnguloDif { get; set; } = 0;
|
||||
public double AnguloRuaCamera { get; set; } = 0;
|
||||
public int ErvasIdentificadas
|
||||
{
|
||||
|
|
@ -347,7 +281,6 @@ namespace AgroBase.Models.Operacoes
|
|||
ErvasNoRadar = 0;
|
||||
HerbicidaConsumido = 0;
|
||||
HerbicidaPorErva = 0;
|
||||
AnguloDif = 0;
|
||||
|
||||
AtuacoesPorBico = new List<Dictionary<string, int>>();
|
||||
if (Variaveis.OperacaoEmAndamento.DispAtu != null)
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
if (Variaveis.OperacaoEmAndamento.Iniciado && !Variaveis.OperacaoEmAndamento.Finalizando)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.FinalizarOperacao();
|
||||
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
|
||||
}
|
||||
}
|
||||
// Se a operação tiver algum item mandatório interrompido
|
||||
|
|
@ -386,6 +386,7 @@ namespace AgroBase.Models
|
|||
Direcao = Direcao.Parado,
|
||||
PercentualVelocidadeSP = 0,
|
||||
PIDdirecional = new PIDModel(),
|
||||
FiltroVelocidade = new KalmanFilter(),
|
||||
TiposControle = Variaveis.OperacaoEmAndamento.Controle.TiposControle.ToList(),
|
||||
SonarAtivado = Parametros.SonarAtivado,
|
||||
SegmentacaoSemantica = Parametros.Modo == ModoOperacao.MapaGPS,
|
||||
|
|
@ -795,6 +796,7 @@ namespace AgroBase.Models
|
|||
LimiteSaida = Controle.Angulo_Max,
|
||||
SetPoint = 0
|
||||
};
|
||||
Controle.FiltroVelocidade = new KalmanFilter(erroMedicao: 2.0, erroProcesso: 0.05);
|
||||
Controle.ControladorMPC = new MPCController();
|
||||
}
|
||||
|
||||
|
|
@ -819,12 +821,21 @@ namespace AgroBase.Models
|
|||
}
|
||||
}
|
||||
|
||||
public void FinalizarOperacao()
|
||||
public async Task FinalizarOperacao()
|
||||
{
|
||||
if (Variaveis.OperacaoEmAndamento.Finalizando)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Variaveis.OperacaoEmAndamento.Finalizando = true;
|
||||
|
||||
PararCarroOperacaoInterrompida(true);
|
||||
|
||||
Variaveis.OperacaoEmAndamento.Trajetoria.LoopAtualizaDados();
|
||||
|
||||
await Task.Delay(2000);
|
||||
|
||||
Variaveis.OperacaoEmAndamento.Iniciado = false;
|
||||
Variaveis.OperacaoEmAndamento.DataFim = DateTime.Now;
|
||||
|
||||
|
|
@ -917,6 +928,7 @@ namespace AgroBase.Models
|
|||
LimiteSaida = Controle.Angulo_Max,
|
||||
SetPoint = 0
|
||||
};
|
||||
Controle.FiltroVelocidade = new KalmanFilter(erroMedicao: 2.0, erroProcesso: 0.05);
|
||||
Controle.ControladorMPC = new MPCController();
|
||||
}
|
||||
|
||||
|
|
@ -930,8 +942,10 @@ namespace AgroBase.Models
|
|||
{
|
||||
Variaveis.OperacaoEmAndamento.StatusAtual = StatusOperacao.Parametrizando;
|
||||
Variaveis.OperacaoEmAndamento.Iniciado = false;
|
||||
Variaveis.OperacaoEmAndamento.Simulando = false;
|
||||
Variaveis.OperacaoEmAndamento.Mapa = new MapasModel();
|
||||
Variaveis.OperacaoEmAndamento.Trajetoria = new TrajetoriaMapaOperacaoModel(new List<List<GPSModel>>());
|
||||
Variaveis.OperacaoEmAndamento.GPSTrajetoria = new List<GPSModel>();
|
||||
|
||||
var Topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == MapasVariaveisModel.TopicoSelecaoRuasMapa);
|
||||
Topico.Mensagens.Add(new MqttService.MqttTopicosMensagensModel()
|
||||
|
|
@ -975,6 +989,7 @@ namespace AgroBase.Models
|
|||
LimiteSaida = Controle.Angulo_Max,
|
||||
SetPoint = 0
|
||||
};
|
||||
Controle.FiltroVelocidade = new KalmanFilter(erroMedicao: 2.0, erroProcesso: 0.05);
|
||||
}
|
||||
|
||||
Controle.Angulo = 0;
|
||||
|
|
@ -2815,6 +2830,7 @@ namespace AgroBase.Models
|
|||
|
||||
public TiposControladorDirecional TipoControleDirecional { get; set; } = TiposControladorDirecional.PID;
|
||||
public PIDModel PIDdirecional { get; set; } = new PIDModel();
|
||||
public KalmanFilter FiltroVelocidade { get; set; } = new KalmanFilter();
|
||||
public MPCController ControladorMPC { get; set; } = new MPCController();
|
||||
|
||||
public OperacaoControleModel Clone()
|
||||
|
|
@ -2829,6 +2845,7 @@ namespace AgroBase.Models
|
|||
PercentualInicioPulverizacao = PercentualInicioPulverizacao,
|
||||
PercentualVelocidadeSP = PercentualVelocidadeSP,
|
||||
PIDdirecional = PIDdirecional.Clone(),
|
||||
FiltroVelocidade = FiltroVelocidade.Clone(),
|
||||
PressaoLinha = PressaoLinha,
|
||||
PulverizadorAutomatico = PulverizadorAutomatico,
|
||||
RPM_Max = RPM_Max,
|
||||
|
|
@ -2918,7 +2935,6 @@ namespace AgroBase.Models
|
|||
}
|
||||
|
||||
public double AnguloRuaCamera { get; set; } = 0;
|
||||
public double AnguloDif { get; set; } = 0;
|
||||
|
||||
public OperacaoSensoriamentoLogAtuModel Atuador { get; set; }
|
||||
public OperacaoSensoriamentoLogMvdModel Movimentacao { get; set; }
|
||||
|
|
@ -2998,15 +3014,22 @@ namespace AgroBase.Models
|
|||
CorredorAtual = _Trajetoria?.CorredorAtual?.Clone(false) ?? new CorredorTrajetoriaModel(),
|
||||
DirecaoCaminho = _Trajetoria?.DirecaoCaminho ?? DirecaoCarroRua.Parado,
|
||||
AnguloCaminho = _Trajetoria?.AnguloCaminho ?? 0,
|
||||
AnguloMedioCorredor = _Trajetoria?.AnguloMedioCorredor ?? 0,
|
||||
DistanciaTotal = _Trajetoria?.DistanciaTotal ?? 0,
|
||||
DistanciaPercorrida = _Trajetoria?.DistanciaPercorrida ?? 0,
|
||||
DistanciaRestante = _Trajetoria?.DistanciaRestante ?? 0,
|
||||
NaMargemDoCorredor = _Trajetoria?.NaMargemDoCorredor ?? false,
|
||||
ManobrandoEntreRuas = _Trajetoria?.ManobrandoEntreRuas ?? false,
|
||||
TempoEstimadoRestante = _Trajetoria?.TempoEstimadoRestante ?? "",
|
||||
TempoEstimadoOperacao = _Trajetoria?.TempoEstimadoOperacao ?? "",
|
||||
ProximoPonto = _Trajetoria?.ProximoPonto?.Clone() ?? new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo),
|
||||
PontoMaisProximo = _Trajetoria?.PontoMaisProximo?.Clone() ?? new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo),
|
||||
PontoAtual = _Trajetoria?.PontoAtual?.Clone() ?? new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo)
|
||||
PontoAtual = _Trajetoria?.PontoAtual?.Clone() ?? new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo),
|
||||
ErroLateralAngular = _Trajetoria?.ErroLateralAngular ?? 0,
|
||||
ErroOrientacaoAngular = _Trajetoria?.ErroOrientacaoAngular ?? 0,
|
||||
ErroOrientacaoAngularCombinado = _Trajetoria?.ErroOrientacaoAngularCombinado ?? 0,
|
||||
ErroOrientacaoAngularCaminho = _Trajetoria?.ErroOrientacaoAngularCaminho ?? 0,
|
||||
ErroOrientacaoAngularProximoPonto = _Trajetoria?.ErroOrientacaoAngularProximoPonto ?? 0
|
||||
};
|
||||
|
||||
var dadosGps = GPSService.UltimaLeitura.Clone();
|
||||
|
|
@ -3029,7 +3052,6 @@ namespace AgroBase.Models
|
|||
DataFim = Variaveis.OperacaoEmAndamento.DataFim,
|
||||
TempoDecorridoSeg = Variaveis.OperacaoEmAndamento.TempoDecorridoSegs,
|
||||
|
||||
AnguloDif = _OpMapaGPS.Sensoriamento.AnguloDif,
|
||||
AnguloRuaCamera = Variaveis.OperacaoEmAndamento.CameraCaminho?.Angulo ?? 0,
|
||||
|
||||
Atuador = dadosAtuador,
|
||||
|
|
@ -3057,7 +3079,6 @@ namespace AgroBase.Models
|
|||
DataInicio = DataInicio,
|
||||
DataFim = DataFim,
|
||||
TempoDecorridoSeg = TempoDecorridoSeg,
|
||||
AnguloDif = AnguloDif,
|
||||
AnguloRuaCamera = AnguloRuaCamera,
|
||||
Atuador = Atuador.Clone(),
|
||||
Movimentacao = Movimentacao.Clone(),
|
||||
|
|
@ -3173,6 +3194,7 @@ namespace AgroBase.Models
|
|||
public StatusCarroMapa StatusCarro { get; set; }
|
||||
public double ProgressoTrajeto { get; set; }
|
||||
public double AnguloCaminho { get; set; }
|
||||
public double AnguloMedioCorredor { get; set; }
|
||||
public DirecaoCarroRua DirecaoCaminho { get; set; }
|
||||
public CorredorTrajetoriaModel CorredorAtual { get; set; }
|
||||
public double DistanciaEsquerda { get; set; }
|
||||
|
|
@ -3181,18 +3203,26 @@ namespace AgroBase.Models
|
|||
public double DistanciaPercorrida { get; set; }
|
||||
public double DistanciaRestante { get; set; }
|
||||
public bool NaMargemDoCorredor { get; set; }
|
||||
public bool ManobrandoEntreRuas { get; set; }
|
||||
public string TempoEstimadoRestante { get; set; }
|
||||
public string TempoEstimadoOperacao { get; set; }
|
||||
public PontoTrajetoriaModel ProximoPonto { get; set; }
|
||||
public PontoTrajetoriaModel PontoAtual { get; set; }
|
||||
public PontoTrajetoriaModel PontoMaisProximo { get; set; }
|
||||
|
||||
public double ErroOrientacaoAngular { get; set; }
|
||||
public double ErroOrientacaoAngularCombinado { get; set; }
|
||||
public double ErroOrientacaoAngularCaminho { get; set; }
|
||||
public double ErroOrientacaoAngularProximoPonto { get; set; }
|
||||
public double ErroLateralAngular { get; set; }
|
||||
|
||||
public OperacaoSensoriamentoLogTrajetoriaModel Clone()
|
||||
{
|
||||
return new OperacaoSensoriamentoLogTrajetoriaModel()
|
||||
{
|
||||
StatusCarro = StatusCarro,
|
||||
AnguloCaminho = AnguloCaminho,
|
||||
AnguloMedioCorredor = AnguloMedioCorredor,
|
||||
DirecaoCaminho = DirecaoCaminho,
|
||||
DistanciaDireita = DistanciaDireita,
|
||||
DistanciaEsquerda = DistanciaEsquerda,
|
||||
|
|
@ -3202,8 +3232,14 @@ namespace AgroBase.Models
|
|||
DistanciaPercorrida = DistanciaPercorrida,
|
||||
DistanciaRestante = DistanciaRestante,
|
||||
NaMargemDoCorredor = NaMargemDoCorredor,
|
||||
ManobrandoEntreRuas = ManobrandoEntreRuas,
|
||||
TempoEstimadoRestante = TempoEstimadoRestante,
|
||||
TempoEstimadoOperacao = TempoEstimadoOperacao,
|
||||
ErroLateralAngular = ErroLateralAngular,
|
||||
ErroOrientacaoAngularCombinado = ErroOrientacaoAngularCombinado,
|
||||
ErroOrientacaoAngular = ErroOrientacaoAngular,
|
||||
ErroOrientacaoAngularCaminho = ErroOrientacaoAngularCaminho,
|
||||
ErroOrientacaoAngularProximoPonto = ErroOrientacaoAngularProximoPonto,
|
||||
ProximoPonto = ProximoPonto.Clone(),
|
||||
PontoAtual = PontoAtual.Clone(),
|
||||
PontoMaisProximo = PontoMaisProximo.Clone(),
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
Posicao = GPSService.UltimaLeitura,
|
||||
LarguraCorredor = 1.0,
|
||||
idxCorredor = CorredorAtual.Idx,
|
||||
idxCorredor = CorredorAtual?.Idx ?? 0,
|
||||
Visitado = true
|
||||
}
|
||||
};
|
||||
|
|
@ -208,8 +208,8 @@ namespace AgroBase.Models
|
|||
public double AnguloCaminho { get; private set; }
|
||||
private void AtualizarAnguloCaminho()
|
||||
{
|
||||
GPSModel pontoComparar = ProximoPonto != null ? ProximoPonto.Posicao : PontoAtual.Posicao;
|
||||
AnguloCaminho = GPSUtils.CalcularOrientacao(GPSService.UltimaLeitura, pontoComparar);
|
||||
PontoTrajetoriaModel pontoComparar = PontoAtual.Aproximando ? PontoAtual : ProximoPonto != null ? ProximoPonto : PontoAtual;
|
||||
AnguloCaminho = GPSUtils.CalcularOrientacao(GPSService.UltimaLeitura, pontoComparar.Posicao);
|
||||
}
|
||||
[JsonProperty]
|
||||
public double DistanciaEsquerda { get; private set; }
|
||||
|
|
@ -217,39 +217,66 @@ namespace AgroBase.Models
|
|||
public double DistanciaDireita { get; private set; }
|
||||
private void AtualizarDistanciasLaterais()
|
||||
{
|
||||
DistanciaEsquerda = CalcularDistanciaLateral(true);
|
||||
DistanciaDireita = CalcularDistanciaLateral(false);
|
||||
DistanciaEsquerda = CalcularDistanciaLateral(true, GPSService.UltimaLeitura, CorredorAtual.idxRuaEsquerda, PontoAtual.Direcao);
|
||||
DistanciaDireita = CalcularDistanciaLateral(false, GPSService.UltimaLeitura, CorredorAtual.idxRuaDireita, PontoAtual.Direcao);
|
||||
}
|
||||
|
||||
private double CalcularDistanciaLateral(bool ladoEsquerdo)
|
||||
public double CalcularDistanciaLateral(bool ladoEsquerdo, GPSModel posicaoAtual, int idxRua, DirecaoCarroRua direcaoAtual)
|
||||
{
|
||||
// Verifica se o corredor atual existe
|
||||
if (!_CorredorAtualDefinido) return 0;
|
||||
|
||||
var rua = ladoEsquerdo ? new List<GPSModel>(RuasPlantacao[CorredorAtual.idxRuaEsquerda]) : new List<GPSModel>(RuasPlantacao[CorredorAtual.idxRuaDireita]);
|
||||
List<GPSModel> rua = new List<GPSModel>(RuasPlantacao[idxRua]);
|
||||
|
||||
double anguloAprojetar = GPSUtils.CalcularOrientacao(rua[rua.Count - 1], rua[0]);
|
||||
double anguloBprojetar = GPSUtils.CalcularOrientacao(rua[0], rua[rua.Count - 1]);
|
||||
GPSModel pontoA = GPSUtils.GerarPontoDeslocado(rua[0], anguloAprojetar, 10);
|
||||
GPSModel pontoB = GPSUtils.GerarPontoDeslocado(rua[rua.Count - 1], anguloBprojetar, 10);
|
||||
double d0 = double.MaxValue;
|
||||
int idx = -1;
|
||||
for (int i = 0; i < rua.Count; i++)
|
||||
{
|
||||
double dist = GPSUtils.DistanciaEntrePontos(posicaoAtual, rua[i]);
|
||||
if (dist < d0)
|
||||
{
|
||||
d0 = dist;
|
||||
idx = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rua.Insert(0, pontoA);
|
||||
rua.Add(pontoB);
|
||||
GPSModel p0 = rua[idx - (idx > 0 ? 1 : 0)];
|
||||
GPSModel p1 = rua[idx + (idx < (rua.Count - 1) ? 1 : 0)];
|
||||
int idxPa = rua.IndexOf(p0);
|
||||
int idxPb = rua.IndexOf(p1);
|
||||
double anguloAprojetar = GPSUtils.CalcularOrientacao(rua[idxPb], rua[idxPa]);
|
||||
double anguloBprojetar = GPSUtils.CalcularOrientacao(rua[idxPa], rua[idxPb]);
|
||||
|
||||
GPSModel pontoA = GPSUtils.GerarPontoDeslocado(rua[idxPa], anguloAprojetar, DistanciaManobraEntreRuas);
|
||||
GPSModel pontoB = GPSUtils.GerarPontoDeslocado(rua[idxPb], anguloBprojetar, DistanciaManobraEntreRuas);
|
||||
|
||||
List<GPSModel> novaRua = new List<GPSModel>();
|
||||
novaRua.Add(pontoA);
|
||||
for (int i = idxPa; i <= idxPb; i++)
|
||||
{
|
||||
novaRua.Add(rua[i]);
|
||||
}
|
||||
novaRua.Add(pontoB);
|
||||
|
||||
rua = novaRua;
|
||||
|
||||
int qtdPontosRua = Convert.ToInt32(GPSUtils.DistanciaDoTrecho(rua));
|
||||
rua = GPSUtils.InterpolarRota(rua, qtdPontosRua);
|
||||
double d = GPSUtils.DistanciaDoTrecho(rua);
|
||||
|
||||
// Calcula a menor distância entre o robô e a rua
|
||||
double distancia = GPSUtils.CalcularMenorDistanciaAteTrecho(GPSService.UltimaLeitura, rua);
|
||||
double distancia = GPSUtils.CalcularMenorDistanciaAteTrecho(posicaoAtual, rua);
|
||||
|
||||
// Calcula o vetor entre os pontos da rua e o vetor entre o ponto A e o GPS
|
||||
double crossProduct =
|
||||
(pontoB.Longitude - pontoA.Longitude) * (GPSService.UltimaLeitura.Latitude - pontoA.Latitude) -
|
||||
(pontoB.Latitude - pontoA.Latitude) * (GPSService.UltimaLeitura.Longitude - pontoA.Longitude);
|
||||
(pontoB.Longitude - pontoA.Longitude) * (posicaoAtual.Latitude - pontoA.Latitude) -
|
||||
(pontoB.Latitude - pontoA.Latitude) * (posicaoAtual.Longitude - pontoA.Longitude);
|
||||
|
||||
// Ajusta a distância com base no sentido de deslocamento do robô
|
||||
if ((PontoAtual.Direcao == DirecaoCarroRua.Volta && ladoEsquerdo) || (PontoAtual.Direcao == DirecaoCarroRua.Ida && !ladoEsquerdo))
|
||||
if ((direcaoAtual == DirecaoCarroRua.Volta && ladoEsquerdo) || (direcaoAtual == DirecaoCarroRua.Ida && !ladoEsquerdo))
|
||||
{
|
||||
distancia *= crossProduct > 0 ? 1 : -1;
|
||||
}
|
||||
|
|
@ -378,7 +405,7 @@ namespace AgroBase.Models
|
|||
private void AtualizarStatusAtual()
|
||||
{
|
||||
StatusAtual = StatusCarroMapa.Parado;
|
||||
if (ProximoPonto != null && CorredorAtual != null)
|
||||
if (ProximoPonto != null && CorredorAtual != null && Variaveis.OperacaoEmAndamento.StatusAtual == StatusOperacao.EmAndamento)
|
||||
{
|
||||
if (!CorredorAtual.Dentro && ProximoPonto.DistanciaAtual > DistanciaManobraEntreRuas)
|
||||
{
|
||||
|
|
@ -480,6 +507,63 @@ namespace AgroBase.Models
|
|||
TempoEstimadoRestante = totalRestante.ToString("HH:mm:ss");
|
||||
}
|
||||
|
||||
[JsonProperty]
|
||||
public double ErroOrientacaoAngular { get; private set; }
|
||||
[JsonProperty]
|
||||
public double ErroOrientacaoAngularCombinado { get; private set; }
|
||||
[JsonProperty]
|
||||
public double ErroOrientacaoAngularCaminho { get; private set; }
|
||||
[JsonProperty]
|
||||
public double ErroOrientacaoAngularProximoPonto { get; private set; }
|
||||
[JsonProperty]
|
||||
public double ErroLateralAngular { get; private set; }
|
||||
|
||||
private void AtualizarErroCombinado()
|
||||
{
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
|
||||
double anguloCamera = _Sensoriamento.AnguloRuaCamera;
|
||||
double anguloCorredor = AnguloMedioCorredor;
|
||||
double anguloProximoPonto = AnguloCaminho;
|
||||
double anguloCarro = _Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
|
||||
// Erro 1: Direção para onde o robô deve ir (centro do corredor)
|
||||
double erroIrParaCentro = GPSUtils.CalcularDiferencaAngulo(anguloCarro, anguloProximoPonto);
|
||||
|
||||
// Erro 2: Quanto o robô está desalinhado da orientação da rua
|
||||
double desalinhamentoComRua = GPSUtils.CalcularDiferencaAngulo(anguloCarro, anguloCorredor);
|
||||
|
||||
// Erro 3 (secundário): Diferença entre o ângulo do corredor e o ponto (curva futura)
|
||||
double curvaDaRua = GPSUtils.CalcularDiferencaAngulo(anguloProximoPonto, anguloCorredor);
|
||||
|
||||
// Peso do desalinhamento atual (prioriza alinhar o robô ao corredor)
|
||||
double pesoAlinhamento = Math.Min(Math.Abs(desalinhamentoComRua) / 30.0, 1.0); // Normaliza até 30°
|
||||
|
||||
// Peso do centro (prioriza ir pro ponto central do corredor)
|
||||
double pesoCentro = 1.0 - pesoAlinhamento;
|
||||
|
||||
// Peso extra para curvas mais fechadas
|
||||
double boostCurva = 1.0 + (Math.Abs(curvaDaRua) / 45.0); // aumenta peso em curvas
|
||||
|
||||
// Calcule o erro lateral baseado nas distâncias entre as ruas do mapa atraves do GPS
|
||||
double erroLateral = !(CorredorAtual?.Dentro ?? false) ? 0 : (DistanciaEsquerda - DistanciaDireita);
|
||||
double distanciaProximoPonto = ProximoPonto.DistanciaAtual;
|
||||
double erroLateralGraus = Math.Atan2(erroLateral, distanciaProximoPonto) * (180.0 / Math.PI);
|
||||
|
||||
// Calcule o erro do ultrassom
|
||||
double erroUltrassom = UltrasonicA05Helper.CalcularErroUltrassons();
|
||||
|
||||
// Combina os erros com pesos dinâmicos
|
||||
double erroCombinado = (erroIrParaCentro * pesoCentro) + (desalinhamentoComRua * pesoAlinhamento);
|
||||
|
||||
|
||||
ErroOrientacaoAngularProximoPonto = erroIrParaCentro;
|
||||
ErroOrientacaoAngularCaminho = desalinhamentoComRua;
|
||||
ErroOrientacaoAngular = curvaDaRua;
|
||||
ErroOrientacaoAngularCombinado = erroCombinado * boostCurva;
|
||||
ErroLateralAngular = erroLateralGraus;
|
||||
}
|
||||
|
||||
private void MarcarPontosIntermediariosNaoVisitados()
|
||||
{
|
||||
if (!_TrajetoriaFixaDefinida) return;
|
||||
|
|
@ -532,6 +616,8 @@ namespace AgroBase.Models
|
|||
AtualizarPercentualTrajetoria();
|
||||
AtualizarTempoEstimado();
|
||||
|
||||
AtualizarErroCombinado();
|
||||
|
||||
AtualizarTrajetoriaDinamica();
|
||||
}
|
||||
|
||||
|
|
@ -787,7 +873,7 @@ namespace AgroBase.Models
|
|||
PontoTrajetoriaModel PontoRobo = new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo)
|
||||
{
|
||||
idxCorredor = 0,
|
||||
idxPonto = _trajetoriaFixa.Count(),
|
||||
idxPonto = 0,
|
||||
idxPontoCorredor = 0,
|
||||
Posicao = GPSService.UltimaLeitura,
|
||||
Direcao = direcaoAtual,
|
||||
|
|
@ -809,7 +895,9 @@ namespace AgroBase.Models
|
|||
|
||||
if (_trajetoriaFixa.Count() > 1 && idxEsq == 0 && idxDir == 0)
|
||||
{
|
||||
(List<GPSModel> ruaEsq, List<GPSModel> ruaDir) = DeterminarRuasLaterais(_trajetoriaFixa[1].Posicao, _trajetoriaFixa[2].Posicao, RuasPlantacao[0], RuasPlantacao[1]);
|
||||
var p0 = _trajetoriaFixa.Where(x => x.Tipo == TipoPontoRua.Rua).Skip(2).FirstOrDefault();
|
||||
var p1 = _trajetoriaFixa.Where(x => x.Tipo == TipoPontoRua.Rua).Skip(3).FirstOrDefault();
|
||||
(List<GPSModel> ruaEsq, List<GPSModel> ruaDir) = DeterminarRuasLaterais(p0.Posicao, p1.Posicao, RuasPlantacao[0], RuasPlantacao[1]);
|
||||
idxEsq = RuasPlantacao.IndexOf(ruaEsq);
|
||||
idxDir = RuasPlantacao.IndexOf(ruaDir);
|
||||
}
|
||||
|
|
@ -847,7 +935,7 @@ namespace AgroBase.Models
|
|||
Direcao = direcaoAtual,
|
||||
Orientacao = GPSUtils.CalcularOrientacao(ultimoPontoTrajetoria.Posicao, PrimeiroPonto),
|
||||
Visitado = false,
|
||||
LarguraCorredor = LarguraCorredorPadrao
|
||||
LarguraCorredor = larguraCorredorMenor
|
||||
};
|
||||
|
||||
bool PontoInicialAdicionado = false;
|
||||
|
|
@ -919,9 +1007,7 @@ namespace AgroBase.Models
|
|||
Direcao = direcaoAtual,
|
||||
Orientacao = GPSUtils.CalcularOrientacao(_trajetoriaFixa.Last().Posicao, pontoAtual),
|
||||
Visitado = false,
|
||||
LarguraCorredor =
|
||||
distanciaCorredor < DistanciaPrimeirosPontosProjecao && !bordaEntrada && !bordaSaida ? larguraCorredorMenor :
|
||||
CorredoresLarguras[idx]
|
||||
LarguraCorredor = bordaEntrada || bordaSaida ? larguraCorredorMenor : CorredoresLarguras[idx]
|
||||
};
|
||||
|
||||
_trajetoriaFixa.Add(PontoTrajetoria);
|
||||
|
|
@ -1110,7 +1196,13 @@ namespace AgroBase.Models
|
|||
private (List<GPSModel> ruaEsquerda, List<GPSModel> ruaDireita) DeterminarRuasLaterais(GPSModel robo, GPSModel proximoPonto, List<GPSModel> rua1, List<GPSModel> rua2)
|
||||
{
|
||||
// Determinar qual está à esquerda e qual está à direita
|
||||
bool rua1EstaEsquerda = EstaEsquerda(robo, proximoPonto, Centroide(rua1));
|
||||
var r1 = new List<GPSModel>(rua1);
|
||||
if (ExtremoMaisProximoMapa == 1)
|
||||
{
|
||||
r1.Reverse();
|
||||
}
|
||||
r1 = r1.Take(3).ToList();
|
||||
bool rua1EstaEsquerda = EstaEsquerda(robo, proximoPonto, Centroide(r1));
|
||||
|
||||
return rua1EstaEsquerda ? (rua1, rua2) : (rua2, rua1);
|
||||
}
|
||||
|
|
@ -1221,8 +1313,8 @@ namespace AgroBase.Models
|
|||
public int idxPontoCorredor { get; set; }
|
||||
public GPSModel Posicao { get; set; }
|
||||
public double Orientacao { get; set; }
|
||||
public Enums.DirecaoCarroRua Direcao { get; set; }
|
||||
public Enums.TipoPontoRua Tipo { get; }
|
||||
public DirecaoCarroRua Direcao { get; set; }
|
||||
public TipoPontoRua Tipo { get; }
|
||||
public double LarguraCorredor { get; set; }
|
||||
public double DistanciaMargem { get; private set; }
|
||||
public bool Visitado { get; set; } = false;
|
||||
|
|
|
|||
|
|
@ -719,35 +719,6 @@ namespace AgroBase.Services
|
|||
|
||||
WT901CService.DadosLeitura.AtualizarOffset(UltimaLeitura);
|
||||
|
||||
/*if (witIniciado && gpsIniciado)
|
||||
{
|
||||
// Obtém os ângulos de ambos os sensores
|
||||
double anguloWT901C = WT901CService.DadosLeitura.AnguloCorrigido;
|
||||
double anguloGPS = UltimaLeitura.OrientacaoReal;
|
||||
double anguloGPSMovimento = UltimaLeitura.OrientacaoMovimento;
|
||||
double distAnguloGPS = UltimaLeitura.Distancia;
|
||||
|
||||
anguloFinal = CalcularAnguloUnificado(anguloGPS, UltimaLeitura.QualidadeFix, anguloGPSMovimento, distAnguloGPS, anguloWT901C);
|
||||
}
|
||||
else if (witIniciado)
|
||||
{
|
||||
// Apenas o WT901C está disponível
|
||||
anguloFinal = WT901CService.DadosLeitura.AnguloCorrigido;
|
||||
}
|
||||
else if (gpsIniciado)
|
||||
{
|
||||
// Apenas o GPS está disponível
|
||||
double anguloGPS = UltimaLeitura.OrientacaoReal;
|
||||
double anguloGPSMovimento = UltimaLeitura.OrientacaoMovimento;
|
||||
double distAnguloGPS = UltimaLeitura.Distancia;
|
||||
|
||||
anguloFinal = CalcularAnguloUnificado(anguloGPS, UltimaLeitura.QualidadeFix, anguloGPSMovimento, distAnguloGPS);
|
||||
}
|
||||
else
|
||||
{
|
||||
anguloFinal = UltimaLeitura.OrientacaoMovimento;
|
||||
}*/
|
||||
|
||||
if (gpsIniciado)
|
||||
{
|
||||
// O GPS está disponível
|
||||
|
|
@ -758,8 +729,9 @@ namespace AgroBase.Services
|
|||
double distAnguloGPS = UltimaLeitura.Distancia;
|
||||
|
||||
//anguloFinal = CalcularAnguloUnificado(anguloGPS, UltimaLeitura.QualidadeFix, anguloGPSMovimento, distAnguloGPS);
|
||||
anguloFinal = GPSUtils.MisturarAngulosPorDistancia(anguloGPS, anguloGPSMovimento, distAnguloGPS, TrajetoriaMapaOperacaoModel.DistanciaMaximaEntreLeituras, 0.03, 0.3);
|
||||
|
||||
anguloFinal = anguloGPS;
|
||||
//anguloFinal = anguloGPS;
|
||||
}
|
||||
else if (witIniciado)
|
||||
{
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1,221 @@
|
|||
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"Id":"1","Name":"28_03_2025_14_52_47","Length":24.117658942990531,"Dist1":0.0,"Dist2":0.0},"geometry":{"id":null,"type":"LineString","coordinates":[[-47.395224896,-22.172530905666665],[-47.395224814666669,-22.172530881166665],[-47.395224869166668,-22.172530858666665],[-47.395224843666668,-22.1725308255],[-47.395224782833331,-22.1725309215],[-47.395224707166669,-22.1725309895],[-47.395224716333331,-22.172530981666668],[-47.3952246845,-22.1725309905],[-47.395224654333333,-22.172531001833335],[-47.395224638333332,-22.1725310205],[-47.395224615333333,-22.1725310215],[-47.395224601333332,-22.1725310395],[-47.3952245865,-22.172531038333332],[-47.395224556666669,-22.172531053333334],[-47.395224520833331,-22.1725310615],[-47.395224496833336,-22.172531070166666],[-47.395224473833331,-22.172531077166667],[-47.395224445666663,-22.172531089166668],[-47.395224442166665,-22.172531103166666],[-47.395224427,-22.172531076333332],[-47.395224394833335,-22.1725310685],[-47.395224381666665,-22.1725311315],[-47.395224372666668,-22.172531105666668],[-47.395224357333333,-22.172531095],[-47.395224388166667,-22.172531347666666],[-47.395225137333334,-22.172534490666667],[-47.395225645,-22.172538111],[-47.39522384633333,-22.172540902666668],[-47.39522103583333,-22.172543275166667],[-47.395217679,-22.17254414],[-47.395214692833335,-22.172546121833335],[-47.395210529,-22.172546959833333],[-47.395206482333336,-22.172548131666666],[-47.395202635833336,-22.172548931],[-47.395198742666665,-22.1725496485],[-47.39519530816667,-22.172551297],[-47.395193089166668,-22.172553379166665],[-47.3951906165,-22.172556357833333],[-47.39518954,-22.172558924333334],[-47.3951892955,-22.172562425333332],[-47.395189338666668,-22.172565753333334],[-47.3951903165,-22.172569415833333],[-47.395191980333337,-22.172572816333332],[-47.395194284666665,-22.172577084833332],[-47.395197333333336,-22.172582304666665],[-47.3951991365,-22.172587995166666],[-47.395201415833334,-22.172594441666668],[-47.395203092666669,-22.172602672666667],[-47.395204304333333,-22.172610736333333],[-47.395205132,-22.172618987833335],[-47.395205720666667,-22.172626966833334],[-47.395206206833336,-22.172634488333333],[-47.395206750333337,-22.1726419035],[-47.395207180666667,-22.172649125166668],[-47.3952078105,-22.172656991166665],[-47.395208609,-22.1726643035],[-47.395209229,-22.1726726965],[-47.395209939166669,-22.1726804585],[-47.395211465666669,-22.172686973],[-47.395212691,-22.1726939085],[-47.3952135945,-22.172699633833332],[-47.3952137895,-22.1727036245],[-47.395214332833334,-22.1727079415],[-47.395215900666663,-22.172710840833332],[-47.395216996833334,-22.172713710833332],[-47.395218383666666,-22.172715863833332],[-47.39521935016667,-22.172718333833334],[-47.395218823,-22.172720601166667],[-47.395218898333333,-22.172720221166667],[-47.395218846666666,-22.172720248],[-47.3952188105,-22.172720256333335],[-47.39521881266667,-22.172720288333334],[-47.395218752333335,-22.1727202475],[-47.395218729166665,-22.172720266333332],[-47.3952186995,-22.172720271833334],[-47.395218683,-22.172720275166668],[-47.395218645666667,-22.172720276333333],[-47.395218627666665,-22.1727202785],[-47.3952186145,-22.172720284],[-47.395218570333334,-22.1727203085],[-47.395218561833332,-22.172720305666665],[-47.3952185305,-22.172720299],[-47.3952184855,-22.172720302666665],[-47.3952184605,-22.172720312166668],[-47.39521843233333,-22.172720307833334],[-47.395218399833333,-22.1727203335],[-47.395218375333336,-22.172720338333335],[-47.395218384,-22.172720347666665],[-47.395218363333335,-22.172720357666666],[-47.395218321833333,-22.172720362666666],[-47.3952182875,-22.172720388833334],[-47.395218217666667,-22.172720461333334],[-47.395218247333332,-22.1727204295],[-47.395218216166668,-22.172720418833332],[-47.395218204666669,-22.1727204255],[-47.395218174,-22.172720434166667]]}}]}
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"Id": "1",
|
||||
"Name": "CidadeJardimTerreno2",
|
||||
"Length": 14.558011415731592,
|
||||
"Dist1": 14.558011415731592,
|
||||
"Dist2": 0.0
|
||||
},
|
||||
"geometry": {
|
||||
"id": null,
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
-47.395205344,
|
||||
-22.172559531333334
|
||||
],
|
||||
[
|
||||
-47.395212610166666,
|
||||
-22.172614638833334
|
||||
],
|
||||
[
|
||||
-47.395219157,
|
||||
-22.172656417833334
|
||||
],
|
||||
[
|
||||
-47.395223544833335,
|
||||
-22.1726892105
|
||||
],
|
||||
[
|
||||
-47.39522414098443,
|
||||
-22.17269369161165
|
||||
],
|
||||
[
|
||||
-47.395225326538004,
|
||||
-22.172702654611555
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"Id": "2",
|
||||
"Name": "CidadeJardimTerreno2",
|
||||
"Length": 14.771318274761821,
|
||||
"Dist1": 14.558011415731592,
|
||||
"Dist2": 0.0
|
||||
},
|
||||
"geometry": {
|
||||
"id": null,
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
-47.39521090233333,
|
||||
-22.172708800833334
|
||||
],
|
||||
[
|
||||
-47.395206943666665,
|
||||
-22.172679811
|
||||
],
|
||||
[
|
||||
-47.395202420666664,
|
||||
-22.1726491015
|
||||
],
|
||||
[
|
||||
-47.395198865666664,
|
||||
-22.172615782833333
|
||||
],
|
||||
[
|
||||
-47.395193255833334,
|
||||
-22.172577132833332
|
||||
],
|
||||
[
|
||||
-47.395192610024395,
|
||||
-22.17257265769541
|
||||
],
|
||||
[
|
||||
-47.395191325698136,
|
||||
-22.172563706509337
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"Id": "3",
|
||||
"Name": "CidadeJardimTerreno2",
|
||||
"Length": 14.827915524386164,
|
||||
"Dist1": 14.558011415731592,
|
||||
"Dist2": 0.0
|
||||
},
|
||||
"geometry": {
|
||||
"id": null,
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
-47.3951762925,
|
||||
-22.172561603
|
||||
],
|
||||
[
|
||||
-47.395180824166665,
|
||||
-22.172591686166665
|
||||
],
|
||||
[
|
||||
-47.395185745333336,
|
||||
-22.172623080166666
|
||||
],
|
||||
[
|
||||
-47.395190433,
|
||||
-22.172656367166667
|
||||
],
|
||||
[
|
||||
-47.395195199,
|
||||
-22.172693641833334
|
||||
],
|
||||
[
|
||||
-47.39519576904436,
|
||||
-22.172698125891035
|
||||
],
|
||||
[
|
||||
-47.39519690267159,
|
||||
-22.172707094716973
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"Id": "4",
|
||||
"Name": "CidadeJardimTerreno2",
|
||||
"Length": 14.785159385903514,
|
||||
"Dist1": 14.558011415731592,
|
||||
"Dist2": 0.0
|
||||
},
|
||||
"geometry": {
|
||||
"id": null,
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
-47.39518293216667,
|
||||
-22.1727127985
|
||||
],
|
||||
[
|
||||
-47.39517819266667,
|
||||
-22.172680514833335
|
||||
],
|
||||
[
|
||||
-47.3951732595,
|
||||
-22.172646752833334
|
||||
],
|
||||
[
|
||||
-47.39516880516667,
|
||||
-22.1726149155
|
||||
],
|
||||
[
|
||||
-47.39516381233334,
|
||||
-22.172581167166665
|
||||
],
|
||||
[
|
||||
-47.39516315429932,
|
||||
-22.172576693573966
|
||||
],
|
||||
[
|
||||
-47.39516184565584,
|
||||
-22.172567745443878
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {
|
||||
"Id": "5",
|
||||
"Name": "CidadeJardimTerreno2",
|
||||
"Length": 14.80117692191233,
|
||||
"Dist1": 14.558011415731592,
|
||||
"Dist2": 0.0
|
||||
},
|
||||
"geometry": {
|
||||
"id": null,
|
||||
"type": "LineString",
|
||||
"coordinates": [
|
||||
[
|
||||
-47.395147317833334,
|
||||
-22.172566031
|
||||
],
|
||||
[
|
||||
-47.395151503166666,
|
||||
-22.172595452333333
|
||||
],
|
||||
[
|
||||
-47.3951561855,
|
||||
-22.172628011166665
|
||||
],
|
||||
[
|
||||
-47.39516159866667,
|
||||
-22.172663757333332
|
||||
],
|
||||
[
|
||||
-47.39516672716667,
|
||||
-22.172697770833334
|
||||
],
|
||||
[
|
||||
-47.395167397572706,
|
||||
-22.172702242832194
|
||||
],
|
||||
[
|
||||
-47.39516873082615,
|
||||
-22.17271118781009
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
<meta name="viewport" content="width=device-width,
|
||||
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style>
|
||||
#map_273c4f61c3fbbe6e7f2c94d82e1811b9 {
|
||||
#map_68dcaf9dd7545b82e750e9f498ab7095 {
|
||||
position: relative;
|
||||
width: 100.0%;
|
||||
height: 100.0%;
|
||||
|
|
@ -39,16 +39,16 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="folium-map" id="map_273c4f61c3fbbe6e7f2c94d82e1811b9" ></div>
|
||||
<div class="folium-map" id="map_68dcaf9dd7545b82e750e9f498ab7095" ></div>
|
||||
|
||||
</body>
|
||||
<script>
|
||||
|
||||
|
||||
var map_273c4f61c3fbbe6e7f2c94d82e1811b9 = L.map(
|
||||
"map_273c4f61c3fbbe6e7f2c94d82e1811b9",
|
||||
var map_68dcaf9dd7545b82e750e9f498ab7095 = L.map(
|
||||
"map_68dcaf9dd7545b82e750e9f498ab7095",
|
||||
{
|
||||
center: [-22.172625713333332, -47.39520747025],
|
||||
center: [-22.172636164916668, -47.395186322185666],
|
||||
crs: L.CRS.EPSG3857,
|
||||
zoom: 12,
|
||||
zoomControl: true,
|
||||
|
|
@ -60,13 +60,13 @@
|
|||
|
||||
|
||||
|
||||
var tile_layer_fa80a60fdccb28e7661c07bfa0881ec8 = L.tileLayer(
|
||||
var tile_layer_18ed5e620d2365ae2eea37d711c8da92 = L.tileLayer(
|
||||
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
|
||||
);
|
||||
|
||||
|
||||
tile_layer_fa80a60fdccb28e7661c07bfa0881ec8.addTo(map_273c4f61c3fbbe6e7f2c94d82e1811b9);
|
||||
tile_layer_18ed5e620d2365ae2eea37d711c8da92.addTo(map_68dcaf9dd7545b82e750e9f498ab7095);
|
||||
|
||||
|
||||
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
}*/
|
||||
});
|
||||
}
|
||||
function geo_json_35710823a9f19abf47e95c1a9abf984f_onEachFeature(feature, layer) {
|
||||
function geo_json_377712b0416695b2616e159ce6022a2d_onEachFeature(feature, layer) {
|
||||
layer.on({
|
||||
|
||||
click: function(e) {
|
||||
|
|
@ -118,20 +118,20 @@
|
|||
}*/
|
||||
});
|
||||
};
|
||||
var geo_json_35710823a9f19abf47e95c1a9abf984f = L.geoJson(null, {
|
||||
onEachFeature: geo_json_35710823a9f19abf47e95c1a9abf984f_onEachFeature,
|
||||
var geo_json_377712b0416695b2616e159ce6022a2d = L.geoJson(null, {
|
||||
onEachFeature: geo_json_377712b0416695b2616e159ce6022a2d_onEachFeature,
|
||||
|
||||
});
|
||||
|
||||
function geo_json_35710823a9f19abf47e95c1a9abf984f_add (data) {
|
||||
geo_json_35710823a9f19abf47e95c1a9abf984f
|
||||
function geo_json_377712b0416695b2616e159ce6022a2d_add (data) {
|
||||
geo_json_377712b0416695b2616e159ce6022a2d
|
||||
.addData(data);
|
||||
}
|
||||
geo_json_35710823a9f19abf47e95c1a9abf984f_add({"features": [{"geometry": {"coordinates": [[-47.395224896, -22.172530905666665], [-47.39522481466667, -22.172530881166665], [-47.39522486916667, -22.172530858666665], [-47.39522484366667, -22.1725308255], [-47.39522478283333, -22.1725309215], [-47.39522470716667, -22.1725309895], [-47.39522471633333, -22.172530981666668], [-47.3952246845, -22.1725309905], [-47.39522465433333, -22.172531001833335], [-47.39522463833333, -22.1725310205], [-47.39522461533333, -22.1725310215], [-47.39522460133333, -22.1725310395], [-47.3952245865, -22.172531038333332], [-47.39522455666667, -22.172531053333334], [-47.39522452083333, -22.1725310615], [-47.395224496833336, -22.172531070166666], [-47.39522447383333, -22.172531077166667], [-47.39522444566666, -22.172531089166668], [-47.395224442166665, -22.172531103166666], [-47.395224427, -22.172531076333332], [-47.395224394833335, -22.1725310685], [-47.395224381666665, -22.1725311315], [-47.39522437266667, -22.172531105666668], [-47.39522435733333, -22.172531095], [-47.39522438816667, -22.172531347666666], [-47.395225137333334, -22.172534490666667], [-47.395225645, -22.172538111], [-47.39522384633333, -22.172540902666668], [-47.39522103583333, -22.172543275166667], [-47.395217679, -22.17254414], [-47.395214692833335, -22.172546121833335], [-47.395210529, -22.172546959833333], [-47.395206482333336, -22.172548131666666], [-47.395202635833336, -22.172548931], [-47.395198742666665, -22.1725496485], [-47.39519530816667, -22.172551297], [-47.39519308916667, -22.172553379166665], [-47.3951906165, -22.172556357833333], [-47.39518954, -22.172558924333334], [-47.3951892955, -22.172562425333332], [-47.39518933866667, -22.172565753333334], [-47.3951903165, -22.172569415833333], [-47.39519198033334, -22.172572816333332], [-47.395194284666665, -22.172577084833332], [-47.395197333333336, -22.172582304666665], [-47.3951991365, -22.172587995166666], [-47.395201415833334, -22.172594441666668], [-47.39520309266667, -22.172602672666667], [-47.39520430433333, -22.172610736333333], [-47.395205132, -22.172618987833335], [-47.39520572066667, -22.172626966833334], [-47.395206206833336, -22.172634488333333], [-47.39520675033334, -22.1726419035], [-47.39520718066667, -22.172649125166668], [-47.3952078105, -22.172656991166665], [-47.395208609, -22.1726643035], [-47.395209229, -22.1726726965], [-47.39520993916667, -22.1726804585], [-47.39521146566667, -22.172686973], [-47.395212691, -22.1726939085], [-47.3952135945, -22.172699633833332], [-47.3952137895, -22.1727036245], [-47.39521433283333, -22.1727079415], [-47.39521590066666, -22.172710840833332], [-47.395216996833334, -22.17271371083333], [-47.395218383666666, -22.172715863833332], [-47.39521935016667, -22.172718333833334], [-47.395218823, -22.172720601166667], [-47.39521889833333, -22.172720221166667], [-47.395218846666666, -22.172720248], [-47.3952188105, -22.172720256333335], [-47.39521881266667, -22.172720288333334], [-47.395218752333335, -22.1727202475], [-47.395218729166665, -22.172720266333332], [-47.3952186995, -22.172720271833334], [-47.395218683, -22.172720275166668], [-47.39521864566667, -22.172720276333333], [-47.395218627666665, -22.1727202785], [-47.3952186145, -22.172720284], [-47.395218570333334, -22.1727203085], [-47.39521856183333, -22.172720305666665], [-47.3952185305, -22.172720299], [-47.3952184855, -22.172720302666665], [-47.3952184605, -22.172720312166668], [-47.39521843233333, -22.172720307833334], [-47.39521839983333, -22.1727203335], [-47.395218375333336, -22.172720338333335], [-47.395218384, -22.172720347666665], [-47.395218363333335, -22.172720357666666], [-47.39521832183333, -22.172720362666666], [-47.3952182875, -22.172720388833334], [-47.39521821766667, -22.172720461333334], [-47.39521824733333, -22.1727204295], [-47.39521821616667, -22.172720418833332], [-47.39521820466667, -22.1727204255], [-47.395218174, -22.172720434166667]], "id": null, "type": "LineString"}, "id": 0, "properties": {"Dist1": 0.0, "Dist2": 0.0, "Id": "1", "Length": 24.11765894299053, "Name": "28_03_2025_14_52_47"}, "type": "Feature"}], "type": "FeatureCollection"});
|
||||
geo_json_377712b0416695b2616e159ce6022a2d_add({"features": [{"geometry": {"coordinates": [[-47.395205344, -22.172559531333334], [-47.395212610166666, -22.172614638833334], [-47.395219157, -22.172656417833334], [-47.395223544833335, -22.1726892105], [-47.39522414098443, -22.17269369161165], [-47.395225326538004, -22.172702654611555]], "id": null, "type": "LineString"}, "id": 0, "properties": {"Dist1": 14.558011415731592, "Dist2": 0.0, "Id": "1", "Length": 14.558011415731592, "Name": "CidadeJardimTerreno2"}, "type": "Feature"}, {"geometry": {"coordinates": [[-47.39521090233333, -22.172708800833334], [-47.395206943666665, -22.172679811], [-47.395202420666664, -22.1726491015], [-47.395198865666664, -22.172615782833333], [-47.395193255833334, -22.172577132833332], [-47.395192610024395, -22.17257265769541], [-47.395191325698136, -22.172563706509337]], "id": null, "type": "LineString"}, "id": 1, "properties": {"Dist1": 14.558011415731592, "Dist2": 0.0, "Id": "2", "Length": 14.771318274761821, "Name": "CidadeJardimTerreno2"}, "type": "Feature"}, {"geometry": {"coordinates": [[-47.3951762925, -22.172561603], [-47.395180824166665, -22.172591686166665], [-47.395185745333336, -22.172623080166666], [-47.395190433, -22.172656367166667], [-47.395195199, -22.172693641833334], [-47.39519576904436, -22.172698125891035], [-47.39519690267159, -22.172707094716973]], "id": null, "type": "LineString"}, "id": 2, "properties": {"Dist1": 14.558011415731592, "Dist2": 0.0, "Id": "3", "Length": 14.827915524386164, "Name": "CidadeJardimTerreno2"}, "type": "Feature"}, {"geometry": {"coordinates": [[-47.39518293216667, -22.1727127985], [-47.39517819266667, -22.172680514833335], [-47.3951732595, -22.172646752833334], [-47.39516880516667, -22.1726149155], [-47.39516381233334, -22.172581167166665], [-47.39516315429932, -22.172576693573966], [-47.39516184565584, -22.172567745443878]], "id": null, "type": "LineString"}, "id": 3, "properties": {"Dist1": 14.558011415731592, "Dist2": 0.0, "Id": "4", "Length": 14.785159385903514, "Name": "CidadeJardimTerreno2"}, "type": "Feature"}, {"geometry": {"coordinates": [[-47.395147317833334, -22.172566031], [-47.395151503166666, -22.172595452333333], [-47.3951561855, -22.172628011166665], [-47.39516159866667, -22.172663757333332], [-47.39516672716667, -22.172697770833334], [-47.395167397572706, -22.172702242832194], [-47.39516873082615, -22.17271118781009]], "id": null, "type": "LineString"}, "id": 4, "properties": {"Dist1": 14.558011415731592, "Dist2": 0.0, "Id": "5", "Length": 14.80117692191233, "Name": "CidadeJardimTerreno2"}, "type": "Feature"}], "type": "FeatureCollection"});
|
||||
|
||||
|
||||
|
||||
geo_json_35710823a9f19abf47e95c1a9abf984f.addTo(map_273c4f61c3fbbe6e7f2c94d82e1811b9);
|
||||
geo_json_377712b0416695b2616e159ce6022a2d.addTo(map_68dcaf9dd7545b82e750e9f498ab7095);
|
||||
|
||||
</script>
|
||||
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
}
|
||||
trajeto_json_add({"features": []});
|
||||
|
||||
trajeto_json.addTo(map_273c4f61c3fbbe6e7f2c94d82e1811b9);
|
||||
trajeto_json.addTo(map_68dcaf9dd7545b82e750e9f498ab7095);
|
||||
|
||||
function adicionarGeometria(novaGeometria) {
|
||||
trajeto_json.addData(novaGeometria);
|
||||
|
|
@ -210,7 +210,7 @@
|
|||
}
|
||||
trajeto_dinamico_json_add({"features": []});
|
||||
|
||||
trajeto_dinamico_json.addTo(map_273c4f61c3fbbe6e7f2c94d82e1811b9);
|
||||
trajeto_dinamico_json.addTo(map_68dcaf9dd7545b82e750e9f498ab7095);
|
||||
|
||||
function adicionarGeometriaDinamica(novaGeometria) {
|
||||
trajeto_dinamico_json.addData(novaGeometria);
|
||||
|
|
@ -263,9 +263,9 @@
|
|||
|
||||
var marcadorEquipamento = L.marker([0, 0], {
|
||||
icon: customIcon
|
||||
}).addTo(map_273c4f61c3fbbe6e7f2c94d82e1811b9);
|
||||
}).addTo(map_68dcaf9dd7545b82e750e9f498ab7095);
|
||||
|
||||
var marcadorBase = L.marker([0, 0], {}).addTo(map_273c4f61c3fbbe6e7f2c94d82e1811b9);
|
||||
var marcadorBase = L.marker([0, 0], {}).addTo(map_68dcaf9dd7545b82e750e9f498ab7095);
|
||||
var icon = L.AwesomeMarkers.icon(
|
||||
{"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "red", "prefix": "glyphicon"}
|
||||
);
|
||||
|
|
@ -347,7 +347,7 @@
|
|||
}
|
||||
|
||||
if (foco) {
|
||||
map_273c4f61c3fbbe6e7f2c94d82e1811b9.setView(novaPosicao, map_273c4f61c3fbbe6e7f2c94d82e1811b9.getZoom());
|
||||
map_68dcaf9dd7545b82e750e9f498ab7095.setView(novaPosicao, map_68dcaf9dd7545b82e750e9f498ab7095.getZoom());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -364,7 +364,7 @@
|
|||
function atualizarSelecaoRuas(selecionadas) {
|
||||
selecionadas = JSON.parse(selecionadas);
|
||||
RuasSelecionadas = Array.isArray(selecionadas) ? [...selecionadas] : [];
|
||||
geo_json_35710823a9f19abf47e95c1a9abf984f.eachLayer(function (layer) {
|
||||
geo_json_377712b0416695b2616e159ce6022a2d.eachLayer(function (layer) {
|
||||
if (RuasSelecionadas.includes(parseInt(layer.feature.id))) {
|
||||
layer.setStyle({ color: 'blue' });
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
5941701e8325b99f36fff6b9c1588b65d819d36a36bdbfbca35ae4c40535bf7e
|
||||
1ccd04225d048dc265da75465ce916117f9ec7d8ad86c56b4979cd52d202386b
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue