diff --git a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs index a7698e7e4..f06cb93bb 100644 --- a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs +++ b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs @@ -132,10 +132,15 @@ namespace AgroBase.Forms if (_Trajetoria == null) { Variaveis.OperacaoEmAndamento.Mapa.AtualizarRuasSelecionadas(); + AtualizandoTela = false; return; } - if (_Sensoriamento.Trajetoria == null) return; + if (_Sensoriamento.Trajetoria == null) + { + AtualizandoTela = false; + return; + } lblStatus.Text = $"Carro: {_Sensoriamento.Trajetoria.StatusCarro} ({_Sensoriamento.OperadorVisual.Analises.segmentacao.status_corredor})"; lblDirecao.Text = $"Direção: {_Sensoriamento.Trajetoria.DirecaoCaminho}"; diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs index d13609db0..60eb2de39 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs @@ -156,7 +156,7 @@ namespace AgroBase.Models //public List ModulosMandatorios { get; set; } = new List(); //public List ParametrosMandatorios { get; set; } = new List(); - public int TempoIniciarOperacao { get; set; } = 30; + public int TempoIniciarOperacao { get; set; } = 10; public string ID { get; set; } public double tmrLogsInterval { @@ -1517,7 +1517,7 @@ namespace AgroBase.Models Variaveis.OperacaoEmAndamento.DefinirComponentesEmUso(); } - HealthWorkerService.AtualizarDadosOperacao(); + HealthWorkerService.AtualizarDadosOperacao(true); break; case BotoesJoystick.L1: // Inicia o modo simulador if (!Variaveis.OperacaoEmAndamento.Iniciado) @@ -1896,8 +1896,9 @@ namespace AgroBase.Models } string nome = Variaveis.OperacaoEmAndamento.idxLog.ToString(); - - Camera.SaveFrames(new List() { TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao }, nome, Caminho); // TipoFrameCamera.Raw4 + var frames_salvar = new List() { TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao }; + if (Variaveis.OperacaoEmAndamento.Parametros.Controle.RegistrarDadosPosProcessamento) frames_salvar.Add(TipoFrameCamera.Raw4); + Camera.SaveFrames(frames_salvar, nome, Caminho); var cameras_conectadas = JsonConvert.DeserializeObject>(RedisService.Get(CtxKey.DadosCameras)); bool conectada = cameras_conectadas.ContainsKey(Camera?.Id ?? ""); @@ -1920,8 +1921,9 @@ namespace AgroBase.Models } string nome = Variaveis.OperacaoEmAndamento.idxLog.ToString(); - - Camera.SaveFrames(new List() { TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao }, nome, Caminho); // CameraFrameType.Heatmap, CameraFrameType.RadarTopDown + var frames_salvar = new List() { TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao }; + if (Variaveis.OperacaoEmAndamento.Parametros.Controle.RegistrarDadosPosProcessamento) frames_salvar.Add(TipoFrameCamera.Heatmap); + Camera.SaveFrames(frames_salvar, nome, Caminho); var cameras_conectadas = JsonConvert.DeserializeObject>(RedisService.Get(CtxKey.DadosCameras)); bool conectada = cameras_conectadas.ContainsKey(Camera?.Id ?? ""); diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs index bbf9780c7..d0c76d638 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs @@ -39,6 +39,8 @@ namespace AgroBase.Models.Operacoes public bool ImuParadaPorInclinacao { get; set; } public bool FrenagemAutomaticaAoParar { get; set; } + public bool RegistrarDadosPosProcessamento { get; set; } = false; + public int MovVelocidadeSErvasPercent { get; set; } public int MovRpmMax { @@ -64,6 +66,10 @@ namespace AgroBase.Models.Operacoes public double AtuAlturaAreaPulverizacao { get; set; } public double AtuPercentualErvasBicoOn { get; set; } public double AtuPercentualErvasBicoOff { get; set; } + + public bool MpcMatrizCusto { get; set; } = true; + public double MpcHorizonteMin { get; set; } = 1.0; + public double MpcHorizonteMax { get; set; } = 2.0; } public class OperacaoParametrosDadosModel diff --git a/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs b/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs index e64f45e90..51da07295 100644 --- a/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs +++ b/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs @@ -21,6 +21,7 @@ namespace AgroBase.Models #region PARAMETROS + public double AnguloAberturaCurva { get; set; } = 45; // Angulo usado para deslocar o ponto de curva public double DistanciaProjecaoRua { get; set; } = 1.5; // Distancia para projetar o primeiro ponto para fora do corredor public static double DistanciaEntrePontos { get; set; } = 0.8; // Distancia entre os pontos dentro do corredor public static double DistanciaEntrePontosCurva { get; set; } = 0.25; // Distancia entre os pontos durante a curva entre corredores @@ -430,11 +431,12 @@ namespace AgroBase.Models { if ((RetornandoBase && CorredorAtual.Dentro) || (!RetornandoBase && Variaveis.OperacaoEmAndamento.StatusAtual == StatusOperacao.EmAndamento)) { + PontoAtual.AtualizarPropriedades(); if (!CorredorAtual.Dentro && ProximoPonto.DistanciaAtual > DistanciaManobraEntreRuas) { StatusAtual = StatusCarroMapa.Direcionando; } - else if (!CorredorAtual.Dentro && (PontoAtual.PontoBorda || PontoAtual.PontoLigacao || ProximoPonto.Tipo == TipoPontoRua.LigacaoEntrada || PontoAtual.Tipo == TipoPontoRua.CruvaEntreCorredores)) + else if (!CorredorAtual.Dentro && (PontoAtual.PontoBorda || PontoAtual.PontoLigacao || PontoAtual.Tipo == TipoPontoRua.CruvaEntreCorredores || PontoAtual.Tipo == TipoPontoRua.Desvio || ProximoPonto.Tipo == TipoPontoRua.LigacaoEntrada)) { StatusAtual = StatusCarroMapa.Manobrando; } @@ -772,8 +774,9 @@ namespace AgroBase.Models private void VerificaFimCorredorSegmentacao() { if (CorredorAtual == null) return; + if (CorredorAtual.DadosVisuais.JaAntecipado) return; - bool modoSimulador = true && Variaveis.OperacaoEmAndamento.Simulando; + bool modoSimulador = false && Variaveis.OperacaoEmAndamento.Simulando; // Limiar de "margem" para considerar proximidade do fim double limiarDistanciaMargem = DistanciaErroMapaPlantacao > -1 ? DistanciaErroMapaPlantacao : 5.0; @@ -880,11 +883,11 @@ namespace AgroBase.Models bool podeUsarSegmentacao = modoSimulador || (dadoFresco && dv.CorredorConfirmado); - bool fimAntecipado = podeUsarSegmentacao && pertoDoFim && foraDoCorredorAgora && foraContinuoSuficiente; + CorredorAtual.DadosVisuais.JaAntecipado = podeUsarSegmentacao && pertoDoFim && foraDoCorredorAgora && foraContinuoSuficiente; Console.WriteLine($"podeUsarSegmentacao: {podeUsarSegmentacao}, pertoDoFim: {pertoDoFim}, foraDoCorredorAgora: {foraDoCorredorAgora}, foraContinuoSuficiente: {foraContinuoSuficiente}"); - if (fimAntecipado) + if (CorredorAtual.DadosVisuais.JaAntecipado) { List pontosRemover = CorredorAtual.Pontos.Where(x => !x.Visitado).ToList(); pontosRemover.ForEach(x => x.Visitado = true); @@ -897,9 +900,9 @@ namespace AgroBase.Models _TrajetoriaFixa.Remove(ponto); } + var pls = CorredorAtual.Pontos[CorredorAtual.Pontos.Count - 1]; if (CorredorAtual.Pontos.Count >= 2) { - var pls = CorredorAtual.Pontos[CorredorAtual.Pontos.Count - 1]; var pbs = CorredorAtual.Pontos[CorredorAtual.Pontos.Count - 2]; pls.AlterarTipo(TipoPontoRua.LigacaoSaida); pbs.AlterarTipo(TipoPontoRua.BordaSaida); @@ -907,17 +910,29 @@ namespace AgroBase.Models _TrajetoriaFixa.FirstOrDefault(x => ReferenceEquals(x, pbs))?.AlterarTipo(pbs.Tipo); } - double anguloControle = CorredorAtual.idxRuaDireita > CorredorAtual.idxRuaEsquerda ? -Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo : Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo; - double anguloDesvio = PontoAtual.Orientacao + anguloControle; - var pontoDesvio = GPSUtils.GerarPontoDeslocado(PontoAtual.Posicao, anguloDesvio, 1.5); - IncluirDesvioNaTrajetoria(new List() { pontoDesvio }, PontoAtual.idxPonto); - - // Garante que os primeiros pontos do corredor atual estão como visitados + // acha o ponto mais próximo do corredor seguinte var pc = _Corredores[CorredorAtual.Idx + 1]; - - // acha o ponto mais próximo (GPSModel pp, double distanciaAtual) = GPSUtils.CalcularPontoMaisProximoTrajetoria(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, pc.Pontos.Select(x => x.Posicao).ToList()); var _pp = pc.Pontos.FirstOrDefault(x => Math.Abs(x.Posicao.Latitude - pp.Latitude) < 1e-8 && Math.Abs(x.Posicao.Longitude - pp.Longitude) < 1e-8); + + double anguloControle = CorredorAtual.idxRuaDireita > CorredorAtual.idxRuaEsquerda ? -AnguloAberturaCurva : AnguloAberturaCurva; + double anguloDesvio = PontoAtual.Orientacao + anguloControle; + double fd = FuncoesMatematicas.Map(Variaveis.OperacaoEmAndamento.Sensoriamento.Controle.PercentualVelocidadeSP, 10, 100, 0.7, 2.5); + + var pontoDesvio = GPSUtils.GerarPontoDeslocado(pls.Posicao, anguloDesvio, DistanciaProjecaoRua * fd); + + + double _FatorLarguraCorredor = CorredorAtual.Largura / LarguraCorredorPadrao; + var proximoPontoProximoCorredor = pc.Pontos[_pp.idxPontoCorredor].Posicao; + List CurvaConexao = CriarCurvaEntrePontos(pontoDesvio, proximoPontoProximoCorredor, DistanciaProjecaoRua * 1.5, pls.Orientacao, 6, false); + CurvaConexao.Insert(0, pontoDesvio); + + + IncluirDesvioNaTrajetoria(CurvaConexao, pls.idxPonto, pls.LarguraCorredor * 0.8); + + + + // Garante que os primeiros pontos do corredor atual estão como visitados if (_pp != null) { int idxProx = _pp.idxPontoCorredor; @@ -946,8 +961,8 @@ namespace AgroBase.Models ReindexarTrajetoriaFixa(); - RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false)); Variaveis.OperacaoEmAndamento.Sensoriamento.AtualizarDados(); + HealthWorkerService.AtualizarDadosOperacao(true); } } } @@ -1350,7 +1365,7 @@ namespace AgroBase.Models int idxEsq = 0; int idxDir = 0; - double anguloAcrescentar = direcaoAtual == DirecaoCarroRua.Ida ? 45 : -45; + double anguloAcrescentar = direcaoAtual == DirecaoCarroRua.Ida ? AnguloAberturaCurva : -AnguloAberturaCurva; for (int idx = 0; idx < Corredores.Count(); idx++) { @@ -1416,13 +1431,10 @@ namespace AgroBase.Models if (distanciaMinima && false) { int pontosAdicionr = Convert.ToInt32(CorredoresLarguras[idx] / (DistanciaEntrePontosCurva * _FatorLarguraCorredor)); - var _penultimoPonto = _trajetoriaFixa[_trajetoriaFixa.Count() - 2].Posicao; double anguloProjecao = GPSUtils.CalcularOrientacao(Corredores[idx - 1].First(), Corredores[idx - 1].Last()); GPSModel _ultimoPonto = GPSUtils.ProjetarPontoDeslocado(Corredores[idx - 1].Last(), DistanciaProjecaoRua, anguloProjecao); - - GPSModel P0 = CalcularPontoControle(_penultimoPonto, _ultimoPonto, PrimeiroPonto, DistanciaProjecaoRua * 2.0); - List CurvaConexao = GerarCurvaConexao(ultimoPontoTrajetoria.Posicao, PrimeiroPonto, P0, pontosAdicionr); + List CurvaConexao = CriarCurvaEntrePontos(ultimoPontoTrajetoria.Posicao, PrimeiroPonto, DistanciaProjecaoRua * 2.0, anguloProjecao, pontosAdicionr, false); for (int i = 0; i < CurvaConexao.Count; i++) { @@ -1556,6 +1568,15 @@ namespace AgroBase.Models RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false)); } + private List CriarCurvaEntrePontos(GPSModel _p1, GPSModel _p2, double distanciaCurva, double anguloCurva, int qtdPontos, bool manterPontos) + { + GPSModel P0 = CalcularPontoControle(anguloCurva, _p1, _p2, distanciaCurva); + List curva = GerarCurvaConexao(_p1, _p2, P0, qtdPontos); + if (manterPontos) curva.Insert(0, _p1); + else curva.RemoveAt(curva.Count - 1); + return curva; + } + private (int, int) AtualizaIndiceRuaLateralCorredor(int i, int idxDir, int incDir, int incEsq) { bool par = (i % 2 == 0); @@ -1575,9 +1596,8 @@ namespace AgroBase.Models return (incDir, incEsq); } - public static GPSModel CalcularPontoControle(GPSModel penultimoPontoRuaAtual, GPSModel ultimoPontoRuaAtual, GPSModel primeiroPontoProximaRua, double distancia) + public static GPSModel CalcularPontoControle(double anguloCurva, GPSModel ultimoPontoRuaAtual, GPSModel primeiroPontoProximaRua, double distancia) { - double anguloCurva = GPSUtils.CalcularOrientacao(penultimoPontoRuaAtual, ultimoPontoRuaAtual); double angulo = GPSUtils.CalcularOrientacao(ultimoPontoRuaAtual, primeiroPontoProximaRua); // Calcular a diferença de ângulo corretamente no espaço de 360 graus @@ -2306,7 +2326,7 @@ namespace AgroBase.Models - private void IncluirDesvioNaTrajetoria(List pontos, int idxPontoApartir) + private void IncluirDesvioNaTrajetoria(List pontos, int idxPontoApartir, double larguraCorredor) { if (pontos == null || pontos.Count == 0) return; @@ -2331,7 +2351,7 @@ namespace AgroBase.Models idxCorredor = pa.idxCorredor, Posicao = pontoGps, Direcao = pa.Direcao, - LarguraCorredor = pa.LarguraCorredor, + LarguraCorredor = larguraCorredor, Orientacao = GPSUtils.CalcularOrientacao(pontoGps, pa.Posicao), Visitado = false }; @@ -2472,6 +2492,7 @@ namespace AgroBase.Models public class DadosVisuaisCorredor { + public bool JaAntecipado { get; set; } = false; // Quanto já andou DENTRO do corredor (EntrandoRua, CaminhandoRua, SaindoRua) public double TempoDentroRuaTotal { get; set; } = 0; public double DistanciaDentroRuaTotal { get; set; } = 0; @@ -2539,6 +2560,8 @@ namespace AgroBase.Models public void AlterarTipo(Enums.TipoPontoRua novo) { Tipo = novo; + PontoBorda = Tipo == Enums.TipoPontoRua.BordaEntrada || Tipo == Enums.TipoPontoRua.BordaSaida; + PontoLigacao = Tipo == Enums.TipoPontoRua.LigacaoEntrada || Tipo == Enums.TipoPontoRua.LigacaoSaida; } public void AtualizarPropriedades() diff --git a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs index e8d0deba9..57855143c 100644 --- a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs @@ -195,10 +195,13 @@ namespace AgroBase.Services.Operadores ); } - public static void AtualizarDadosOperacao() + public static void AtualizarDadosOperacao(bool forcar = false) { - if (AtualizandoRedis) + if (AtualizandoRedis && !forcar) return; + + while (AtualizandoRedis && forcar) {} + AtualizandoRedis = true; AtualizarDadosEquipamento(); @@ -221,6 +224,7 @@ namespace AgroBase.Services.Operadores ("modulos_mandatorios", _Parametros.ModulosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()), ("modulos_opcionais", _Parametros.ModulosMandatorios.Where(x => !x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()), ("parametros_mandatorios", _Parametros.ParametrosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Parametro).ToArray()), + ("ponto_mapa_ref", Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?.Select(p => new double[] { p.Posicao.Latitude, p.Posicao.Longitude }).FirstOrDefault()), ("Mov", new { percent_vel_max = pControle.MovVelocidadeSErvasPercent, @@ -243,15 +247,14 @@ namespace AgroBase.Services.Operadores distanciaMargem = p.LarguraCorredor * 0.8 }) .ToList(), - horizonte = 2.0, - horizonte_min = 1.2, - horizonte_max = 2.8, - horizonte_parado = 1.2, + horizonte_min = pControle.MpcHorizonteMin, + horizonte_max = pControle.MpcHorizonteMax, angulo_max_graus = pControle.DirAnguloMaximo, - velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent), - velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent), + velocidade_min = Math.Round(FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent), 4), + velocidade_max = Math.Round(FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent), 4), tempo_entre_comandos = (Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == Enums.T_Code.Dir)?.DelayEnvioComando ?? 500) / 1000.0, - passos_atraso = 1 + passos_atraso = 1, + usa_matriz_custo = pControle.MpcMatrizCusto } } ), @@ -285,6 +288,8 @@ namespace AgroBase.Services.Operadores RedisService.Publish(CmdKey.HealthWorkerRx, JsonConvert.SerializeObject(comando)); } + //Console.WriteLine("Dados de operacao atualizados com sucesso!"); + AtualizandoRedis = false; } @@ -298,7 +303,9 @@ namespace AgroBase.Services.Operadores ("direcional_automatico", pControle.DirecionalAutomatico), ("frenagem_automatica", pControle.FrenagemAutomaticaAoParar), ("oak_parada_por_bloqueio", pControle.OakParadaPorObstaculo), - ("imu_parada_por_inclinacao", pControle.ImuParadaPorInclinacao) + ("imu_parada_por_inclinacao", pControle.ImuParadaPorInclinacao), + + ("registrar_dados_pos_processamento", pControle.RegistrarDadosPosProcessamento) ); } diff --git a/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs b/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs index 3552f100f..0f1f23a78 100644 --- a/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs +++ b/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs @@ -132,7 +132,7 @@ namespace AgroBase.Services.Operadores TempoDesconectado = 0; if (!Variaveis.OperacaoEmAndamento.OperacaoConfigurada) { - HealthWorkerService.AtualizarDadosOperacao(); + HealthWorkerService.AtualizarDadosOperacao(true); } } } diff --git a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par index 646b360fc..e2915ec2c 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par +++ b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par @@ -1 +1 @@ -{"UltimoTickRegistrador":"0001-01-01T00:00:00","tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":250,"IntervalHz":4.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mvd","TimeTick":"00:00:00"},"tmrRegistradorMOV":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mov","TimeTick":"00:00:00"},"tmrRegistradorDIR":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":500,"IntervalHz":2.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Dir","TimeTick":"00:00:00"},"Dispositivo":109,"_EnderecoCAN_Tx":0,"_EnderecoCAN_Rx":0,"ConexaoAtiva":false,"DirPronto":false,"MovPronto":false,"_TaxaAmostragem":250,"DistanciaPercorridaOperacao":0.0,"TempoEmAtividade":0.0,"DistanciaPercorridaTotal":0.0,"DistanciaPercorridaParcial":0.0,"VelocidadeMedia":0.0,"DiametroRoda":0.355,"ReducaoMotorBLDC":5.0,"RPM_Max_MotorBLDC":500.0,"IP_Mov":"192.168.105.10","IP_Dir":"192.168.105.11","Modulos":[{"Modulo_ID":"ET","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":5,"_EnderecoCAN_Rx":5,"heartBeatValue":0,"Mod_ID":"ET","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"ET","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":0,"UltimoEnvio":"2026-02-26T15:12:11.7521527-03:00","DelayEnvio":500,"Servo":{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":1,"_EnderecoCAN_Rx":1,"Mod_ID":"ET","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"EF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":7,"_EnderecoCAN_Rx":7,"heartBeatValue":0,"Mod_ID":"EF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"EF","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":3,"_EnderecoCAN_Rx":3,"Mod_ID":"EF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":98.35,"UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":-183.25,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":3,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DT","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":6,"_EnderecoCAN_Rx":6,"heartBeatValue":0,"Mod_ID":"DT","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DT","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":180,"UltimoEnvio":"2026-02-26T16:00:21.332118-03:00","DelayEnvio":500,"Servo":{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":true}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":2,"_EnderecoCAN_Rx":2,"Mod_ID":"DT","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":8,"_EnderecoCAN_Rx":8,"heartBeatValue":0,"Mod_ID":"DF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DF","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":4,"_EnderecoCAN_Rx":4,"Mod_ID":"DF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":3,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}}]} \ No newline at end of file +{"UltimoTickRegistrador":"0001-01-01T00:00:00","tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":250,"IntervalHz":4.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mvd","TimeTick":"00:00:00"},"tmrRegistradorMOV":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mov","TimeTick":"00:00:00"},"tmrRegistradorDIR":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":500,"IntervalHz":2.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Dir","TimeTick":"00:00:00"},"Dispositivo":109,"_EnderecoCAN_Tx":0,"_EnderecoCAN_Rx":0,"ConexaoAtiva":false,"DirPronto":false,"MovPronto":false,"_TaxaAmostragem":250,"DistanciaPercorridaOperacao":0.0,"TempoEmAtividade":0.0,"DistanciaPercorridaTotal":0.0,"DistanciaPercorridaParcial":0.0,"VelocidadeMedia":0.0,"DiametroRoda":0.355,"ReducaoMotorBLDC":5.0,"RPM_Max_MotorBLDC":500.0,"IP_Mov":"192.168.105.10","IP_Dir":"192.168.105.11","Modulos":[{"Modulo_ID":"ET","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":5,"_EnderecoCAN_Rx":5,"heartBeatValue":0,"Mod_ID":"ET","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":0,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"ET","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":0,"UltimoEnvio":"2026-02-27T16:02:44.8030962-03:00","DelayEnvio":500,"Servo":{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":1,"_EnderecoCAN_Rx":1,"Mod_ID":"ET","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"EF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":7,"_EnderecoCAN_Rx":7,"heartBeatValue":0,"Mod_ID":"EF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":0,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"EF","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":3,"_EnderecoCAN_Rx":3,"Mod_ID":"EF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":98.35,"UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":-183.25,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DT","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":6,"_EnderecoCAN_Rx":6,"heartBeatValue":0,"Mod_ID":"DT","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":0,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DT","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":180,"UltimoEnvio":"2026-02-27T16:04:17.0954522-03:00","DelayEnvio":500,"Servo":{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":true}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":2,"_EnderecoCAN_Rx":2,"Mod_ID":"DT","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":8,"_EnderecoCAN_Rx":8,"heartBeatValue":0,"Mod_ID":"DF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":0,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DF","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":4,"_EnderecoCAN_Rx":4,"Mod_ID":"DF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}}]} \ No newline at end of file diff --git a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par index ad3ef5feb..864ede3b1 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par +++ b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par @@ -1 +1 @@ -{"ContadorCarga":{"TempoEstimadoMinutos":0.0,"Iniciado":false,"CargaAtualAmp":20.0,"_Consumido":0.0,"ConsumidoAmp":0.0,"PercentualAtual":100.0,"PercentualConsumido":0.0,"PercentualBateria":0.0,"EnergiaConsumida_Wh":0.0,"_dt":0.0,"CorrenteInstantanea":0.0,"TensaoInstantanea":0.0,"PotenciaInstantanea":0.0,"WhRestante":840.0,"WhPorMetro":0.0,"WhPorMetroBase":0.1167,"WhPorMetroHistorico":0.0,"WhPorMetroReferencia":0.1167,"DistanciaMaximaTeorica_m":0.0,"DistanciaMaximaSegura_m":0.0,"DistanciaEstimadaRestante_m":0.0,"MargemSegurancaAutonomia":0.3},"CoolerControl":{"TempOn":55.0,"TempTurbo":65.0,"TempCritical":75.0,"Histerese":1.5,"MinOnTime":"00:00:30","MinOffTime":"00:00:30","AlphaFiltro":0.2,"ModoAtual":0,"CoolerEntradaEstado":0,"CoolerSaidaEstado":0,"CoolerEntradaLeitura":0,"CoolerSaidaLeitura":0,"TemperaturaFiltrada":31.881600000000006,"UltimaMudancaModo":"0001-01-01T00:00:00","AlertaTemperaturaCritica":false},"tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"SensoriamentoModel.IniciarRegistrador","Id":"tmrRegistrador_Sen","TimeTick":"00:00:00"},"Dispositivo":102,"Modulo_ID":"Sen","_EnderecoCAN_Tx":17,"_EnderecoCAN_Rx":17,"_TaxaAmostragem":1000,"FrequenciaBase":1.0,"RequisitarDados":true,"Conectado":false,"ConexaoAtiva":false,"DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Dispositivo":0,"Versao":0,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"UltimoComandoRespondido":"0001-01-01T00:00:00","Sensores":null,"Sinaleiros":null,"Reles":null,"Servos":null},"Sensores":[{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TBAT","ID_Num":5,"Descricao":"Temperatura da bateria","Componente":4,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"AB3V","ID_Num":11,"Descricao":"Corrente no Barramento 3V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"5","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":3.0,"maximo":3.4,"nominal":3.3,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":500.0,"nominal":100.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB5V","ID_Num":12,"Descricao":"Corrente no Barramento 5V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":4.9,"maximo":5.2,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":1000.0,"nominal":300.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB7V2","ID_Num":13,"Descricao":"Corrente no Barramento 7,2V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":7.0,"maximo":7.4,"nominal":7.2,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":0.0,"maximo":3000.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB12V","ID_Num":14,"Descricao":"Corrente no Barramento 12V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":11.5,"maximo":12.5,"nominal":12.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":10000.0,"nominal":500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB19V","ID_Num":15,"Descricao":"Corrente no Barramento 19V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":18.8,"maximo":19.2,"nominal":19.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":500.0,"maximo":4000.0,"nominal":1500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB24V","ID_Num":16,"Descricao":"Corrente no Barramento 24V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"6","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":23.8,"maximo":24.3,"nominal":24.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":100.0,"maximo":20000.0,"nominal":700.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB36V","ID_Num":17,"Descricao":"Corrente no Barramento 36V","Componente":6,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"7","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":31.0,"maximo":42.5,"nominal":37.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":200.0,"maximo":75000.0,"nominal":2500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":35.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"LUZABT","ID_Num":31,"Descricao":"Luminosidade Ambiente","Componente":30,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x29","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":55,"posicao":2,"indice":0,"minimo":50.0,"maximo":80000.0,"nominal":10000.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"Lux"}]},{"ID":"IUVABT","ID_Num":32,"Descricao":"Indice de radiacao UV Ambiente","Componente":31,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[51],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":51,"posicao":2,"indice":1,"minimo":0.0,"maximo":11.0,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"IUV"}]},{"ID":"MQ2","ID_Num":33,"Descricao":"Gas e Fumaca","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":600.0,"nominal":50.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"MQ7","ID_Num":34,"Descricao":"Monoxido de carbono","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":400.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"QLDABT","ID_Num":35,"Descricao":"Qualidade do ar","Componente":32,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":57,"posicao":2,"indice":0,"minimo":0.0,"maximo":1000.0,"nominal":150.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPB"},{"funcao":58,"posicao":2,"indice":1,"minimo":400.0,"maximo":2000.0,"nominal":600.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"},{"funcao":59,"posicao":2,"indice":2,"minimo":1.0,"maximo":3.0,"nominal":1.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"AQI"},{"funcao":54,"posicao":3,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":3,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"SHTABT","ID_Num":36,"Descricao":"Temperatura e Umidade Ambiente","Componente":29,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x44","QtdBytes":1,"Escalar":false,"Enviar":false},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":2,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"CHVABT","ID_Num":37,"Descricao":"Chuva","Componente":33,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[52],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":52,"posicao":2,"indice":1,"minimo":0.0,"maximo":100.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]}],"Sinaleiros":[{"ID":"LEDMN","ID_Num":21,"Descricao":"Sinaleiro indicação de modo Manual ativo","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":99,"statusOperacao":null,"statusLED":0,"QtdPiscadas":0,"TempoMs":0,"PausaMs":0},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0},{"ID":"LEDAT","ID_Num":22,"Descricao":"Sinaleiro indicação de modo Automático ativo","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":99,"statusOperacao":null,"statusLED":1,"QtdPiscadas":0,"TempoMs":0,"PausaMs":0},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0},{"ID":"LEDOP","ID_Num":23,"Descricao":"Sinaleiro indicação do status da operação ativa","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":1,"statusOperacao":1,"statusLED":2,"QtdPiscadas":2,"TempoMs":800,"PausaMs":2000},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0}],"Reles":[{"ID":"RLCIN","ID_Num":81,"Descricao":"Rele Cooler Entrada","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0},{"ID":"RLCOUT","ID_Num":82,"Descricao":"Rele Cooler Saida","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0}],"Servos":[{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]}],"CameraCaminho":{"Dispositivo":117,"Index":0,"Id":"14442C10C143E2D600","Name":"OAK-D Lite","Description":"(0) OAK-D Lite","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1.1","Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}},"CamerasSolo":[{"Dispositivo":112,"Index":0,"Id":"LT00B00001","Name":"GAL5000-60ucNIR","Description":"(0) GAL5000-60ucNIR","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1005","Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}}],"ConfiguracaoSensorUltrassom":{"Configuracao":0,"Sensores":[{"ID":1,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":2,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":3,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":4,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false}],"_paradaFrontal":false,"_paradaTraseira":false,"_paradaEsquerda":false,"_paradaDireita":false,"DesvioNecessario":false,"ParadaNecessaria":false,"DirecoesObstaculos":[],"DirecaoDesvio":1},"loRaService":{"ID":"LoRa","ID_Num":251,"Componente":26,"Conectado":false,"Configurado":false,"Iniciado":false,"FrequenciaEnvioDadosBase":0.2,"TempoEnvioDadosBase":5000.0,"UltimoRxDados":0.0,"_ultimoRxDados":"0001-01-01T00:00:00","UltimoTxDados":0.0,"_ultimoTxDados":"0001-01-01T00:00:00","ParametrosSet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":192,"power":0,"packetSizeAndPower":192,"tranMode":64,"worCycle":3,"tranModeAndWorCycle":67,"channelRssi":0,"lbt":0,"packetRssi":0,"address":2,"channel":65,"key":0},"ParametrosGet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":0,"airRate":0,"baudAndAirRate":0,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":0,"worCycle":0,"tranModeAndWorCycle":0,"channelRssi":0,"lbt":0,"packetRssi":0,"address":0,"channel":0,"key":0},"Funcoes":[14,47,48,49,3,2],"MensagensRecebidasAvulsas":[]},"LoRaParametrosBase":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":64,"worCycle":7,"tranModeAndWorCycle":71,"channelRssi":0,"lbt":0,"packetRssi":0,"address":1,"channel":23,"key":0}} \ No newline at end of file +{"ContadorCarga":{"TempoEstimadoMinutos":0.0,"Iniciado":false,"CargaAtualAmp":20.0,"_Consumido":0.0,"ConsumidoAmp":0.0,"PercentualAtual":100.0,"PercentualConsumido":0.0,"PercentualBateria":0.0,"EnergiaConsumida_Wh":0.0,"_dt":0.0,"CorrenteInstantanea":0.0,"TensaoInstantanea":0.0,"PotenciaInstantanea":0.0,"WhRestante":840.0,"WhPorMetro":0.0,"WhPorMetroBase":0.1167,"WhPorMetroHistorico":0.0,"WhPorMetroReferencia":0.1167,"DistanciaMaximaTeorica_m":0.0,"DistanciaMaximaSegura_m":0.0,"DistanciaEstimadaRestante_m":0.0,"MargemSegurancaAutonomia":0.3},"CoolerControl":{"TempOn":55.0,"TempTurbo":65.0,"TempCritical":75.0,"Histerese":1.5,"MinOnTime":"00:00:30","MinOffTime":"00:00:30","AlphaFiltro":0.2,"ModoAtual":0,"CoolerEntradaEstado":0,"CoolerSaidaEstado":0,"CoolerEntradaLeitura":0,"CoolerSaidaLeitura":0,"TemperaturaFiltrada":58.027996976617871,"UltimaMudancaModo":"2026-02-27T16:04:16.4316786-03:00","AlertaTemperaturaCritica":false},"tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"SensoriamentoModel.IniciarRegistrador","Id":"tmrRegistrador_Sen","TimeTick":"00:00:00"},"Dispositivo":102,"Modulo_ID":"Sen","_EnderecoCAN_Tx":17,"_EnderecoCAN_Rx":17,"_TaxaAmostragem":1000,"FrequenciaBase":1.0,"RequisitarDados":true,"Conectado":false,"ConexaoAtiva":false,"DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Dispositivo":0,"Versao":0,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"UltimoComandoRespondido":"0001-01-01T00:00:00","Sensores":null,"Sinaleiros":null,"Reles":null,"Servos":null},"Sensores":[{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TBAT","ID_Num":5,"Descricao":"Temperatura da bateria","Componente":4,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"AB3V","ID_Num":11,"Descricao":"Corrente no Barramento 3V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"5","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":3.0,"maximo":3.4,"nominal":3.3,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":500.0,"nominal":100.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB5V","ID_Num":12,"Descricao":"Corrente no Barramento 5V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":4.9,"maximo":5.2,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":1000.0,"nominal":300.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB7V2","ID_Num":13,"Descricao":"Corrente no Barramento 7,2V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":7.0,"maximo":7.4,"nominal":7.2,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":0.0,"maximo":3000.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB12V","ID_Num":14,"Descricao":"Corrente no Barramento 12V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":11.5,"maximo":12.5,"nominal":12.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":10000.0,"nominal":500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB19V","ID_Num":15,"Descricao":"Corrente no Barramento 19V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":18.8,"maximo":19.2,"nominal":19.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":500.0,"maximo":4000.0,"nominal":1500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB24V","ID_Num":16,"Descricao":"Corrente no Barramento 24V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"6","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":23.8,"maximo":24.3,"nominal":24.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":100.0,"maximo":20000.0,"nominal":700.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB36V","ID_Num":17,"Descricao":"Corrente no Barramento 36V","Componente":6,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"7","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":31.0,"maximo":42.5,"nominal":37.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":200.0,"maximo":75000.0,"nominal":2500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":35.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"LUZABT","ID_Num":31,"Descricao":"Luminosidade Ambiente","Componente":30,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x29","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":55,"posicao":2,"indice":0,"minimo":50.0,"maximo":80000.0,"nominal":10000.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"Lux"}]},{"ID":"IUVABT","ID_Num":32,"Descricao":"Indice de radiacao UV Ambiente","Componente":31,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[51],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":51,"posicao":2,"indice":1,"minimo":0.0,"maximo":11.0,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"IUV"}]},{"ID":"MQ2","ID_Num":33,"Descricao":"Gas e Fumaca","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":600.0,"nominal":50.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"MQ7","ID_Num":34,"Descricao":"Monoxido de carbono","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":400.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"QLDABT","ID_Num":35,"Descricao":"Qualidade do ar","Componente":32,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":57,"posicao":2,"indice":0,"minimo":0.0,"maximo":1000.0,"nominal":150.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPB"},{"funcao":58,"posicao":2,"indice":1,"minimo":400.0,"maximo":2000.0,"nominal":600.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"},{"funcao":59,"posicao":2,"indice":2,"minimo":1.0,"maximo":3.0,"nominal":1.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"AQI"},{"funcao":54,"posicao":3,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":3,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"SHTABT","ID_Num":36,"Descricao":"Temperatura e Umidade Ambiente","Componente":29,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x44","QtdBytes":1,"Escalar":false,"Enviar":false},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":2,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"CHVABT","ID_Num":37,"Descricao":"Chuva","Componente":33,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[52],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":52,"posicao":2,"indice":1,"minimo":0.0,"maximo":100.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]}],"Sinaleiros":[{"ID":"LEDMN","ID_Num":21,"Descricao":"Sinaleiro indicação de modo Manual ativo","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":99,"statusOperacao":null,"statusLED":0,"QtdPiscadas":0,"TempoMs":0,"PausaMs":0},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0},{"ID":"LEDAT","ID_Num":22,"Descricao":"Sinaleiro indicação de modo Automático ativo","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":99,"statusOperacao":null,"statusLED":1,"QtdPiscadas":0,"TempoMs":0,"PausaMs":0},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0},{"ID":"LEDOP","ID_Num":23,"Descricao":"Sinaleiro indicação do status da operação ativa","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":1,"statusOperacao":1,"statusLED":2,"QtdPiscadas":2,"TempoMs":800,"PausaMs":2000},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0}],"Reles":[{"ID":"RLCIN","ID_Num":81,"Descricao":"Rele Cooler Entrada","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0},{"ID":"RLCOUT","ID_Num":82,"Descricao":"Rele Cooler Saida","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0}],"Servos":[{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]}],"CameraCaminho":{"Dispositivo":117,"Index":0,"Id":"14442C10C143E2D600","Name":"OAK-D Lite","Description":"(0) OAK-D Lite","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1.1","Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}},"CamerasSolo":[{"Dispositivo":112,"Index":0,"Id":"LT00B00001","Name":"GAL5000-60ucNIR","Description":"(0) GAL5000-60ucNIR","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1005","Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}}],"ConfiguracaoSensorUltrassom":{"Configuracao":0,"Sensores":[{"ID":1,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":2,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":3,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":4,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false}],"_paradaFrontal":false,"_paradaTraseira":false,"_paradaEsquerda":false,"_paradaDireita":false,"DesvioNecessario":false,"ParadaNecessaria":false,"DirecoesObstaculos":[],"DirecaoDesvio":1},"loRaService":{"ID":"LoRa","ID_Num":251,"Componente":26,"Conectado":false,"Configurado":false,"Iniciado":false,"FrequenciaEnvioDadosBase":0.2,"TempoEnvioDadosBase":5000.0,"UltimoRxDados":0.0,"_ultimoRxDados":"0001-01-01T00:00:00","UltimoTxDados":0.0,"_ultimoTxDados":"0001-01-01T00:00:00","ParametrosSet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":192,"power":0,"packetSizeAndPower":192,"tranMode":64,"worCycle":3,"tranModeAndWorCycle":67,"channelRssi":0,"lbt":0,"packetRssi":0,"address":2,"channel":65,"key":0},"ParametrosGet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":0,"airRate":0,"baudAndAirRate":0,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":0,"worCycle":0,"tranModeAndWorCycle":0,"channelRssi":0,"lbt":0,"packetRssi":0,"address":0,"channel":0,"key":0},"Funcoes":[14,47,48,49,3,2],"MensagensRecebidasAvulsas":[]},"LoRaParametrosBase":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":64,"worCycle":7,"tranModeAndWorCycle":71,"channelRssi":0,"lbt":0,"packetRssi":0,"address":1,"channel":23,"key":0}} \ No newline at end of file diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py index 7833599af..ba7dc09fb 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py @@ -83,7 +83,10 @@ def main(): acao = HealthWorkerCommandType(dados.get("cmd", 0)) if acao == HealthWorkerCommandType.AtualizarPontosMapa: - ContextoGlobalRedis._atualizar_pontos_mapa() + try: + ContextoGlobalRedis._atualizar_pontos_mapa() + except Exception as e: + mostrar_log(f"Erro ao atualizar pontos do mapa: {e}") mostrar_log("Dados de mapa da Operacao atualizados com sucesso!") def inicializar(): diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/main.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/main.py index 36c223abb..9ca03fd10 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/main.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/main.py @@ -10,7 +10,6 @@ def main(): from manager_worker.gerenciador import ManagerWorker from manager_worker.config import mostrar_log from shared.enums import ManagerWorkerCommandType - from manager_worker.modulos.mpc import inicializar as iniciar_mpc from shared.contexto_global_redis import ContextoGlobalRedis, CmdKey, CtxKey from shared.mensagem_worker import WorkerFilaMensagens @@ -58,12 +57,19 @@ def main(): acao = ManagerWorkerCommandType(dados.get("cmd", 0)) if acao == ManagerWorkerCommandType.IniciarMPC: - parametros = dados.get("params", {}).get("parametros") - mapa = dados.get("params", {}).get("mapa") - iniciar_operacao = dados.get("params", {}).get("iniciar_operacao", False) - if parametros is not None: - p_ref = ContextoGlobalRedis.get_operacao().get("ponto_mapa_ref", []) - iniciar_mpc(parametros, mapa, p_ref, iniciar_operacao) + try: + _p = dados.get("params") + if _p is not None: + parametros = _p.get("parametros") + mapa = _p.get("mapa") + iniciar_operacao = _p.get("iniciar_operacao", False) + p_ref = _p.get("p_ref", []) + from manager_worker.modulos.mpc import inicializar as iniciar_mpc + iniciar_mpc(parametros, mapa, p_ref, iniciar_operacao) + else: + ContextoGlobalRedis()._atualizar_mpc(do_manager=True, iniciar_operacao=False) + except Exception as e: + mostrar_log(f"Erro ao Iniciar MPC: {e}") elif acao == ManagerWorkerCommandType.AtualizarDadosControle: #mostrar_log("Adicionado na fila") fila.adicionar(acao) diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py index 9af0ae0d5..425625d84 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py @@ -19,6 +19,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): _snr = ContextoGlobalRedis.get_modulo(T_Code.Snr) visual_worker_ativado = _controle.get("sonar_ativado", False) + usa_matriz_custo = _controle.get("usa_matriz_custo", False) visual_worker_operante = (_snr.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)) == StatusModulo.OPERANTE.value _dados_vw = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {}) _snapshot_vw = _dados_vw.get("matriz_confianca") @@ -56,10 +57,6 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): Vmin = 0.1 # if _trajetoria.get("status", StatusCarroMapa.Parado.value) == StatusCarroMapa.CaminhandoRua.value else 0.8 contexto = { - "Operacao": { - "Status": _operacao.get("status"), - "Finalizando": _operacao.get("finalizando") - }, "GPS": { "Latitude": _gps.get("lat", 0), "Longitude": _gps.get("lon", 0), @@ -88,6 +85,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): "Operante": visual_worker_operante, "Atualizado": visual_worker_atualizado, "MatrizCusto": { + "EmUso": usa_matriz_custo, "Valida": visual_worker_ativado and visual_worker_operante and visual_worker_atualizado, "Custo": custo, "Navegavel": nav, @@ -95,21 +93,10 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): "EscalasX": escalas, "Block": block }, - "Camera": { - "FovH": ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {}).get("parametros", {}).get("fov_h", 0.7), - "DistanciaMax": _operacao.get("Snr", {}).get("distancia_maxima", 5000) / 1000.0, - "DistanciaMin": _operacao.get("Snr", {}).get("distancia_minima", 500) / 1000.0, - } - }, - "RegrasAtivas": { - "matriz_custo": False, - "deteccao_obstaculos": False, }, "Equipamento": { "largura": _equipamento.get("largura", 0.85), - "entre_eixos": _equipamento.get("distancia_entre_eixos", 0.92), - "angulo_roll_max": _equipamento.get("angulo_roll_max", 15.0), - "angulo_pitch_max": _equipamento.get("angulo_pitch_max", 30.0), + "entre_eixos": _equipamento.get("distancia_entre_eixos", 0.92) } } diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py index c164b71e7..2a2d5edc2 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py @@ -37,13 +37,11 @@ class ControladorMPC: self.dt = 0 #print(parametros_mpc) - self.angulo_max_graus = parametros_mpc.get("angulo_max_graus", 30.0) - self.velocidade_min = parametros_mpc.get("velocidade_min", 0.4) - self.velocidade_max = parametros_mpc.get("velocidade_max", 1.9) - self.horizonte = parametros_mpc.get("horizonte", 2.5) - self.horizonte_min = parametros_mpc.get("horizonte_min", 0.6) - self.horizonte_max = parametros_mpc.get("horizonte_max", 2.8) - self.horizonte_parado = parametros_mpc.get("horizonte_parado", 0.5) + self.angulo_max_graus = parametros_mpc.get("angulo_max_graus") + self.velocidade_min = parametros_mpc.get("velocidade_min") + self.velocidade_max = parametros_mpc.get("velocidade_max") + self.horizonte_min = parametros_mpc.get("horizonte_min") + self.horizonte_max = parametros_mpc.get("horizonte_max") self._beam_traj_min = parametros_mpc.get("beam_traj_min", 3) # nº mínimo de trajetórias completas que queremos self._beam_topN_max = parametros_mpc.get("beam_topN_max", 5) # limite superior de candidatos ativos self._beam_topN_min = parametros_mpc.get("beam_topN_min", 2) # limite inferior @@ -357,64 +355,6 @@ class ControladorMPC: # UTILS - def _corrigir_pontos_visitados_new(self, x, y, pontos_visitados: np.ndarray, idx_atual: int = -1, limite_max_avanco: float = 5.0, limite_max_pontos: int = 10, velocidade: float = -1, dt: float = -1, look_ahead: bool = True): - try: - p_xy, p_mg, p_s = self._p_xy, self._p_margem, self._p_s - N = p_xy.shape[0] - if N == 0: - return -1 - - # --- (1) Igual ao antigo: marcar EXCLUSIVO quando idx_atual vier do C# --- - if idx_atual > -1: - pontos_visitados[:idx_atual+1] = True # <<< EXCLUSIVO (antes era :idx_atual+1) - return idx_atual - - if pontos_visitados.all(): - return N - 1 - - start_idx = int(np.argmax(~pontos_visitados)) - - # janela por metros + clamp por nº de pontos (compatível com o antigo) - s_start = p_s[start_idx] - s_lim = s_start + float(limite_max_avanco) - end_idx = int(np.searchsorted(p_s, s_lim, side="right") - 1) - if end_idx < start_idx: - end_idx = start_idx - end_idx = min(end_idx, start_idx + int(limite_max_pontos)) - - sl = slice(start_idx, end_idx + 1) - dx = x - p_xy[sl, 0] - dy = y - p_xy[sl, 1] - dist2 = dx*dx + dy*dy - margem2 = p_mg[sl] * p_mg[sl] - - # --- (2) Opcional para fidelidade ao antigo: usar '<' em vez de '<=' --- - hits = dist2 < margem2 # era <= - - if np.any(hits): - off = int(np.argmax(hits)) - idx = start_idx + off - pontos_visitados[:idx] = True - if velocidade > -1 and look_ahead: - s_hit = self._p_s[idx] - s_goal = s_hit + self.d_look_ahead_m(velocidade, dt) - idx_alvo = int(np.searchsorted(self._p_s, s_goal, side="left")) - idx_alvo = min(idx_alvo, len(self._p_s)-1) - return idx_alvo - return idx - - # --- (3) Fallback robusto para “próximo não visitado” --- - nv = np.flatnonzero(~pontos_visitados) - return int(nv[0]) if nv.size else (N - 1) - - except Exception as e: - mostrar_log(f"Erro ao corrigir pontos visitados: {e}") - try: - nv = np.flatnonzero(~pontos_visitados) - return int(nv[0]) if nv.size else (N - 1) - except Exception: - return -1 - def _proximo_nao_visitado(self, visitados): try: for i, v in enumerate(visitados): @@ -590,64 +530,6 @@ class ControladorMPC: # theta = (theta + np.pi) % (2*np.pi) - np.pi return x, y, theta, visitados - def d_look_ahead_m(self, velocidade, dt: float = None): - """ - Retorna look-ahead em METROS. - - velocidade: pode vir em m/s ou normalizada (0-1). Detecto automaticamente. - - dt: passo real do MPC (s) para suavização adaptativa (opcional). - """ - - # --- 1) Normalização de velocidade --------------------------------------- - # tente usar self.vel_max_m_s se já existir; senão, usa 6.8 km/h (~1.889 m/s) - vel_max_ms = getattr(self, "vel_max_m_s", 6.8/3.6) - v = float(velocidade) - #if v <= 1.05: # heurística: trata <=1.0 como v_norm - # v = max(0.0, min(1.0, v)) * vel_max_ms - #else: - # v = max(0.0, v) # já está em m/s - v = max(0.0, v) # já está em m/s - - # --- 2) Base polinomial (suave e previsível) ------------------------------ - # L_base = L0 + a*v + b*v^2 (clamp em [Lmin, Lmax]) - Lmin, Lmax = self.horizonte_min, self.horizonte_max # bom para teu range (1.3–6.8 km/h) - L0, a, b = self.horizonte_parado, 0.70, 0.20 - L = L0 + a*v + b*(v*v) - if L < Lmin: L = Lmin - if L > Lmax: L = Lmax - - # --- 3) Redução por curvatura e erro de orientação ------------------------ - # Se você já calcula curvatura/erro, exponha em self; senão, assumo 0. - kappa = abs(getattr(self, "curvatura_atual", 0.0)) # 1/m - err_yaw = abs(getattr(self, "erro_angular_atual", 0.0)) # rad - - # Fatores <=1.0: reduzem o L em curva forte e/ou erro de yaw grande. - # Ajuste c_k, c_e conforme seu corredor (mais alto = reduz mais). - c_k, c_e = 3.0, 1.2 - f_k = 1.0 / (1.0 + c_k * kappa) - f_e = 1.0 / (1.0 + c_e * err_yaw) - L *= min(f_k, f_e) - - # --- 4) Compensação de latência de controle/planta ------------------------ - # Se você tem latência medida, exponha em self.tau_ctrl (s). Senão: ~0.15 s. - tau = float(getattr(self, "tau_ctrl", 0.15)) - L += v * tau # “empurra” o alvo à frente para cobrir atraso - - # Clamp final para garantir limites mesmo após fatores - if L < Lmin: L = Lmin - if L > Lmax: L = Lmax - - # --- 5) Suavização temporal (anti-chatter) -------------------------------- - # EMA com constante de tempo ~0.4 s (ajuste T_ema). Usa dt se informado. - T_ema = 0.40 - if dt is None: - dt = float(getattr(self, "dt", 0.15)) # teu MPC já guarda dt - alpha = max(0.0, min(1.0, 1.0 - pow(2.718281828, -dt / T_ema))) - L_suave = getattr(self, "_L_ema", L) - L_suave = (1.0 - alpha) * L_suave + alpha * L - self._L_ema = L_suave - - return L_suave - def _wrap_pi(self, a): try: @@ -792,6 +674,7 @@ class ControladorMPC: self.tempo_execucao_local = contexto.get("Carro", {}).get("TempoEntreComandos", 0.5) self.passos_horizonte_local = max(1, math.floor(1 / self.tempo_execucao_local)) + self.passos_horizonte_local = 1 # -------------------- Correção por latência (vida real) -------------------- # Mantém correção com 'self.dt' e 'velocidade' REAIS @@ -819,8 +702,8 @@ class ControladorMPC: idx_alvo_correcao = self._corrigir_pontos_visitados(x, y, self.visitados_execucao, idx_proximo_ponto_real) # -------------------- Planejamento: horizonte ESPACIAL fixo -------------------- - S_ALVO = float(getattr(self, "horizonte", 2.5)) - V_FLOOR = float(getattr(self, "_vmin_planejamento", 0.40)) + S_ALVO = self.horizonte_max + V_FLOOR = float(getattr(self, "_vmin_planejamento", 0.30)) DT_MIN = float(getattr(self, "_dt_pred_min", 0.05)) DT_MAX = float(getattr(self, "_dt_pred_max", 0.25)) K_ALVO = int(getattr(self, "_k_alvo", 16)) @@ -864,6 +747,8 @@ class ControladorMPC: self.qtd_comandos_sucessivos = K + #print(f"S_ALVO: {S_ALVO}, v_sim: {v_sim}, passos_local: {self.passos_horizonte_local}, K: {K}, dt_pred: {dt_pred}") + # -------------------- Seleção do comando -------------------- angulo_anterior = np.radians(comando_anterior.get("angulo", 0.0)) tipo_anterior = TipoMovimentoDirecional(comando_anterior.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value)) @@ -1079,7 +964,7 @@ class ControladorMPC: # -------------------- Debug opcional da matriz de custo -------------------- self._tick_id = getattr(self, "_tick_id", 0) + 1 - if (getattr(self, "debug_cost_vis", False) and contexto.get("RegrasAtivas", {}).get("matriz_custo", False) and (self._tick_id % 10 == 0)): + if (getattr(self, "debug_cost_vis", False) and contexto.get("VisualWorker", {}).get("MatrizCusto", {}).get("EmUso", False) and (self._tick_id % 10 == 0)): dados_matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", {}) deadline_dbg = time.perf_counter() + 0.03 tipos_dbg, angs_dbg, _ = self._gerar_angulos_candidatos_receding( @@ -1184,9 +1069,9 @@ class ControladorMPC: # 3) Flags de matriz dados_matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", {}) + regra_matriz_custo = bool(dados_matriz_custo.get("EmUso", False)) matriz_custo_valida = bool(dados_matriz_custo.get("Valida", False)) - regra_matriz_custo = bool(contexto.get("RegrasAtivas", {}).get("matriz_custo", False)) - filtrar_matriz = matriz_custo_valida and regra_matriz_custo + filtrar_matriz = regra_matriz_custo and matriz_custo_valida # 4) Geração bruta (graus) angulos_raw = self._gerar_candidatos_brutos(angulo_ideal_deg, filtrar_matriz) diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc_old.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc_old.py deleted file mode 100644 index 600baefef..000000000 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc_old.py +++ /dev/null @@ -1,1782 +0,0 @@ -import math -import time -import numpy as np -from copy import deepcopy -from bisect import bisect_right -from concurrent.futures import ThreadPoolExecutor, as_completed - -from shared.enums import StatusCarroMapa, TipoMovimentoDirecional, TipoPontoRua -from manager_worker.config import mostrar_log -from shared.gps_handler import GPSHandler -#from shared.visualizador_trajetoria import VisualizadorTrajetoria - -_mpc = None -_iniciado = False - -def inicializar(parametros, mapa, p_ref, forcar): - global _mpc, _iniciado - if not _iniciado or len(_mpc.pontos_info) != len(mapa) or forcar: - _mpc = ControladorMPC(parametros_mpc=parametros, pontos_mapa=mapa, p_ref=p_ref) - mostrar_log(f"MPC iniciado! Trajetoria com {len(_mpc.pontos_info)} pontos") - _iniciado = True - -def get_mpc(): - global _mpc - return _mpc - -def comando_parado(): - return 0.0, TipoMovimentoDirecional.RodasDianteiras - -class ControladorMPC: - def __init__(self, parametros_mpc, pontos_mapa, p_ref): - try: - self.gps_handler = GPSHandler(p_ref[0], p_ref[1]) - self.lat0 = p_ref[0] - self.lon0 = p_ref[1] - #self.visualizador = VisualizadorTrajetoria() - - self.ultima_atualizacao = None - self.dt = 0 - - self.angulo_max_graus = parametros_mpc.get("angulo_max_graus", 30.0) - self.velocidade_min = parametros_mpc.get("velocidade_min", 0.4) - self.velocidade_max = parametros_mpc.get("velocidade_max", 1.9) - self.horizonte = parametros_mpc.get("horizonte", 2.5) - self.horizonte_passos = 10 - - self.pontos_info = [] - self.visitados_execucao = [] - - self.pontos_info = pontos_mapa - - if pontos_mapa: - self.visitados_execucao = [False] * len(self.pontos_info) - - self.executor = ThreadPoolExecutor(max_workers=20) - except Exception as e: - mostrar_log(f"Erro ao inicializar MPC: {e}") - - - # UTILS - - def _proximo_nao_visitado(self, visitados): - for i, v in enumerate(visitados): - if not v: - return i - return len(visitados) - 1 - - def _corrigir_pontos_visitados(self, x, y, pontos_visitados, idx_atual=-1, limite_max_avanço=5.0): - if (idx_atual > -1): - for idx, ponto in enumerate(self.pontos_info): - if (idx < idx_atual): - pontos_visitados[idx] = True - else: - break - return idx_atual - - for idx, ponto in enumerate(self.pontos_info): - if pontos_visitados[idx]: - continue - pos = ponto["xy"] - margem = ponto.get("distanciaMargem", 0.7) - dist = np.linalg.norm([x - pos[0], y - pos[1]]) - if dist < margem: - for i in range(idx + 1): - pontos_visitados[i] = True - return idx - if idx > 0 and not pontos_visitados[idx - 1] and idx >= limite_max_avanço: - break - return self._proximo_nao_visitado(pontos_visitados) - - def _calcular_pesos_movimento(self, contexto, erro_ori_rad): - peso_erro_pos = 1.2 # 0 - peso_erro_ori = 1.0 # 1 - peso_suavidade = 1.4 # 2 - peso_fator_re = 0.2 # 3 - peso_ideal = 0.4 # 4 - - CARRO = contexto.get("Carro", {}) - status = StatusCarroMapa(CARRO.get("Status", StatusCarroMapa.Parado.value)) - dentro = CARRO.get("DentroCorredor", False) - manobrando = CARRO.get("ManobrandoEntreRuas", False) - velocidade = CARRO.get("Velocidade", self.velocidade_min) - - # Penalidade proporcional à velocidade - penalidade_por_velocidade = (velocidade / self.velocidade_max) / 10.0 - erro_ori_deg = np.degrees(erro_ori_rad) - erro_ori_clipped = max(min(erro_ori_deg, self.angulo_max_graus), -self.angulo_max_graus) - erro_ori_norm = abs(erro_ori_clipped / self.angulo_max_graus) - - custo_movimento = { - TipoMovimentoDirecional.RodasDianteiras: 0.0, - TipoMovimentoDirecional.MovimentoArco: 0.0 - } - - if manobrando or status in [ StatusCarroMapa.EntrandoRua, StatusCarroMapa.SaindoRua, StatusCarroMapa.Manobrando ]: - custo_movimento[TipoMovimentoDirecional.MovimentoArco] += 0.0 - custo_movimento[TipoMovimentoDirecional.RodasDianteiras] += 1.0 - else: - custo_movimento[TipoMovimentoDirecional.MovimentoArco] += 0.0 if erro_ori_norm >= 0.4 else 1.0 - custo_movimento[TipoMovimentoDirecional.RodasDianteiras] += 1.2 if erro_ori_norm >= 0.4 else 0.0 - - return (peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_ideal, custo_movimento) - - def _gerar_angulos_candidatos(self, angulo_ideal_rad, erro_ori, contexto): - def clamp(v, vmin, vmax): - return max(vmin, min(vmax, v)) - - CARRO = contexto.get("Carro", {}) - status = CARRO.get("Status", 0) - manobrando = CARRO.get("ManobrandoEntreRuas", False) - - if manobrando or status in [ StatusCarroMapa.EntrandoRua, StatusCarroMapa.SaindoRua, StatusCarroMapa.Manobrando ]: - tipos_validos = [ TipoMovimentoDirecional.MovimentoArco ] - else: - tipos_validos = [ TipoMovimentoDirecional.RodasDianteiras, TipoMovimentoDirecional.MovimentoArco ] - - erro_ori_deg = np.degrees(erro_ori) - angulo_ideal_deg = np.degrees(angulo_ideal_rad) - - # Passo varia conforme erro angular - if erro_ori_deg > 10: - passo = 5.0 - faixa = 15.0 - elif erro_ori_deg > 5: - passo = 2.5 - faixa = 7.5 - else: - passo = 1.5 - faixa = 4.5 - - # Geração em torno do ideal - candidatos_graus = list(np.arange(angulo_ideal_deg - faixa, angulo_ideal_deg + faixa + 0.1, passo)) - - extras = [ - -self.angulo_max_graus, # mínimo possível - -self.angulo_max_graus * 0.75, # -75% - self.angulo_max_graus * 0.75, # +75% - self.angulo_max_graus # máximo possível - ] - - # Clamping e eliminação de duplicatas - candidatos_radianos = sorted(set( - np.radians(clamp(g, -self.angulo_max_graus, self.angulo_max_graus)) - for g in (candidatos_graus + extras) - )) - - #print(f"Ideal: {round(angulo_ideal_deg, 2)}°, Erro Ori: {round(erro_ori_deg, 2)}°, Obstáculos: {len(obstaculos)}, Candidatos: {[round(np.degrees(a), 2) for a in candidatos_radianos]}") - return tipos_validos, candidatos_radianos - - def _erro_angular(self, angulo_alvo, angulo_atual, angulo_caminho, peso_local=0.5): - erro_com_ponto = (angulo_alvo - angulo_atual + np.pi) % (2 * np.pi) - np.pi - erro_com_caminho = (angulo_caminho - angulo_atual + np.pi) % (2 * np.pi) - np.pi - - erro_combinado = (1 - peso_local) * erro_com_caminho + peso_local * erro_com_ponto - return abs(erro_combinado) - - def _atualiza_posicao_obstaculos(self, contexto, new_x, new_y, new_theta, omega): - obstaculos = deepcopy(contexto.get("VisualWorker", {}).get("Obstaculos", [])) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - for obst in obstaculos: - obst["distancia_m"] = max(0.0, obst["distancia_m"] - velocidade * min(0.2, self.dt)) - # Assume que o obstáculo está a 'distancia_m' à frente, em um ângulo correspondente ao centro_percentual original - fov = contexto["VisualWorker"]["Camera"]["FovH"] # exemplo: np.radians(70) - centro_antigo = obst.get("centro_percentual", [0.5, 0.5])[0] - angulo_original = (centro_antigo - 0.5) * fov - # Estima a posição real do obstáculo - x_obst = new_x + obst["distancia_m"] * np.cos(new_theta + angulo_original) - y_obst = new_y + obst["distancia_m"] * np.sin(new_theta + angulo_original) - # Recalcula o centro_percentual estimado - centro_x = centro_antigo - (omega / fov) - obst["centro_percentual"] = [centro_x, obst.get("centro_percentual", [0.5, 0.5])[1]] - #print(f"📍 (x: {new_x}, y: {new_y}, t: {new_theta}) Obstáculo simulado em x: {x_obst:.2f}, y: {y_obst:.2f}, omega: {np.degrees(omega):.2f}°, centro_x: {obst['centro_percentual'][0]:.3f} ({centro_x:.3f}) / ({centro_antigo:.3f})") - return obstaculos - - def _simular_trajetoria_matriz_custo(self, matriz_custo, linhas_info, tipo, angulo, distancia_m, theta_rad, largura_equipamento): - altura = len(matriz_custo) - largura = len(matriz_custo[0]) - if largura == 0 or altura == 0 or distancia_m == 0: - return 0.0, True - - # 2. Ordena por profundidade crescente - linhas_ordenadas = sorted(linhas_info.values(), key=lambda item: item["distancia"]) - distancia_min_m = linhas_ordenadas[0]["distancia"] - distancia_max_m = linhas_ordenadas[-1]["distancia"] - - # 3. Simula trajetória ponto a ponto e acumula custo - x_sim = self.x_ant # no referencial do robô: (0, 0) - y_sim = self.y_ant - custo_total = 0.0 - passos = 1 - matriz_concluida = False - fora_matriz_horizontal = False - celulas_ocupadas = [] - - for _ in range(passos): - # Avança no referencial do robô - x_sim += distancia_m * np.sin(-theta_rad) - y_sim += distancia_m * np.cos(theta_rad) - - # Verifica limites de profundidade - if y_sim < distancia_min_m: - continue # fora da matriz - elif y_sim > distancia_max_m: - matriz_concluida = True - break - - # Localiza a linha mais próxima da profundidade atual - linha_alvo = next( - (linha["idx"] for linha in reversed(linhas_ordenadas) if y_sim >= linha["distancia"]), - linhas_ordenadas[0]["idx"] - ) - escala_x = linhas_info[linha_alvo]["escala_x"] - largura_total = escala_x * largura - x_centralizado = x_sim + largura_total / 2 - coluna_alvo = int(x_centralizado / escala_x) - - #if 0 <= linha_alvo < altura and 0 <= coluna_alvo < largura: - # custo_total += matriz_custo[linha_alvo][coluna_alvo]["custo"] - - escala_x = matriz_custo[linha_alvo][0]["escala_x"] - colunas_ocupadas = int(np.ceil(largura_equipamento / escala_x)) - colunas_por_lado = colunas_ocupadas // 2 - - # 2. Soma os custos ao longo do caminho (de trás até a frente) - for i in range(altura - 1, linha_alvo - 1, -1): - for j in range(coluna_alvo - colunas_por_lado, coluna_alvo + colunas_por_lado + 1): - if 0 <= i < altura and 0 <= j < largura: - celulas_ocupadas.append((i, j)) - custo_total += matriz_custo[i][j]["custo"] - #else: - # custo_total += 20.0 - # fora_matriz_horizontal = True - - mostrar_log(f"d: {self.y_ant:.2f} m, {tipo.name} {np.degrees(angulo):.2f} - Posicao ({linha_alvo}, {coluna_alvo}), x_sim: {x_sim}, y_sim: {y_sim}, Custo: {round(custo_total, 4)}, Theta: {np.degrees(theta_rad):.2f}, Passo: {round(passos * distancia_m, 2)} m") #, celulas: {celulas_ocupadas} - - #if fora_matriz_horizontal and len(celulas_ocupadas) == 0: - # matriz_concluida = True - # custo_total = float('inf') - - return custo_total, matriz_concluida - - def corrigir_pose_por_latencia( - self, - x, y, theta, visitados, - latency_s, # atraso a compensar (s) - dt, # dt nominal do seu controle - nova_posicao_fn, # self._nova_posicao - u_hold, # {'v': m/s, 'omega': rad/s} (ou forneça 'tipo' e 'angulo' + calc_omega) - cmd_seq=None, # opcional: [(dur_s, u_dict), ...] que cobre latency_s - time_left_ms=lambda: 1e9, - calc_omega_fn=None # opcional: fn(tipo, angulo_rad, v) -> omega - ): - """ - Propaga (x,y,theta) por 'latency_s' usando 'nova_posicao_fn' que depende de self.dt. - Retorna (x, y, theta) estimados no presente. - """ - visitados_copy = visitados.copy() - latency_s = max(0.0, float(latency_s)) - if latency_s == 0.0: - return x, y, theta, visitados_copy - - # --- constrói sequência efetiva de comandos --- - if not cmd_seq: - cmd_seq = [(latency_s, u_hold)] - else: - total = sum(max(0.0, d) for d, _ in cmd_seq) - if total < latency_s: - cmd_seq = list(cmd_seq) + [(latency_s - total, cmd_seq[-1][1])] - - # --- adaptador para usar dt_eff com fn que usa self.dt --- - def aplicar_passo_dt(xk, yk, thetak, u, dt_eff): - # garantir que temos omega e v - v = u.get('v', 0.0) - if 'omega' in u: - omega = u['omega'] - else: - if calc_omega_fn is not None and 'tipo' in u and 'angulo' in u: - omega = calc_omega_fn(v, u['angulo'], u['tipo']) - else: - omega = 0.0 # fallback: reta - old_dt = self.dt - try: - self.dt = dt_eff - return nova_posicao_fn(xk, yk, thetak, omega, v, u.get('tipo'), u.get('angulo', 0.0)) - finally: - self.dt = old_dt - - # --- integra por tempo, quebrando cada trecho em subpassos ~dt --- - t_rem = latency_s - for dur_s, u in cmd_seq: - if t_rem <= 0.0: - break - seg = min(dur_s, t_rem) - if seg <= 0.0: - continue - - n = max(1, int(round(seg / dt))) - dt_eff = seg / n - - for _ in range(n): - if time_left_ms() <= 0.0: - return x, y, theta, visitados_copy - x, y, theta = aplicar_passo_dt(x, y, theta, u, dt_eff) - idx_alvo = self._corrigir_pontos_visitados(x, y, visitados_copy) - - t_rem -= seg - - # normaliza theta se quiser - # theta = (theta + np.pi) % (2*np.pi) - np.pi - return x, y, theta, visitados_copy - - - - # MPC MIOPE - - def compute(self, contexto, comando_anterior): - try: - agora = time.time() - self.dt = 0.2 if self.ultima_atualizacao == None else agora - self.ultima_atualizacao - self.ultima_atualizacao = agora - comando = self._processar_mpc(contexto, comando_anterior) - mostrar_log(f"Estatisticas MPC: dt = {round(self.dt, 2)} s, freq = {round(1.0 / self.dt, 2)} Hz") - return comando - - except Exception as e: - mostrar_log(f"❌ Erro ao processar compute MPC: {e}") - - def _processar_mpc(self, contexto, comando_anterior): - try: - if not self.pontos_info: - return None - - GPS = contexto.get("GPS", {}) - pos_lat = GPS.get("Latitude", 0) - pos_lon = GPS.get("Longitude", 0) - theta = np.radians(GPS.get("AnguloCarro", 0)) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - - x, y = self.gps_handler.converter_latlon_para_xz(pos_lat, pos_lon) - - x_plot = x - y_plot = y - sim = [(x, y, theta)] - x_temp, y_temp, theta_temp = x, y, theta - - atraso_simulado_passos = 0 # Delay estimado de resposta do robô - - distancia_m = velocidade * self.dt - - if distancia_m > 0: - pontos_horizonte = int(self.horizonte / (distancia_m)) - else: - pontos_horizonte = 10 - - pontos_horizonte = max(10, min(pontos_horizonte, 120)) # entre 10 e 120 pontos - - pontos_horizonte = self.horizonte_passos - - angulo_final = None - tipo_final = None - self.x_ant = 0 - self.y_ant = 0 - self.dist_acumulada = 0 - - for i in range(pontos_horizonte): - primeira_execucao = angulo_final is None and tipo_final is None - if primeira_execucao: - idx_alvo = self._corrigir_pontos_visitados(x_temp, y_temp, self.visitados_execucao) - else: - idx_alvo = self._corrigir_pontos_visitados(x_temp, y_temp, deepcopy(self.visitados_execucao)) - if idx_alvo >= len(self.pontos_info): - angulo_final, tipo_final = comando_parado() - break - if i < atraso_simulado_passos and comando_anterior: - angulo_mpc = np.radians(comando_anterior["angulo"]) - tipo_mpc = TipoMovimentoDirecional(comando_anterior["tipo"]) - else: - ponto_info = self.pontos_info[idx_alvo] - tipo_ponto = TipoPontoRua(ponto_info.get("tipo")) - ponto_alvo = ponto_info["xy"] - angulo_mpc, tipo_mpc = self._calcular_melhor_candidato(ponto_alvo, x_temp, y_temp, theta_temp, deepcopy(self.visitados_execucao), contexto, comando_anterior, primeira_execucao) - if primeira_execucao: - angulo_final = angulo_mpc - tipo_final = tipo_mpc - - omega = self.gps_handler.calcular_omega(velocidade, angulo_mpc, tipo_mpc) - - # Simula a movimentação usando theta com base rotacionada (-theta + 90) - theta_plot = (-theta_temp) + np.radians(90) - x_temp += velocidade * np.cos(theta_temp) * self.dt - y_temp += velocidade * np.sin(theta_temp) * self.dt - theta_ant = theta_temp - theta_temp += omega * self.dt - delta_theta = (theta_ant - theta_temp + np.pi) % (2 * np.pi) - np.pi - - self.x_ant += distancia_m * np.sin(-delta_theta) - self.y_ant += distancia_m * np.cos(delta_theta) - - comando_anterior["angulo"] = angulo_mpc - comando_anterior["tipo"] = tipo_mpc - - x_plot += velocidade * np.cos(theta_plot) * self.dt - y_plot += velocidade * np.sin(theta_plot) * self.dt - - sim.append((x_plot, y_plot, theta_plot)) - - # Converte os pontos simulados para lat/lon - simulacao_latlon = [] - for sx, sy, theta in sim: - dlat = sy / self.gps_handler.raio_terra - dlon = sx / (self.gps_handler.raio_terra * np.cos(np.radians(self.lat0))) - lat = self.lat0 + np.degrees(dlat) - lon = self.lon0 + np.degrees(dlon) - simulacao_latlon.append([lat, lon, theta]) - - #angulo_final, tipo_final = self._calcular_melhor_candidato(sim[0][0], sim[0][1], theta, self.visitados_execucao, contexto, comando_anterior, False) - - return { - "angulo": np.degrees(angulo_final), - "tipo": tipo_final, - "simulacao": simulacao_latlon, - "parada_necessaria": False - } - - except Exception as e: - mostrar_log(f"❌ Erro ao processar MPC: {e}") - - def _calcular_melhor_candidato(self, ponto_alvo, x, y, theta, visitados, contexto, comando_anterior, primeira_execucao): - try: - orient = self.gps_handler.calcular_orientacao(ponto_alvo, (x, y)) - delta_theta = (orient - theta + np.pi) % (2 * np.pi) - np.pi - erro_ori = abs(delta_theta) - angulo = np.clip(delta_theta, -np.radians(self.angulo_max_graus), np.radians(self.angulo_max_graus)) - - melhor_custo = float('inf') - melhor_tipo = TipoMovimentoDirecional.RodasDianteiras - melhor_angulo = angulo - - tipos_validos, angulos_candidatos = self._gerar_angulos_candidatos(angulo, erro_ori, contexto) - - velocidade = velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - deslocamento = velocidade * self.dt - - ctx_vw = contexto.get("VisualWorker", {}) - vw_ativado = ctx_vw.get("Ativado", False) - vw_operante = ctx_vw.get("Operante", False) - com_matriz_custo = contexto.get("RegrasAtivas", {}).get("matriz_custo", False) - filtrar_matriz = vw_ativado and vw_operante and com_matriz_custo - - if filtrar_matriz: - matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", [[]]) - # 1. Analisa profundidade média por linha - from shared.utils import analisar_linhas_por_profundidade - linhas_info = analisar_linhas_por_profundidade(matriz_custo, "distancia_m", contexto.get("VisualWorker", {}).get("Camera", {}).get("FovH", 0.7)) - - for tipo in tipos_validos: - for angulo_testado in angulos_candidatos: - omega = self.gps_handler.calcular_omega(velocidade, angulo_testado, tipo) - theta_sim = theta + omega * self.dt - delta_theta_sim = (theta - theta_sim + np.pi) % (2 * np.pi) - np.pi - x_sim = x + (np.cos(theta_sim) * deslocamento) - y_sim = y + (np.sin(theta_sim) * deslocamento) - - custo = 0.0 - - if filtrar_matriz: - custo_espaco, matriz_concluida = self._simular_trajetoria_matriz_custo(matriz_custo, linhas_info, tipo, angulo_testado, deslocamento, delta_theta_sim) - custo += custo_espaco - - if custo > melhor_custo: - continue - - idx_alvo_sim = self._corrigir_pontos_visitados(x_sim, y_sim, deepcopy(visitados)) - - ponto_alvo_sim = self.pontos_info[idx_alvo_sim]["xy"] - orient_sim = self.gps_handler.calcular_orientacao((x_sim, y_sim), ponto_alvo_sim) - orient_sim = (orient_sim + np.pi) % (2 * np.pi) - erro_pos = np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]]) - erro_ori_sim = self._erro_angular(orient_sim, theta_sim) - pesos = self._calcular_pesos_movimento(contexto, erro_ori_sim) - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_ideal, peso_movimento = pesos[0], pesos[1], pesos[2], pesos[3], pesos[4], pesos[5] - vetor_alvo = np.array(ponto_alvo_sim) - np.array([x_sim, y_sim]) - vetor_alvo_norm = vetor_alvo / np.linalg.norm(vetor_alvo) - vetor_movel = np.array([np.cos(theta_sim), np.sin(theta_sim)]) - cos_angulo = -np.dot(vetor_movel, vetor_alvo_norm) - delta_angulo = abs(angulo_testado - np.radians(comando_anterior.get("angulo", 0))) - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suavidade = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - custo_tipo_movimento = peso_movimento[tipo] # * erro_pos - erro_re = (1 - cos_angulo) if cos_angulo > 0 else cos_angulo - custo_re = -erro_re * erro_pos * peso_fator_re - erro_ideal = abs(angulo_testado - angulo) - custo_ideal = peso_ideal * erro_ideal - custo_mapa = (custo_pos + custo_ori + custo_suavidade + custo_tipo_movimento + custo_ideal + custo_re) / 10.0 - custo += custo_mapa - - #if primeira_execucao: - # mostrar_log(f"{tipo.name} {round(np.degrees(angulo_testado), 2)}°, d: {round(deslocamento, 2)} m - iPA: {idx_alvo_sim}, Custo: {round(custo, 4)}, Omega: {round(np.degrees(omega), 2)}°, Theta: {round(np.degrees(theta_sim), 2)}°, Ori: {round(np.degrees(orient_sim), 2)}°, E Ori: {round(np.degrees(erro_ori_sim), 3)}°, E Pos: {round(erro_pos, 3)}, F Re: {round(erro_re, 3)}, d°: {round(np.degrees(delta_angulo), 2)}, CE: {round(custo_espaco, 4)}, CP: {round(custo_pos, 4)}, CO: {round(custo_ori, 4)}, CM: {round(custo_tipo_movimento, 4)}, CS: {round(custo_suavidade, 4)}, CR: {round(custo_re, 4)}, CI: {round(custo_ideal, 4)}") - if custo < melhor_custo: - melhor_custo = custo - melhor_tipo = tipo - melhor_angulo = angulo_testado - - #if primeira_execucao: - # mostrar_log(f"COMANDO: {tipo.name}, Angulo ideal: {round(np.degrees(angulo), 2)}, Melhor angulo: {round(np.degrees(melhor_angulo), 2)}, Custo: {round(melhor_custo, 3)}") - - mostrar_log(f"z: {self.y_ant:.3f} m, x: {self.x_ant:.3f} m, COMANDO: {melhor_tipo.name}, Angulo ideal: {round(np.degrees(angulo), 2)}, Melhor angulo: {round(np.degrees(melhor_angulo), 2)}, Custo: {round(melhor_custo, 3)}") - return melhor_angulo, melhor_tipo - - except Exception as e: - mostrar_log(f"❌ Erro ao calcular melhor candidato: {e}") - - - - # MPC COM CANDIDATO FIXO DURANTE O HORIZONTE - - def compute_fixo(self, contexto, comando_anterior): - try: - agora = time.time() - self.dt = 0.2 if self.ultima_atualizacao == None else agora - self.ultima_atualizacao - self.ultima_atualizacao = agora - comando = self._processar_mpc_fixo(contexto, comando_anterior) - mostrar_log(f"Estatisticas MPC: dt = {round(self.dt, 2)} s, freq = {round(1.0 / self.dt, 2)} Hz") - return comando - - except Exception as e: - mostrar_log(f"❌ Erro ao processar compute MPC: {e}") - - def _processar_mpc_fixo(self, contexto, comando_anterior): - try: - if not self.pontos_info: - return None - GPS = contexto.get("GPS", {}) - pos_lat = GPS.get("Latitude", 0) - pos_lon = GPS.get("Longitude", 0) - theta = np.radians(GPS.get("AnguloCarro", 0)) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - - x, y = self.gps_handler.converter_latlon_para_xz(pos_lat, pos_lon) - - x_temp, y_temp, theta_temp = x, y, theta - - distancia_m = velocidade * self.dt - - if distancia_m > 0: - pontos_horizonte = int(self.horizonte / (distancia_m)) - else: - pontos_horizonte = 10 - - pontos_horizonte = max(10, min(pontos_horizonte, 50)) # entre 10 e 50 pontos - - self.horizonte_passos = pontos_horizonte - - angulo_final = None - tipo_final = None - self.x_ant = 0 - self.y_ant = 0 - self.dist_acumulada = 0 - idx_alvo = contexto.get("Carro", {}).get("IdxProximoPonto", 0) - if idx_alvo >= len(self.pontos_info): - angulo_final, tipo_final = comando_parado() - else: - ponto_info = self.pontos_info[idx_alvo] - ponto_alvo = ponto_info["xy"] - angulo_final, tipo_final, sim = self._calcular_melhor_candidato_horizonte_fixo(ponto_alvo, x_temp, y_temp, theta_temp, deepcopy(self.visitados_execucao), contexto, comando_anterior) - - comando_anterior["angulo"] = angulo_final - comando_anterior["tipo"] = tipo_final - - # Converte os pontos simulados para lat/lon - simulacao_latlon = [] - for sx, sy in sim: - dlat = sy / self.gps_handler.raio_terra - dlon = sx / (self.gps_handler.raio_terra * np.cos(np.radians(self.lat0))) - lat = self.lat0 + np.degrees(dlat) - lon = self.lon0 + np.degrees(dlon) - simulacao_latlon.append([lat, lon]) - - return { - "angulo": np.degrees(angulo_final), - "tipo": tipo_final, - "simulacao": simulacao_latlon - } - - except Exception as e: - mostrar_log(f"❌ Erro ao processar MPC: {e}") - - def _calcular_melhor_candidato_horizonte_fixo(self, ponto_alvo, x, y, theta, visitados, contexto, comando_anterior): - try: - orient = self.gps_handler.calcular_orientacao(ponto_alvo, (x, y)) - delta_theta = (orient - theta + np.pi) % (2 * np.pi) - np.pi - erro_ori = abs(delta_theta) - angulo = np.clip(delta_theta, -np.radians(self.angulo_max_graus), np.radians(self.angulo_max_graus)) - - melhor_custo = float('inf') - melhor_tipo = TipoMovimentoDirecional.RodasDianteiras - melhor_angulo = angulo - - tipos_validos, angulos_candidatos = self._gerar_angulos_candidatos(angulo, erro_ori, contexto) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - manobrando = contexto.get("Carro", {}).get("ManobrandoEntreRuas", False) - distancia_m = velocidade * self.dt - matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", [[]]) - - simulacoes = {} - - # 1. Analisa profundidade média por linha - from shared.utils import analisar_linhas_por_profundidade - linhas_info = analisar_linhas_por_profundidade(matriz_custo, "distancia_m", contexto.get("VisualWorker", {}).get("Camera", {}).get("FovH", 0.7)) - - for tipo in tipos_validos: - for angulo_testado in angulos_candidatos: - custo_total = 0.0 - x_sim, y_sim, theta_sim = x, y, theta - x_plot, y_plot = x, y - self.x_ant, self.y_ant = 0.0, 0.0 - chave = (tipo, angulo_testado) - simulacoes[chave] = [] - comando_anterior_copy = deepcopy(comando_anterior) - omega = self.gps_handler.calcular_omega(velocidade, angulo_testado, tipo) - for _ in range(self.horizonte_passos): - theta_sim += omega * self.dt - x_sim += np.cos(theta_sim) * distancia_m - y_sim += np.sin(theta_sim) * distancia_m - - - theta_plot = (-theta_sim) + np.radians(90) - theta_ant = theta_sim - omega * self.dt - delta_theta = (theta_ant - theta_sim + np.pi) % (2 * np.pi) - np.pi - x_plot += velocidade * np.cos(theta_plot) * self.dt - y_plot += velocidade * np.sin(theta_plot) * self.dt - simulacoes[chave].append((x_plot, y_plot)) - - - delta_theta_sim = (theta - theta_sim + np.pi) % (2 * np.pi) - np.pi - custo_espaco, matriz_concluida = self._simular_trajetoria_matriz_custo(matriz_custo, linhas_info, tipo, angulo_testado, distancia_m, delta_theta_sim) - - custo_total += custo_espaco - - self.x_ant += distancia_m * np.sin(-delta_theta_sim) - self.y_ant += distancia_m * np.cos(delta_theta_sim) - - # Avaliação final da posição no final da simulação - idx_alvo_sim = self._corrigir_pontos_visitados(x_sim, y_sim, deepcopy(visitados)) - ponto_alvo_sim = self.pontos_info[idx_alvo_sim]["xy"] - orient_sim = self.gps_handler.calcular_orientacao((x_sim, y_sim), ponto_alvo_sim) - orient_sim = (orient_sim + np.pi) % (2 * np.pi) - - erro_pos = np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]]) - erro_ori_sim = self._erro_angular(orient_sim, theta_sim) - - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_movimento, peso_ideal = self._calcular_pesos_movimento(contexto, erro_ori_sim, erro_pos) - - vetor_alvo = np.array(ponto_alvo_sim) - np.array([x_sim, y_sim]) - vetor_alvo_norm = vetor_alvo / np.linalg.norm(vetor_alvo) - vetor_movel = np.array([np.cos(theta_sim), np.sin(theta_sim)]) - cos_angulo = -np.dot(vetor_movel, vetor_alvo_norm) - delta_angulo = abs(angulo_testado - comando_anterior_copy.get("angulo", 0)) - - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suavidade = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - custo_tipo_movimento = peso_movimento[tipo] - erro_re = (1 - cos_angulo) if cos_angulo > 0 else cos_angulo - custo_re = -erro_re * erro_pos * peso_fator_re - erro_ideal = abs(angulo_testado - angulo) - custo_ideal = peso_ideal * erro_ideal - custo_mapa = (custo_pos + custo_ori + custo_suavidade + custo_tipo_movimento + custo_ideal + custo_re) / 10.0 - if manobrando: - custo_mapa *= 20.0 - - custo_total += custo_mapa - - comando_anterior_copy["angulo"] = angulo_testado - comando_anterior_copy["tipo"] = tipo - - if matriz_concluida: - break - - if custo_total < melhor_custo: - melhor_custo = custo_total - melhor_tipo = tipo - melhor_angulo = angulo_testado - - melhor_trajetoria = simulacoes.get((melhor_tipo, melhor_angulo), []) - mostrar_log(f"📈 HORIZONTE FIXO | COMANDO: {melhor_tipo.name}, Angulo ideal: {round(np.degrees(angulo), 2)}, Melhor angulo: {round(np.degrees(melhor_angulo), 2)}, Custo Total: {round(melhor_custo, 4)}") - return melhor_angulo, melhor_tipo, melhor_trajetoria - - except Exception as e: - mostrar_log(f"❌ Erro no MPC de horizonte fixo: {e}") - - - - # MPC AVANCADO COM PREVISAO DE HORIZONTE - - def compute_horizonte(self, contexto, comando_anterior): - agora = time.time() - self.dt = 0.2 if self.ultima_atualizacao == None else agora - self.ultima_atualizacao - self.ultima_atualizacao = agora - - GPS = contexto.get("GPS", {}) - pos_lat = GPS.get("Latitude", 0) - pos_lon = GPS.get("Longitude", 0) - theta = np.radians(GPS.get("AnguloCarro", 0)) - x, y = self._latlon_to_xy(pos_lat, pos_lon, self.lat0, self.lon0) - angulo_final, tipo_final = self._calcular_melhor_candidato_horizonte( - x, y, theta, - self.visitados_execucao.copy(), - contexto, - comando_anterior - ) - comando = { - "angulo": np.degrees(angulo_final), - "tipo": tipo_final, - "simulacao": [] - } - return comando - - def _calcular_melhor_candidato_horizonte(self, x, y, theta, visitados_sim, contexto, comando_anterior): - idx_alvo = self._corrigir_pontos_visitados(x, y, visitados_sim) - if idx_alvo >= len(self.pontos_info): - return comando_parado() - - ponto_info = self.pontos_info[idx_alvo] - ponto_alvo = ponto_info["xy"] - orient = self.gps_handler.calcular_orientacao(ponto_alvo, (x, y)) - delta_theta = (orient - theta + np.pi) % (2 * np.pi) - np.pi - erro_ori = abs(delta_theta) - angulo_ideal = np.clip(delta_theta, -np.radians(self.angulo_max_graus), np.radians(self.angulo_max_graus)) - - melhor_custo = float("inf") - melhor_tipo = None - melhor_angulo = None - - tipos_validos, angulos_candidatos = self._gerar_angulos_candidatos(angulo_ideal, erro_ori, contexto) - - for tipo in tipos_validos: - for angulo in angulos_candidatos: - #custo, simulacoes = self.simular_passos_recursivo(x, y, theta, self.horizonte_passos, 0, visitados_sim.copy(), contexto, 0, melhor_custo, comando_anterior, angulo_ideal, erro_ori) - custo = self.simular_passos(x, y, theta, self.horizonte_passos, visitados_sim.copy(), contexto, { "angulo": angulo, "tipo": tipo }, 0, melhor_custo, comando_anterior, angulo_ideal) - #print(f"Tipo: {tipo.name}, Angulo: {np.degrees(angulo)}, Simulacoes: {simulacoes}: Custo: {custo}") - #input("⏸️ Pressione Enter para continuar...") - if custo < melhor_custo: - melhor_custo = custo - melhor_tipo = tipo - melhor_angulo = angulo - - return melhor_angulo, melhor_tipo - - def simular_passos(self, x, y, theta, passos_restantes, visitados_sim, contexto, comando, custo_acumulado, custo_melhor, comando_anterior, angulo_ideal): - if passos_restantes == 0: - return custo_acumulado - - tipo = comando["tipo"] - angulo_testado = comando["angulo"] - velocidade = contexto["Carro"].get("Velocidade", 0) - dt = self.dt - - idx_alvo = self._corrigir_pontos_visitados(x, y, visitados_sim.copy()) - ponto_alvo = self.pontos_info[idx_alvo]["xy"] - orient = self.gps_handler.calcular_orientacao(ponto_alvo, (x, y)) - delta_theta = (orient - theta + np.pi) % (2 * np.pi) - np.pi - angulo = np.clip(delta_theta, -np.radians(self.angulo_max_graus), np.radians(self.angulo_max_graus)) - - omega = self.gps_handler.calcular_omega(velocidade, angulo_testado, tipo) - theta_sim = theta + omega * dt - x_sim = x - velocidade * np.cos(theta_sim) * dt - y_sim = y - velocidade * np.sin(theta_sim) * dt - - idx_alvo_sim = self._corrigir_pontos_visitados(x_sim, y_sim, visitados_sim) - ponto_alvo_sim = self.pontos_info[idx_alvo_sim]["xy"] - if np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]]) < self.pontos_info[idx_alvo_sim].get("distanciaMargem", 0.7): - visitados_sim[idx_alvo_sim] = True - orient_sim = self.gps_handler.calcular_orientacao(ponto_alvo_sim, (x_sim, y_sim)) - - erro_pos = np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]]) - erro_ori_sim = self._erro_angular(orient_sim, theta_sim) - - vetor_alvo = np.array([x_sim, y_sim]) - np.array(ponto_alvo_sim) - vetor_alvo_norm = vetor_alvo / np.linalg.norm(vetor_alvo) - vetor_movel = np.array([np.cos(theta_sim), np.sin(theta_sim)]) - cos_angulo = -np.dot(vetor_movel, vetor_alvo_norm) - - delta_angulo = abs(angulo_testado - comando_anterior.get("angulo", 0)) - - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_movimento, peso_ideal = self._calcular_pesos_movimento(contexto, erro_ori_sim, erro_pos) - - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suavidade = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - erro_re = (1 - cos_angulo) if cos_angulo > 0 else cos_angulo - custo_re = -erro_re * erro_pos * peso_fator_re - if passos_restantes == self.horizonte_passos: - custo_tipo_movimento = peso_movimento[tipo] - else: - custo_tipo_movimento = 0 - - erro_ideal = abs(angulo_testado - angulo) - custo_ideal = peso_ideal * erro_ideal - - custo = custo_pos + custo_ori + custo_suavidade + custo_tipo_movimento + custo_ideal + custo_re - - custo_acumulado += custo - - print(f"{passos_restantes} {tipo.name} {round(np.degrees(angulo_testado), 2)}°, iPA: {idx_alvo_sim}, Custo: {round(custo_acumulado, 4)}, Omega: {round(np.degrees(omega), 2)}°, Theta: {round(np.degrees(theta_sim), 2)}°, Ori: {round(np.degrees(orient_sim), 2)}°, E Pos: {round(erro_pos, 3)}, E Ori: {round(np.degrees(erro_ori_sim), 3)}°, F Re: {round(erro_re, 3)}, d°: {round(np.degrees(delta_angulo), 2)}, CP: {round(custo_pos, 4)}, CO: {round(custo_ori, 4)}, CM: {round(custo_tipo_movimento, 4)}, CS: {round(custo_suavidade, 4)}, CR: {round(custo_re, 4)}, CI: {round(custo_ideal, 4)}") - - if custo_acumulado > custo_melhor: - return float('inf') - - novo_comando_anterior = { - "angulo": comando["angulo"], - "tipo": comando["tipo"] - } - - return self.simular_passos(x_sim, y_sim, theta_sim, passos_restantes - 1, visitados_sim, contexto, comando, custo_acumulado, custo_melhor, novo_comando_anterior, angulo_ideal) - - def simular_passos_recursivo(self, x, y, theta, passos_restantes, simulacoes, visitados_sim, contexto, custo_acumulado, custo_melhor, comando_anterior, angulo_ideal, erro_ori): - if passos_restantes == 0: - return custo_acumulado, simulacoes - - velocidade = contexto["Carro"].get("Velocidade", 0) - dt = self.dt - melhor_custo = float("inf") - - tipos_validos, angulos_candidatos = self._gerar_angulos_candidatos(angulo_ideal, erro_ori, contexto) - - for tipo in tipos_validos: - for angulo in angulos_candidatos: - #print(f"Simulando {tipo.name} {np.degrees(angulo)}") - omega = self.gps_handler.calcular_omega(velocidade, angulo, tipo) - theta_temp = theta + omega * dt - x_temp = x + velocidade * np.cos(theta) * dt - y_temp = y + velocidade * np.sin(theta) * dt - visitados_temp = visitados_sim.copy() - - idx_alvo = self._corrigir_pontos_visitados(x_temp, y_temp, visitados_temp) - if idx_alvo >= len(self.pontos_info): - continue - - ponto_alvo = self.pontos_info[idx_alvo]["xy"] - if np.linalg.norm([x_temp - ponto_alvo[0], y_temp - ponto_alvo[1]]) < self.pontos_info[idx_alvo].get("distanciaMargem", 0.7): - visitados_temp[idx_alvo] = True - - orient_sim = self.gps_handler.calcular_orientacao(ponto_alvo, (x_temp, y_temp)) - erro_ori_sim = self._erro_angular(orient_sim, theta_temp) - erro_pos = np.linalg.norm([x_temp - ponto_alvo[0], y_temp - ponto_alvo[1]]) - - vetor_alvo = np.array([x_temp, y_temp]) - np.array(ponto_alvo) - vetor_alvo_norm = vetor_alvo / np.linalg.norm(vetor_alvo) - vetor_movel = np.array([np.cos(theta_temp), np.sin(theta_temp)]) - cos_angulo = -np.dot(vetor_movel, vetor_alvo_norm) - erro_re = (1 - cos_angulo) if cos_angulo > 0 else cos_angulo - - delta_angulo = abs(angulo - comando_anterior.get("angulo", 0)) - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_movimento, peso_ideal = self._calcular_pesos_movimento(contexto, erro_ori_sim, erro_pos) - - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suav = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - custo_mov = peso_movimento[tipo] - custo_re = -erro_re * erro_pos * peso_fator_re - custo_ideal = peso_ideal * abs(angulo - angulo_ideal) - - custo_total = custo_acumulado + custo_pos + custo_ori + custo_suav + custo_mov + custo_re + custo_ideal - - if custo_total > custo_melhor: - continue - - custo, simulacoes = self.simular_passos_recursivo( - x_temp, y_temp, theta_temp, passos_restantes - 1, simulacoes + 1, visitados_temp, contexto, - custo_total, custo_melhor, {"angulo": angulo, "tipo": tipo}, angulo_ideal, erro_ori - ) - - #print(f"{tipo.name} {round(np.degrees(angulo), 2)}°, iPA: {idx_alvo}, Custo: {round(custo_total, 4)}, Omega: {round(np.degrees(omega), 2)}°, Theta: {round(np.degrees(theta), 2)}°, Ori: {round(np.degrees(orient_sim), 2)}°, E Pos: {round(erro_pos, 3)}, E Ori: {round(np.degrees(erro_ori_sim), 3)}°, F Re: {round(erro_re, 3)}, d°: {round(np.degrees(delta_angulo), 2)}, CP: {round(custo_pos, 4)}, CO: {round(custo_ori, 4)}, CM: {round(custo_mov, 4)}, CS: {round(custo_suav, 4)}, CR: {round(custo_re, 4)}, CI: {round(custo_ideal, 4)}") - - if custo < melhor_custo: - melhor_custo = custo - - return melhor_custo, simulacoes - - - - # MPC COM GERACAO DE CANDIDATOS INTELIGENTE - - def compute_inteligente(self, contexto, comando_anterior): - try: - agora = time.time() - self.dt = 0.2 if self.ultima_atualizacao == None else agora - self.ultima_atualizacao - self.ultima_atualizacao = agora - comando = self._processar_mpc_inteligente(contexto, comando_anterior) - mostrar_log(f"Estatisticas MPC: dt = {round(self.dt, 2)} s, freq = {round(1.0 / self.dt, 2)} Hz") - return comando - - except Exception as e: - mostrar_log(f"❌ Erro ao processar compute MPC: {e}") - - def _processar_mpc_inteligente(self, contexto, comando_anterior): - try: - if not self.pontos_info: - return None - GPS = contexto.get("GPS", {}) - pos_lat = GPS.get("Latitude", 0) - pos_lon = GPS.get("Longitude", 0) - theta = np.radians(GPS.get("AnguloCarro", 0)) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - - x, y = self._latlon_to_xy(pos_lat, pos_lon, self.lat0, self.lon0) - - x_temp, y_temp, theta_temp = x, y, theta - - distancia_m = velocidade * self.dt - - self.horizonte = 1.14 - - if distancia_m > 0: - pontos_horizonte = min(int(self.horizonte / (distancia_m)), 50) - else: - pontos_horizonte = 1 - - self.horizonte_passos = pontos_horizonte - #self.horizonte_passos = 5 - - angulo_final = None - tipo_final = None - #self.x_ant = 0 - #self.y_ant = 0 - #self.dist_acumulada = 0 - idx_alvo = contexto.get("Carro", {}).get("IdxProximoPonto", 0) - if idx_alvo >= len(self.pontos_info): - angulo_final, tipo_final = comando_parado() - else: - ponto_info = self.pontos_info[idx_alvo] - ponto_alvo = ponto_info["xy"] - idx_alvo_atual = self._corrigir_pontos_visitados(x, y, self.visitados_execucao, idx_alvo) - print(f"idx_alvo: {idx_alvo}, idx_alvo_visitados: {idx_alvo_atual}") - angulo_final, tipo_final, sim = self._calcular_melhor_candidato_inteligente(ponto_alvo, x_temp, y_temp, theta_temp, self.visitados_execucao, contexto, comando_anterior) - - comando_anterior["angulo"] = angulo_final - comando_anterior["tipo"] = tipo_final - - # Converte os pontos simulados para lat/lon - simulacao_latlon = [] - for sx, sy in sim: - dlat = sy / self.gps_handler.raio_terra - dlon = sx / (self.gps_handler.raio_terra * np.cos(np.radians(self.lat0))) - lat = self.lat0 + np.degrees(dlat) - lon = self.lon0 + np.degrees(dlon) - simulacao_latlon.append([lat, lon]) - - return { - "angulo": np.degrees(angulo_final), - "tipo": tipo_final, - "simulacao": simulacao_latlon - } - - except Exception as e: - mostrar_log(f"❌ Erro ao processar MPC: {e}") - - def _calcular_melhor_candidato_inteligente(self, ponto_alvo, x, y, theta, visitados, contexto, comando_anterior): - try: - orient = self._calcular_orientacao(ponto_alvo, (x, y)) - delta_theta = (orient - theta + np.pi) % (2 * np.pi) - np.pi - erro_ori = abs(delta_theta) - angulo = np.clip(delta_theta, -np.radians(self.angulo_max_graus), np.radians(self.angulo_max_graus)) - - melhor_custo = float('inf') - melhor_tipo = TipoMovimentoDirecional.RodasDianteiras - melhor_angulo = angulo - - tipos_validos, angulos_candidatos = self._gerar_angulos_candidatos_inteligente(angulo, erro_ori, contexto) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - distancia_m = velocidade * self.dt - #manobrando = contexto.get("Carro", {}).get("ManobrandoEntreRuas", False) - #matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", [[]]) - - simulacoes = {} - - # 1. Analisa profundidade média por linha - #linhas_info = analisar_linhas_por_profundidade(matriz_custo, "distancia_m", contexto.get("VisualWorker", {}).get("Camera", {}).get("FovH", 0.7)) - - for tipo in tipos_validos: - for angulo_testado in angulos_candidatos: - custo_total = 0.0 - x_sim, y_sim, theta_sim = x, y, theta - self.x_ant, self.y_ant = 0.0, 0.0 - chave = (tipo, angulo_testado) - simulacoes[chave] = [] - comando_anterior_copy = deepcopy(comando_anterior) - pontos_visitados = deepcopy(visitados) - omega = self._calcular_omega(velocidade, angulo_testado, tipo) - - for passo in range(self.horizonte_passos): - old_theta = theta_sim - theta_sim += omega * self.dt - x_sim += np.sin(theta_sim) * distancia_m - y_sim += np.cos(theta_sim) * distancia_m - - simulacoes[chave].append((x_sim, y_sim)) - - #delta_theta = (old_theta - theta_sim + np.pi) % (2 * np.pi) - np.pi - #largura = contexto.get("Equipamento", {}).get("largura", 0.85) - #custo_espaco, matriz_concluida = self._simular_trajetoria_matriz_custo(matriz_custo, linhas_info, tipo, angulo_testado, distancia_m, delta_theta, largura) - #custo_total += custo_espaco - #self.x_ant += distancia_m * np.sin(-delta_theta) - #self.y_ant += distancia_m * np.cos(delta_theta) - - # Avaliação final da posição no final da simulação - idx_alvo_sim = self._corrigir_pontos_visitados(x_sim, y_sim, pontos_visitados) - ponto_alvo_sim = self.pontos_info[idx_alvo_sim]["xy"] - orient_sim = self._calcular_orientacao((x_sim, y_sim), ponto_alvo_sim) - orient_sim = (orient_sim + np.pi) % (2 * np.pi) - - erro_pos = np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]]) - erro_ori_sim = self._erro_angular(orient_sim, theta_sim) - - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_movimento, peso_ideal = self._calcular_pesos_movimento(contexto, erro_ori_sim, erro_pos) - - vetor_alvo = np.array(ponto_alvo_sim) - np.array([x_sim, y_sim]) - vetor_alvo_norm = vetor_alvo / np.linalg.norm(vetor_alvo) - vetor_movel = np.array([np.cos(theta_sim), np.sin(theta_sim)]) - cos_angulo = -np.dot(vetor_movel, vetor_alvo_norm) - delta_angulo = abs(angulo_testado - comando_anterior_copy.get("angulo", 0)) - - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suavidade = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - custo_tipo_movimento = peso_movimento[tipo] - erro_re = (1.0 - cos_angulo) if cos_angulo > 0 else cos_angulo - custo_re = -erro_re * erro_pos * peso_fator_re - erro_ideal = abs(angulo_testado - angulo) - custo_ideal = peso_ideal * erro_ideal - custo_mapa = (custo_pos + custo_ori + custo_suavidade + custo_tipo_movimento + custo_ideal + custo_re) - - custo_total += custo_mapa - - comando_anterior_copy["angulo"] = angulo_testado - comando_anterior_copy["tipo"] = tipo - - #if matriz_concluida: - # break - - #print(f"Passo: {passo}, Alvo: {idx_alvo_sim}, Distancia: {((passo + 1) * distancia_m):.2f} m, Theta: {theta_sim:.2f}°, DX: {(x - x_sim):.2f} m, DY: {(y - y_sim):.2f} m, y_sim: {y_sim:.4f}, x_sim: {x_sim:.4f}, Tipo: {tipo.name}, Angulo: {np.degrees(angulo_testado):.2f}, custo: {custo_total}") - #mostrar_log(f"Omega: {np.degrees(omega):.2f}°, Ori: {np.degrees(orient_sim):.2f}°, E Ori: {np.degrees(erro_ori_sim):.3f}°, E Pos: {erro_pos:.3f}, F Re: {erro_re:.3f}, d°: {np.degrees(delta_angulo):.2f}, CM: {custo_mapa:.4f}, CP: {custo_pos:.4}, CO: {custo_ori:.4f}, CT: {custo_tipo_movimento:.4f}, CS: {custo_suavidade:.4f}, CR: {custo_re:.4f}, CI: {custo_ideal:.4f}") - - if custo_total < melhor_custo: - melhor_custo = custo_total - melhor_tipo = tipo - melhor_angulo = angulo_testado - - melhor_trajetoria = simulacoes.get((melhor_tipo, melhor_angulo), []) - mostrar_log(f"📈 HORIZONTE FIXO INTELIGENTE | COMANDO: {melhor_tipo.name}, Angulo ideal: {np.degrees(angulo):.2f}, Melhor angulo: {np.degrees(melhor_angulo):.2f}, Custo Total: {melhor_custo:.4f}") - return melhor_angulo, melhor_tipo, melhor_trajetoria - - except Exception as e: - mostrar_log(f"❌ Erro no MPC de horizonte fixo inteligente: {e}") - - def _gerar_angulos_candidatos_inteligente(self, angulo_ideal_rad, erro_ori, contexto): - def clamp(v, vmin, vmax): - return max(vmin, min(vmax, v)) - - CARRO = contexto.get("Carro", {}) - status = CARRO.get("Status", 0) - manobrando = CARRO.get("ManobrandoEntreRuas", False) - - if manobrando or status in [ StatusCarroMapa.EntrandoRua, StatusCarroMapa.SaindoRua, StatusCarroMapa.Manobrando ]: - tipos_validos = [ TipoMovimentoDirecional.MovimentoArco ] - else: - tipos_validos = [ TipoMovimentoDirecional.RodasDianteiras, TipoMovimentoDirecional.MovimentoArco ] - - erro_ori_deg = np.degrees(erro_ori) - angulo_ideal_deg = np.degrees(angulo_ideal_rad) - - # Passo varia conforme erro angular - if erro_ori_deg > 10: - passo = 5.0 - faixa = 15.0 - elif erro_ori_deg > 5: - passo = 2.5 - faixa = 7.5 - else: - passo = 1.5 - faixa = 4.5 - - # Geração em torno do ideal - candidatos_graus = list(np.arange(angulo_ideal_deg - faixa, angulo_ideal_deg + faixa + 0.1, passo)) - - # Clamping e eliminação de duplicatas - candidatos_radianos = sorted(set( - np.radians(clamp(g, -self.angulo_max_graus, self.angulo_max_graus)) - for g in (candidatos_graus) - )) - - #print(f"Ideal: {round(angulo_ideal_deg, 2)}°, Erro Ori: {round(erro_ori_deg, 2)}°, Obstáculos: {len(obstaculos)}, Candidatos: {[round(np.degrees(a), 2) for a in candidatos_radianos]}") - return tipos_validos, candidatos_radianos - - - - # MPC COM GERACAO DE CANDIDATOS RECEDING - - def compute_receding(self, contexto, comando_anterior): - try: - agora = time.time() - self.dt = 0.25 if self.ultima_atualizacao is None else agora - self.ultima_atualizacao - #self.dt = max(min(self.dt, 0.4), 0.1) - _dt = self.dt - freq_tick = 1.0 / _dt - #self.dt = 0.5 - self.ultima_atualizacao = agora - comando = self._processar_mpc_receding(contexto, comando_anterior) - - t_exec = max((time.time() - self.ultima_atualizacao), 1e-3) - if comando['erro']: - mostrar_log(f"🧭 Direcional MPC | Erro: {comando['erro']} | Parada: {comando['parada_necessaria']} | Movimento: {TipoMovimentoDirecional(comando['tipo']).name} | Ângulo: {comando['angulo']}° | Horizonte: {len(comando['simulacao'])} | dt: {_dt:.2f} s | freq = {(freq_tick):.2f} Hz | t_exec: {t_exec:.2} s | f_exec: {(1.0 / t_exec):.2f} Hz") - return comando - - except Exception as e: - mostrar_log(f"❌ Erro ao processar compute MPC: {e}") - - def _processar_mpc_receding(self, contexto, comando_anterior): - t_init = time.time() - - now = time.perf_counter - t0 = now() - SLA_MS = getattr(self, "_mpc_sla_ms", 200.0) # 200 ms ⇒ 5 Hz - HEAD_MS = getattr(self, "_mpc_headroom_ms", 25.0) - deadline = t0 + (SLA_MS - HEAD_MS) / 1000.0 - - try: - if not self.pontos_info: - return None - - GPS = contexto.get("GPS", {}) - pos_lat = GPS.get("Latitude", 0) - pos_lon = GPS.get("Longitude", 0) - pos_theta = GPS.get("AnguloCarro", 0) - pos_passos_atraso = GPS.get("PassosAtraso", 0) - pos_timestamp = GPS.get("Timestamp", 0.0) - pos_latencia = now() - pos_timestamp - - LAT_MAX = 2.0 - if pos_latencia >= LAT_MAX: - mostrar_log(f"[GPS] Grande latencia entre coordenadas detectado ({pos_latencia:.3f}/{LAT_MAX}): parando por fallback") - return self._comando_fallback_hot_stop(comando_anterior, latencia=pos_latencia) - if (pos_passos_atraso > 3): - mostrar_log(f"[GPS] Atraso detectado de {(pos_passos_atraso / 3.0):.1f} passos, {pos_latencia:.3f} s") - - x, y = self.gps_handler.converter_latlon_para_xz(pos_lat, pos_lon) - theta = np.radians(pos_theta) - x0, y0, t0 = x, y, theta - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - status_carro = contexto.get("Carro", {}).get("Status", StatusCarroMapa.Parado.value) - idx_proximo_ponto_real = contexto.get("Carro", {}).get("IdxProximoPonto", 0) - idx_ponto_alvo = contexto.get("Carro", {}).get("IdxPontoAlvo", 0) - Nmax = 20 if status_carro == StatusCarroMapa.CaminhandoRua.value else 40 - - # Comando de hold (se não tiver buffer de comandos aplicados) - u_hold = { - "tipo": comando_anterior.get("tipo"), - "angulo": np.radians(comando_anterior.get("angulo", 0.0)), - "v": velocidade, - "omega": self.gps_handler.calcular_omega(velocidade, np.radians(comando_anterior.get("angulo", 0.0)), comando_anterior.get("tipo")) - } - # Opcional: sequência real de comandos aplicados durante a latência (se você tiver) - cmd_seq = None # ou algo como [(0.12, u1), (0.08, u2), ...] - x, y, theta, pts_visitados = self.corrigir_pose_por_latencia( - x, y, theta, self.visitados_execucao, - latency_s=min(pos_latencia, LAT_MAX), - dt=self.dt, - nova_posicao_fn=self._nova_posicao, - u_hold=u_hold, - cmd_seq=cmd_seq, - time_left_ms=lambda: (deadline - now()) * 1000.0, - calc_omega_fn=self.gps_handler.calcular_omega - ) - if self._verifica_tempo_maximo_execucao(t_init, f"corrigir_pose_latencia"): - return self._comando_fallback_hot_stop(comando_anterior) - idx_alvo_correcao = self._corrigir_pontos_visitados(x, y, pts_visitados, idx_proximo_ponto_real) # marca pontos antigos como visitados - - distancia_m = velocidade * self.dt - ultimo_ponto = idx_proximo_ponto_real >= len(self.pontos_info) - self.tempo_execucao_local = contexto.get("Carro", {}).get("TempoEntreComandos", 0.5) - if ultimo_ponto: - self.passos_horizonte_local = 1 - self.qtd_comandos_sucessivos = 3 - elif distancia_m > 0: - passos_total = min(int(self.horizonte / distancia_m), Nmax) - self.passos_horizonte_local = max(1, math.ceil(self.tempo_execucao_local / self.dt)) - self.qtd_comandos_sucessivos = max(1, passos_total // self.passos_horizonte_local) - else: - self.passos_horizonte_local = 0 - self.qtd_comandos_sucessivos = 0 - - t_0 = time.time() - angulo_anterior = np.radians(comando_anterior.get("angulo", 0)) - tipo_anterior = TipoMovimentoDirecional(comando_anterior.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value)) - - simulacao_latlon = [] - t_2 = time.time() - - #mostrar_log(f"previsao_futura em {(t_1 - t_0):.4f}s, correcao_pontos_visitados em {(t_2 - t_1):.4f}") - - if ultimo_ponto: - angulo_final, tipo_final = comando_parado() - parada_necessaria = True - else: - candidatos_ativos = [{ - "x": x, "y": y, "theta": theta, - "custo": 0.0, - "comandos": [(tipo_anterior, angulo_anterior)], - "trajetoria": [], - "visitados": deepcopy(pts_visitados), - "inicial": True - }] - - t0 = time.time() - for passo in range(self.qtd_comandos_sucessivos): - #mostrar_log(f"simulacao_horizonte passo {passo}") - if self._verifica_tempo_maximo_execucao(t_init, f"simulacao_horizonte passo {passo}"): - return self._comando_fallback_hot_stop(comando_anterior) - t1 = time.time() - novos_candidatos = [] - for candidato in candidatos_ativos: - t1_0 = time.time() - x_atual, y_atual, theta_atual = candidato["x"], candidato["y"], candidato["theta"] - visitados = deepcopy(candidato["visitados"]) - cmd_anterior = { - "tipo": candidato["comandos"][-1][0], - "angulo": candidato["comandos"][-1][1], - } - idx_alvo = self._corrigir_pontos_visitados(x_atual, y_atual, visitados) - ponto_alvo = self.pontos_info[idx_alvo]["xy"] - t2 = time.time() - tipos, angs, custos_candidatos = self._gerar_angulos_candidatos_receding(ponto_alvo, (x_atual, y_atual, theta_atual), (x, y, theta), contexto) - t3 = time.time() - - #mostrar_log(f"corrigir_pontos_visitados em {(t2 - t1_0):.4f}s, gerar_angulos_candidatos em {(t3 - t2):.4f}s") - - def simular_e_gerar(candidato, tipo, angulo): - if self._verifica_tempo_maximo_execucao(t_init, f"simular_e_gerar, tipo {tipo.name}, angulo {np.degrees(angulo):.2f}"): - return self._comando_fallback_hot_stop(comando_anterior) - try: - custo, sim, valido = self._simular_passo(x_atual, y_atual, theta_atual, tipo, angulo, custos_candidatos, cmd_anterior, contexto, deepcopy(visitados)) - #print(f"{tipo.name} | angulo: {np.degrees(angulo):.2f} : Custo: {custo}") - x_f, y_f, theta_f = sim[-1] - if valido: - return { - "x": x_f, "y": y_f, "theta": theta_f, - "custo": candidato["custo"] + custo, - "comandos": candidato["comandos"] + [(tipo, angulo)], - "trajetoria": candidato["trajetoria"] + sim, - "visitados": deepcopy(visitados), - "inicial": False - } - else: - return None - except Exception as e: - mostrar_log(f"Erro ao simular e gerar passo para {tipo.name} | {np.degrees(angulo):.2f}: {e}") - return None - - futures = [self.executor.submit(simular_e_gerar, candidato, tipo, angulo) for tipo in tipos for angulo in angs] - try: - for fut in as_completed(futures, timeout=0.3): - try: - novo = fut.result(timeout=0.05) - if novo: - novos_candidatos.append(novo) - except Exception as e: - mostrar_log(f"⚠️ Timeout ou erro em future: {e}") - except Exception as e: - mostrar_log(f"Uma tarefa estourou timeout durante o processo de simular passo no horizonte: {e}") - - t4 = time.time() - # Filtro opcional: limitar para os N melhores candidatos - t5 = time.time() - candidatos_ativos = self._selecionar_melhores(novos_candidatos, N=5) - t6 = time.time() - candidatos_ativos = self._filtrar_por_margem_angular(candidatos_ativos, margem_graus=2.0) - t7 = time.time() - #mostrar_log(f"loop_candidatos em {(t5 - t1):.4f}s, melhores em {(t6 - t5):.4f}s, margem em {(t7 - t6):.4f}s") - #print("Melhores candidatos filtrados:") - #for i, c in enumerate(candidatos_ativos): - # comando = c["comandos"][-1] if c["comandos"] else ("-", 0) - # tipo = comando[0] - # angulo = np.degrees(comando[1]) - # print(f"{i+1}. Tipo: {tipo.name if hasattr(tipo, 'name') else tipo}, Angulo: {round(angulo, 2)}, Custo: {round(c['custo'], 4)}") - #t5 = time.time() - #print(f"Passo {passo} simulado em {t5 - t1} segundos") - - t100 = time.time() - #print(f"Simulacao completa: {t100 - t0} segundos") - candidatos_validos = [c for c in candidatos_ativos if not c.get("inicial", False)] - if len(candidatos_validos) > 0: - try: - melhor = min(candidatos_validos, key=lambda c: c["custo"]) - except Exception as e: - mostrar_log(f"Erro ao selecionar melhor candidato: {e}") - melhor = None - else: - melhor = None - #comandos_formatados = [(tipo.name, round(float(np.degrees(angulo)), 2)) for tipo, angulo in melhor["comandos"]] - #print(comandos_formatados) - #trajetoria_foramtada = [(round(float(_x), 2), round(float(_y), 2), round(float(np.degrees(_theta)), 2)) for _x, _y, _theta in melhor["trajetoria"]] - #print(trajetoria_foramtada) - #self.visualizador.atualizar(melhor["trajetoria"]) - parada_necessaria = melhor is None - if not parada_necessaria: - _comandos = melhor.get("comandos", []) - if len(_comandos) == 0: - pass - else: - idx_cmd = 0 if len(_comandos) == 1 else 1 - tipo_final, angulo_final = _comandos[idx_cmd] - simulacao_latlon = list(self.gps_handler.converter_trajetoria_para_latlon(melhor["trajetoria"]) or []) - simulacao_latlon.insert(0, (pos_lat, pos_lon, pos_theta)) - else: - angulo_final = 0 - tipo_final = TipoMovimentoDirecional.RodasDianteiras - simulacao_latlon = [] - #print(f"Simulacao: {len(simulacao_latlon)}") - _cmd = { - "enviar_comando": True, - "parada_necessaria": parada_necessaria, - "erro": False, - "latencia": pos_latencia, - "angulo": float(round(np.degrees(angulo_final), 2)), - "tipo": tipo_final.value, - "simulacao": simulacao_latlon - } - return _cmd - - except Exception as e: - mostrar_log(f"❌ Erro ao processar MPC: {e}") - return self._comando_fallback_hot_stop(comando_anterior) - - def _verifica_tempo_maximo_execucao(self, t_init, processo): - limite = 1.0 / 5.0 - delta = time.time() - t_init - hot_stop = delta > limite - if hot_stop: - mostrar_log(f"🚨 Tempo maximo de execucao excedido: {delta}/{limite}, processo: {processo}") - self.executor.shutdown(wait=False) - self.executor = ThreadPoolExecutor(max_workers=20) - return hot_stop - - def _comando_fallback_hot_stop(self, comando_anterior, latencia=0): - _cmd = { - "enviar_comando": True, - "parada_necessaria": True, - "erro": True, - "latencia": latencia, - "angulo": comando_anterior.get("angulo", 0), - "tipo": comando_anterior.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value), - "simulacao": [] - } - return _cmd - - def _gerar_angulos_candidatos_receding(self, ponto_alvo, ponto_atual, ponto_ref, contexto): - try: - orient = self.gps_handler.calcular_orientacao(ponto_alvo, ponto_atual) - delta_theta = (orient - ponto_atual[2] + np.pi) % (2 * np.pi) - np.pi - angulo_ideal_rad = np.clip(delta_theta, -np.radians(self.angulo_max_graus), np.radians(self.angulo_max_graus)) - angulo_ideal_deg = np.degrees(angulo_ideal_rad) - - CARRO = contexto.get("Carro", {}) - status = CARRO.get("Status", 0) - manobrando = CARRO.get("ManobrandoEntreRuas", False) - - if manobrando or status in [ StatusCarroMapa.EntrandoRua, StatusCarroMapa.SaindoRua, StatusCarroMapa.Manobrando ]: - tipos_validos = [ TipoMovimentoDirecional.MovimentoArco ] - elif np.degrees(delta_theta) > 10.0: - tipos_validos = [ TipoMovimentoDirecional.RodasDianteiras, TipoMovimentoDirecional.MovimentoArco ] - else: - tipos_validos = [ TipoMovimentoDirecional.RodasDianteiras ] - - dados_matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", {}) - matriz_custo_valida = dados_matriz_custo.get("Valida", False) - regra_matriz_custo = contexto.get("RegrasAtivas", {}).get("matriz_custo", False) - filtrar_matriz = matriz_custo_valida and regra_matriz_custo - - angulos_raw = self._gerar_candidatos_brutos(angulo_ideal_deg, filtrar_matriz) - #print(f"Angulos Brutos: {[round(float(a), 2) for a in angulos_raw]}") - tipos_final, angulos_final, custos_candidatos = self._filtrar_candidatos_validos_por_matriz(filtrar_matriz, tipos_validos, angulos_raw, angulo_ideal_rad, ponto_atual, ponto_ref, contexto) - #print(f"Angulos Filtrados Matriz: {[round(float(np.degrees(a)), 2) for a in angulos_final]}") - angulos_final = self._uniformizar_angulos_candidatos(angulos_final, angulo_ideal_rad, 10) - #print(f"Angulos Uniformizados: {[round(float(np.degrees(a)), 2) for a in angulos_final]}") - - return tipos_final, angulos_final, custos_candidatos - except Exception as e: - mostrar_log(f"❌ Erro ao gerar candidatos receding com contexto visual: {e}") - return [], [] - - def _gerar_candidatos_brutos(self, angulo_ideal_deg, filtrar_matriz_custo): - try: - # 1. Geração em torno do ideal - if abs(angulo_ideal_deg) > 10: - passo_ideal = 5.0 - passo_total = 3.0 - faixa_ideal = 15.0 - elif abs(angulo_ideal_deg) > 5: - passo_ideal = 2.5 - passo_total = 7.5 - faixa_ideal = 7.5 - else: - passo_ideal = 1.5 - passo_total = 10.0 - faixa_ideal = 4.5 - - angulos_ideais = list(np.arange(angulo_ideal_deg - faixa_ideal, - angulo_ideal_deg + faixa_ideal + 0.1, - passo_ideal)) - angulos_ideais = sorted(set(np.clip(angulos_ideais, -self.angulo_max_graus, self.angulo_max_graus))) - - #print(f"Angulos ideais: {[f'{float(a):.2f}' for a in angulos_ideais]}") - - # 2. Se for com matriz de custo, gera todo o sweep - if filtrar_matriz_custo: - sweep = list(np.arange(-self.angulo_max_graus, self.angulo_max_graus + 0.1, passo_total)) - - # 3. Remove ângulos muito próximos dos ideais - def esta_proximo(g, lista, margem=1.5): - return any(abs(g - i) < margem for i in lista) - - sweep_filtrado = [g for g in sweep if not esta_proximo(g, angulos_ideais)] - #print(f"Sweep filtrado: {[f'{float(a):.2f}' for a in sweep_filtrado]}") - candidatos_graus = sorted(set(angulos_ideais + sweep_filtrado)) - #print(f"Candidatos graus: {[f'{float(a):.2f}' for a in candidatos_graus]}") - else: - candidatos_graus = angulos_ideais - - return candidatos_graus - - except Exception as e: - mostrar_log(f"❌ Erro ao gerar candidatos brutos: {e}") - return [] - - def _filtrar_candidatos_validos_por_matriz(self, filtrar_matriz, tipos, angulos_deg, angulo_ideal_rad, p_atual, p_ref, contexto): - pesos = self._calcular_pesos_movimento(contexto, abs(angulo_ideal_rad)) - peso_angulo_ideal = pesos[4] - try: - angulos_rad = [np.radians(g) for g in angulos_deg] - dados_matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", {}) - if isinstance(dados_matriz_custo, dict): - custo_grid = dados_matriz_custo.get("Custo", None) - else: - custo_grid = dados_matriz_custo - - if (not filtrar_matriz) or (custo_grid is None) or (np.size(custo_grid) == 0): - custos_candidatos = {} - for tipo in tipos: - for ang in angulos_rad: - erro_ideal = abs(ang - angulo_ideal_rad) - custo_ideal = peso_angulo_ideal * erro_ideal - custos_candidatos[(tipo, ang)] = custo_ideal - return tipos, angulos_rad, custos_candidatos - - tipos_validos = [] - angulos_validos = [] - - distancias_ref = dados_matriz_custo.get("DistanciasRef", None) if isinstance(dados_matriz_custo, dict) else None - if distancias_ref is not None and len(distancias_ref) > 1: - distancia_sim_m = float(distancias_ref[-2]) - else: - distancia_sim_m = 1.0 - largura = contexto.get("Equipamento", {}).get("largura", 0.85) - velocidade = contexto.get("Carro", {}).get("Velocidade", 1.0) - - tarefas = [] - custos_candidatos = {} - - def avaliar(tipo, ang): - #print(f"{tipo.name} | angulo: {np.degrees(ang):.2f} : Avaliando") - traj = self._simular_trajetoria_curta(p_atual, tipo, ang, velocidade, distancia_sim_m) - #print(f"{tipo.name} | angulo: {np.degrees(ang):.2f} : pontos simulacao: {len(traj)}") - custo, valido = self._avaliar_trajetoria_matriz_custo(tipo, ang, traj, p_ref, dados_matriz_custo, largura) - #print(f"{tipo.name} | angulo: {np.degrees(ang):.2f} : valido {valido}, custo: {custo:.4f}") - if valido: - erro_ideal = abs(ang - angulo_ideal_rad) - custo_ideal = peso_angulo_ideal * erro_ideal - return tipo, ang, custo + custo_ideal - return None - - for tipo in tipos: - for ang in angulos_rad: - tarefas.append(self.executor.submit(avaliar, tipo, ang)) - - try: - for fut in as_completed(tarefas, timeout=0.3): - try: - res = fut.result(timeout=0.05) - if res: - tipo, ang, custo = res - tipos_validos.append(tipo) - angulos_validos.append(ang) - chave = (tipo.value, round(float(np.degrees(ang)), 2)) - custos_candidatos[chave] = custo - except Exception as e: - mostrar_log(f"⚠️ Timeout ou erro em future: {e}") - except Exception as e: - mostrar_log(f"Uma tarefa estourou timeout durante o processo de filtrar candidatos validos na matriz de custo: {e}") - - return tipos_validos, angulos_validos, custos_candidatos - except Exception as e: - mostrar_log(f"❌ Erro ao filtrar candidatos por matriz: {e}") - return [], [], {} - - def _simular_trajetoria_curta(self, p_atual, tipo, angulo, velocidade, dist_min): - try: - traj = [] - distancia_m = velocidade * self.dt - if distancia_m <= 0.001: - return [] - - omega = self.gps_handler.calcular_omega(velocidade, angulo, tipo) - - x_temp, y_temp, theta_temp = p_atual[0], p_atual[1], p_atual[2] - - passos = math.ceil(dist_min / distancia_m) - - for _ in range(passos): - x_temp, y_temp, theta_temp = self._nova_posicao(x_temp, y_temp, theta_temp, omega, velocidade, tipo, angulo) - traj.append((x_temp, y_temp, theta_temp)) - - return traj - except Exception as e: - mostrar_log(f"❌ Erro na simulação curta: {e}") - return [] - - def _avaliar_trajetoria_matriz_custo(self, tipo, ang, trajetoria, p_ref, dados_matriz_custo, largura_equipamento): - try: - matriz_custo = dados_matriz_custo.get("Custo", None) - matriz_nav = dados_matriz_custo.get("Navegavel", None) - if (matriz_custo is None) or (np.size(matriz_custo) == 0) or not trajetoria: - return float("inf"), False - - altura = len(matriz_custo) - largura = len(matriz_custo[0]) - custo_total = 0.0 - celulas_atravessadas = 0 - - distancias_y = dados_matriz_custo.get("DistanciasRef", [])[::-1] - escalas_ref = dados_matriz_custo.get("EscalasX", [])[::-1] - - distancia_min_m = distancias_y[0] if len(distancias_y) > 0 else 0.6 - - for x, y, theta in trajetoria: - x_rel, y_rel = self.gps_handler.converter_para_referencial_robo(x, y, p_ref[0], p_ref[1], p_ref[2]) - if y_rel < distancia_min_m: - #print(f"{tipo.name} | angulo: {np.degrees(ang):.2f} : descartando, x: {x:.4f}, x_rel: {x_rel:.4f}, y: {y:.4f}, y_rel: {y_rel:.4f}, t: {theta:.4f}, d_min: {distancia_min:.4f}") - continue - - # Busca binária na profundidade - idx = bisect_right(distancias_y, y_rel) - if idx >= altura: - idx = altura - 1 - if idx < 0: - idx = 0 - #print(f"{tipo.name} | angulo: {np.degrees(ang):.2f} : x: {x:.4f}, x_rel: {x_rel:.4f}, y: {y:.4f}, y_rel: {y_rel:.4f}, t: {theta:.4f}, idx: {idx}, distancia: {(distancias_y[idx] if idx > -1 else 0):.4f}") - if idx < 0 or idx >= altura: - continue # fora da matriz - - idx = altura - idx - - escala_x = escalas_ref[idx] - largura_total = escala_x * largura - colunas_ocupadas = int(np.ceil(largura_equipamento / escala_x)) - colunas_por_lado = colunas_ocupadas // 2 - - # Se a matriz vai de -largura_total/2 (esquerda) até +largura_total/2 (direita) - j_central = int((x_rel + largura_total / 2) / escala_x) - - for j in range(j_central - colunas_por_lado, j_central + colunas_por_lado + 1): - if 0 <= j < largura: - celulas_atravessadas += 1 - custo_total += matriz_custo[idx][j] - navegavel = matriz_nav[idx][j] - if not navegavel: - return custo_total, False - custo_total = custo_total / max(1, celulas_atravessadas) - return custo_total, True - - except Exception as e: - mostrar_log(f"❌ Erro ao avaliar trajetoria na matriz: {e}") - return float("inf"), False - - def _uniformizar_angulos_candidatos(self, angulos_validos, angulo_ideal_rad, max_candidatos=9): - try: - if len(angulos_validos) <= max_candidatos: - return angulos_validos - - extremos = [] - rad_min = -np.radians(self.angulo_max_graus) - rad_max = np.radians(self.angulo_max_graus) - - if rad_min in angulos_validos: - extremos.append(rad_min) - if 0.0 in angulos_validos: - extremos.append(0.0) - if rad_max in angulos_validos: - extremos.append(rad_max) - if angulo_ideal_rad in angulos_validos and angulo_ideal_rad not in extremos: - extremos.append(angulo_ideal_rad) - - restantes = [a for a in angulos_validos if a not in extremos] - restantes.sort() - - qtd_restantes = max_candidatos - len(extremos) - if qtd_restantes <= 0: - return sorted(extremos[:max_candidatos]) - - # Distribuição uniforme usando linspace para evitar perdas - indices = np.linspace(0, len(restantes) - 1, qtd_restantes).astype(int) - selecionados = [restantes[i] for i in indices] - - #print(f"Candidatos uniformizados de {len(angulos_validos)} para {len(extremos + selecionados)}") - - return sorted(set(extremos + selecionados)) - - except Exception as e: - mostrar_log(f"❌ Erro ao uniformizar ângulos: {e}") - return angulos_validos - - def _selecionar_melhores(self, candidatos: list, N: int = 10) -> list: - try: - if not candidatos: - return [] - - # Ordena pelo custo total (menor primeiro) - candidatos_ordenados = sorted(candidatos, key=lambda c: c.get("custo", float('inf'))) - - # Retorna os N melhores - return candidatos_ordenados[:N] - except Exception as e: - mostrar_log(f"❌ Erro ao selecionar melhores candidatos: {e}") - return [] - - def _filtrar_por_margem_angular(self, candidatos, margem_graus=2.0): - """Mantém apenas o melhor candidato em cada margem angular.""" - selecionados = [] - angulos_escolhidos = [] - for c in candidatos: - # Pega o último ângulo do comando - if not c["comandos"]: - continue - _, angulo = c["comandos"][-1] - # Se não tem nada próximo, adiciona - if not any(abs(np.degrees(angulo) - np.degrees(a)) < margem_graus for a in angulos_escolhidos): - selecionados.append(c) - angulos_escolhidos.append(angulo) - return selecionados - - def _simular_passo(self, x, y, theta, tipo, angulo_testado, custos_candidatos, comando_anterior, contexto, visitados): - # Custo pode variar de 0 ~ 13, em situacoes mais extremas, por passo - try: - custo_total = 0.0 - x_sim, y_sim, theta_sim = x, y, theta - self.x_ant, self.y_ant = 0.0, 0.0 - chave = (tipo.value, round(float(np.degrees(angulo_testado)), 2)) - simulacoes = [] - comando_anterior_copy = deepcopy(comando_anterior) - pontos_visitados = deepcopy(visitados) - velocidade = contexto.get("Carro", {}).get("Velocidade", 0.0) - angulo_caminho = np.radians(contexto.get("Carro", {}).get("AnguloCaminho", 0.0)) - status_carro = StatusCarroMapa(contexto.get("Carro", {}).get("Status", StatusCarroMapa.Parado.value)) - dentro_corredor = contexto.get("Carro", {}).get("DentroCorredor", False) - #omega_bkp = self.gps_handler.calcular_omega_bkp(velocidade, angulo_testado, tipo) - omega = self.gps_handler.calcular_omega(velocidade, angulo_testado, tipo) - #print(f"Omega novo: {omega}, Omega antigo: {omega_bkp}, Velocidade: {velocidade}, Angulo: {angulo_testado}, Tipo: {tipo.name}") - custo_visual_worker = custos_candidatos.get(chave, 0.0) - - for passo in range(self.passos_horizonte_local): - try: - #old_theta = theta_sim - x_sim, y_sim, theta_sim = self._nova_posicao(x_sim, y_sim, theta_sim, omega, velocidade, tipo, angulo_testado) - - simulacoes.append((x_sim, y_sim, theta_sim)) - - idx_alvo_sim = self._corrigir_pontos_visitados(x_sim, y_sim, pontos_visitados) - ponto_alvo_sim = self.pontos_info[idx_alvo_sim]["xy"] - orient_sim = self.gps_handler.calcular_orientacao((x_sim, y_sim), ponto_alvo_sim) - orient_sim = (orient_sim + np.pi) % (2 * np.pi) - - erro_pos = np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]]) - peso_erro_orientacao_caminho = 0.3 if status_carro == StatusCarroMapa.CaminhandoRua and dentro_corredor else 0.7 - erro_ori_sim = self._erro_angular(orient_sim, theta_sim, angulo_caminho, peso_erro_orientacao_caminho) - - pesos = self._calcular_pesos_movimento(contexto, erro_ori_sim) - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_movimento = pesos[0], pesos[1], pesos[2], pesos[3], pesos[5] - - vetor_alvo = np.array(ponto_alvo_sim) - np.array([x_sim, y_sim]) - vetor_alvo_norm = vetor_alvo / np.linalg.norm(vetor_alvo) - vetor_movel = np.array([np.cos(theta_sim), np.sin(theta_sim)]) - cos_angulo = -np.dot(vetor_movel, vetor_alvo_norm) - delta_angulo = abs(angulo_testado - comando_anterior_copy.get("angulo", 0)) - - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suavidade = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - custo_tipo_movimento = peso_movimento[tipo] - erro_re = (1.0 - cos_angulo) if cos_angulo > 0 else cos_angulo - custo_re = -erro_re * erro_pos * peso_fator_re - custo_mapa = (custo_pos + custo_ori + custo_suavidade + custo_tipo_movimento + custo_re + custo_visual_worker) - - custo_total += custo_mapa - - comando_anterior_copy["angulo"] = angulo_testado - comando_anterior_copy["tipo"] = tipo - - #if matriz_concluida: - # break - - #print(f"Passo: {passo}, Alvo: {idx_alvo_sim}, Distancia: {((passo + 1) * distancia_m):.2f} m, Theta: {theta_sim:.2f}°, DX: {(x - x_sim):.2f} m, DY: {(y - y_sim):.2f} m, y_sim: {y_sim:.4f}, x_sim: {x_sim:.4f}, Tipo: {tipo.name}, Angulo: {np.degrees(angulo_testado):.2f}, custo: {custo_total}") - #mostrar_log(f"Omega: {np.degrees(omega):.2f}°, Ori: {np.degrees(orient_sim):.2f}°, E Ori: {np.degrees(erro_ori_sim):.3f}°, E Pos: {erro_pos:.3f}, F Re: {erro_re:.3f}, d°: {np.degrees(delta_angulo):.2f}, CM: {custo_mapa:.4f}, CP: {custo_pos:.4}, CO: {custo_ori:.4f}, CT: {custo_tipo_movimento:.4f}, CS: {custo_suavidade:.4f}, CR: {custo_re:.4f}") - - except Exception as e: - mostrar_log(f"❌ Erro ao simular passo {passo}, {tipo.name}, {np.degrees(angulo_testado):.2f}: {e}") - - return custo_total, simulacoes, True - except Exception as e: - mostrar_log(f"Erro ao simular passo para {tipo.name} | angulo: {np.degrees(angulo_testado):.2f}: {e}") - return float('inf'), [(0, 0, 0)], False - - def _nova_posicao(self, x, y, theta, omega, velocidade, tipo, angulo_rad): - distancia_m = velocidade * self.dt - - theta_sim = theta + (omega * self.dt) - x_sim = x + (np.sin(theta_sim) * distancia_m) - y_sim = y + (np.cos(theta_sim) * distancia_m) - - return x_sim, y_sim, theta_sim - - def _nova_posicao_new(self, x, y, theta, omega, velocidade, tipo, angulo_rad): - dt = self.dt - v = velocidade - distancia = v * dt - - if tipo == TipoMovimentoDirecional.MovimentoDiagonal: - # crab: yaw não muda; desloca na direção (theta + steer) - move_heading = theta + angulo_rad - theta_sim = theta - dx = distancia * np.sin(move_heading) # Leste - dy = distancia * np.cos(move_heading) # Norte - x_sim = x + dx - y_sim = y + dy - return x_sim, y_sim, theta_sim - - # Demais modos: pode ter guinada - if abs(omega) < 1e-6: - # reta - theta_sim = theta - dx = distancia * np.cos(theta_sim) - dy = distancia * np.sin(theta_sim) - x_sim = x - dx - y_sim = y - dy - return x_sim, y_sim, theta_sim - else: - # arco (uniciclo, 0=N, +θ horário) - dtheta = omega * dt - x_sim = x - (v / omega) * (np.cos(theta + dtheta) - np.cos(theta)) - y_sim = y - (v / omega) * (-np.sin(theta + dtheta) + np.sin(theta)) - theta_sim = theta + dtheta - return x_sim, y_sim, theta_sim diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py index b33021457..e066dc697 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py @@ -132,7 +132,7 @@ class ContextoGlobalRedis: dados = json.loads(mensagem["data"]) funcao_callback(dados) except Exception as e: - mostrar_log(f"Erro ao processar comando recebido: {e}") + mostrar_log(f"Erro ao processar comando recebido: {mensagem['data']} | {e}") # Roda o ouvinte em uma thread separada (não bloqueia) threading.Thread(target=_ouvinte, daemon=True).start() @@ -553,24 +553,23 @@ class ContextoGlobalRedis: if (dados_dir.get("tipo_controle", TiposControladorDirecional.Manual.value) == TiposControladorDirecional.MPC.value): dados_mpc = dados_dir.get("mpc", {}) mapa = cls.get_operacao().get("pontos_mapa", []) + p_ref = cls.get_operacao().get("ponto_mapa_ref", []) if do_manager: - p_ref = cls.get_operacao().get("ponto_mapa_ref", []) from manager_worker.modulos.mpc import inicializar as iniciar_mpc iniciar_mpc(dados_mpc, mapa, p_ref, iniciar_operacao) else: - cls.publicar_comando(CmdKey.ManagerWorkerRx, { "cmd": ManagerWorkerCommandType.IniciarMPC.value, "params": { "parametros": dados_mpc, "mapa": mapa, "iniciar_operacao": iniciar_operacao } }) + cls.publicar_comando(CmdKey.ManagerWorkerRx, { "cmd": ManagerWorkerCommandType.IniciarMPC.value, "params": { "parametros": dados_mpc, "mapa": mapa, "p_ref": p_ref, "iniciar_operacao": iniciar_operacao } }) @classmethod def _atualizar_pontos_mapa(cls): pontos_info = [] - p_ref = (0, 0) _operacao = cls.get_operacao() dados_dir = _operacao.get("Dir", {}) if (dados_dir.get("tipo_controle", TiposControladorDirecional.Manual.value) == TiposControladorDirecional.MPC.value): dados_mpc = dados_dir.get("mpc", {}) pontos = dados_mpc.get("pontos", []) if pontos is not None and len(pontos) > 0: - p_ref = pontos[0]["lat"], pontos[0]["lon"] + p_ref = cls.get_operacao().get("ponto_mapa_ref") from shared.gps_handler import GPSHandler handler = GPSHandler(p_ref[0], p_ref[1]) for p in pontos: @@ -584,7 +583,6 @@ class ContextoGlobalRedis: cls.atualizar_ctx_dict( CtxKey.DadosOperacao, pontos_mapa=pontos_info, - ponto_mapa_ref=p_ref ) if len(pontos_info) > 0: diff --git a/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs b/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs index 32c134afd..93c834330 100644 --- a/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs +++ b/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs @@ -846,7 +846,7 @@ namespace OperationControl.Controls { foreach (var rua in RuasMapaCarregado) { - var dado = Mapa.features.FirstOrDefault(x => x.properties.Id == rua.Id); + var dado = Mapa?.features?.FirstOrDefault(x => x.properties.Id == rua.Id); if (dado == null) continue; rua.Selected = RuasSelecionadas.Contains(dado.properties.Id); } diff --git a/Python/plot_ccordenadas.py b/Python/plot_ccordenadas.py new file mode 100644 index 000000000..295f69e2e --- /dev/null +++ b/Python/plot_ccordenadas.py @@ -0,0 +1,37 @@ +import matplotlib.pyplot as plt + +# Substitua pelas suas coordenadas (lat, lon) +coords = [ + [-22.172709676583331,-47.395223974666663], + [-22.172716850972222,-47.395224935138884], + [-22.172725134386194,-47.39523641178512], + [-22.172728586980455,-47.395222881810845],[-22.172727347766877,-47.395217842486744],[-22.172724131546165,-47.395213953604689],[-22.172718938318319,-47.395211215164665],[-22.172711768083332,-47.395209627166665] + #[-22.172711768083332,-47.395209627166665] +] + +# Separar latitude e longitude +lats = [c[0] for c in coords] +lons = [c[1] for c in coords] + +plt.figure(figsize=(8, 6)) + +# Linha conectando os pontos +plt.plot(lons, lats, linestyle='-', marker='o') + +# Primeiro ponto (verde) +plt.scatter(lons[0], lats[0], color='green', s=100, label='Primeiro') + +# Último ponto (vermelho) +plt.scatter(lons[-1], lats[-1], color='red', s=100, label='Último') + +# Numerar os pontos +for i, (lat, lon) in enumerate(coords): + plt.text(lon, lat, f' {i}', fontsize=10) + +plt.xlabel("Longitude") +plt.ylabel("Latitude") +plt.title("Plot de Coordenadas") +plt.legend() +plt.grid(True) + +plt.show() \ No newline at end of file