ajustes lora e deteccao de obstaculos

This commit is contained in:
Diego Freitas 2025-09-16 10:31:32 -03:00
parent 9611f564b5
commit e80d8cabcf
169 changed files with 13497 additions and 1426 deletions

Binary file not shown.

View File

@ -754,9 +754,10 @@ namespace AgroBase
private static bool VerificaComandoValidoSonar(Keys Comando) private static bool VerificaComandoValidoSonar(Keys Comando)
{ {
List<Keys> ComandosImpedidos = new List<Keys>(); List<Keys> ComandosImpedidos = new List<Keys>();
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual; var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
if (Variaveis.OperacaoEmAndamento.Controle.SonarAtivado && Sonar.Iniciado && Sonar.Status == StatusModulo.Operante && (Sonar.Analises.matriz_confianca?.block?.decision?.parar ?? false)) Sonar?.Resumo?.AtualizarStatusBloqueio(false);
var DeveParar = Sonar?.Resumo?.DeveParar ?? false;
if (DeveParar)
{ {
ComandosImpedidos.Add(Keys.Up); ComandosImpedidos.Add(Keys.Up);
/*switch (Sonar.Resumo.DirecaoDesvio) /*switch (Sonar.Resumo.DirecaoDesvio)

View File

@ -706,6 +706,7 @@ namespace AgroBase.Models.Modules
{ {
RequisitarDadosModulo(Variaveis.ID_Num_sTOD, CanMessagePosicaoDados.DadosAll, CanMessagePosicaoDados.DadosAll, true); RequisitarDadosModulo(Variaveis.ID_Num_sTOD, CanMessagePosicaoDados.DadosAll, CanMessagePosicaoDados.DadosAll, true);
} }
VerificaControleLeitura();
} }
AtualizaComponentesIniciados(); AtualizaComponentesIniciados();
@ -751,6 +752,32 @@ namespace AgroBase.Models.Modules
return (_atuadorOperante, ModsComFalha); return (_atuadorOperante, ModsComFalha);
} }
private void VerificaControleLeitura()
{
if (true) // !frmDiagnosticos.Diagnosticando
{
foreach (var bico in BicosPulverizadores.Where(x => x.Comandar && x.Inicializado))
{
Estado leituraEstado = (Estado?)(bico.ValoresLeituras.FirstOrDefault(x => x.funcao == FuncoesPinout.EstadoLeitura)?.atual?.valor) ?? Estado.Desligado;
Estado comandoEstado = bico.ComandoAtuar ? Estado.Ligado : Estado.Desligado;
if (leituraEstado != comandoEstado)
{
GeneralJoystick.EnviarComandoAtuador(bico.Componente, bico.ComandoAtuar, bico.ID);
}
}
var bomba = BombasPressurizadoras.FirstOrDefault(x => x.Comandar && x.Inicializado);
if (bomba != null)
{
bool leituraEstado = (bomba.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Potencia)?.atual?.valor ?? 0) > 0;
if (bomba.ComandoAtuar != leituraEstado)
{
GeneralJoystick.EnviarComandoAtuador(bomba.Componente, bomba.ComandoAtuar, bomba.ID);
}
}
}
}
private void AtualizaComponentesIniciados() private void AtualizaComponentesIniciados()
{ {
DateTime Agora = DateTime.Now; DateTime Agora = DateTime.Now;
@ -782,7 +809,7 @@ namespace AgroBase.Models.Modules
var Bomba = BombasPressurizadoras.FirstOrDefault(); var Bomba = BombasPressurizadoras.FirstOrDefault();
if (Bomba.Inicializado) if (Bomba.Inicializado)
{ {
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, true, Bomba.ID); GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, true, Bomba.ID);
bool AtingiuPressao() => PressaoLinha >= Variaveis.OperacaoEmAndamento.Controle.PressaoLinha; bool AtingiuPressao() => PressaoLinha >= Variaveis.OperacaoEmAndamento.Controle.PressaoLinha;
@ -796,11 +823,11 @@ namespace AgroBase.Models.Modules
{ {
if (Bico.Inicializado) if (Bico.Inicializado)
{ {
GeneralJoystick.EnviarComandoAtuador(S_Code.sBIC, true, Bico.ID); GeneralJoystick.EnviarComandoAtuador(Bico.Componente, true, Bico.ID);
await Task.Delay(200); await Task.Delay(200);
GeneralJoystick.EnviarComandoAtuador(S_Code.sBIC, false, Bico.ID); GeneralJoystick.EnviarComandoAtuador(Bico.Componente, false, Bico.ID);
} }
} }

View File

@ -1660,6 +1660,7 @@ namespace AgroBase.Models.Modules
Componente = S_Code.sLRA, Componente = S_Code.sLRA,
Funcoes = new List<FuncoesPinout>() Funcoes = new List<FuncoesPinout>()
{ {
FuncoesPinout.ENA,
FuncoesPinout.M0, FuncoesPinout.M0,
FuncoesPinout.M1, FuncoesPinout.M1,
FuncoesPinout.Aux, FuncoesPinout.Aux,

View File

@ -137,7 +137,8 @@ namespace AgroBase.Models
int qtdCamerasSolo, int qtdCamerasSolo,
TiposControladorDirecional tipoControleDirecional, TiposControladorDirecional tipoControleDirecional,
bool movimentoAutomatico, bool movimentoAutomatico,
bool pulverizadorAutomatico) bool pulverizadorAutomatico,
bool frenagemAutomatica)
{ {
if (string.IsNullOrEmpty(descricao)) if (string.IsNullOrEmpty(descricao))
{ {
@ -171,7 +172,8 @@ namespace AgroBase.Models
SonarAtivado = sonarAtivado, SonarAtivado = sonarAtivado,
QtdCamerasSolo = qtdCamerasSolo, QtdCamerasSolo = qtdCamerasSolo,
MovimentoAutomatico = movimentoAutomatico, MovimentoAutomatico = movimentoAutomatico,
PulverizadorAutomatico = pulverizadorAutomatico PulverizadorAutomatico = pulverizadorAutomatico,
FrenagemAtuomatica = frenagemAutomatica
}; };
Parametros.Mapa.LimparDados(true); Parametros.Mapa.LimparDados(true);
@ -231,6 +233,7 @@ namespace AgroBase.Models
TipoControleDirecional = Parametros.DirTipoMovimento, TipoControleDirecional = Parametros.DirTipoMovimento,
PulverizadorAutomatico = Parametros.PulverizadorAutomatico, PulverizadorAutomatico = Parametros.PulverizadorAutomatico,
MovimentoAutomatico = Parametros.MovimentoAutomatico, MovimentoAutomatico = Parametros.MovimentoAutomatico,
FrenagemAutomatica = Parametros.FrenagemAtuomatica,
TipoMovimento = Variaveis.OperacaoEmAndamento.Controle.TipoMovimento, TipoMovimento = Variaveis.OperacaoEmAndamento.Controle.TipoMovimento,
heartbeat = 0, heartbeat = 0,
SimulacaoMPC = new List<MPCSimulacaoModel>(), SimulacaoMPC = new List<MPCSimulacaoModel>(),
@ -309,6 +312,7 @@ namespace AgroBase.Models
{ {
MovimentoAutomatico = false, MovimentoAutomatico = false,
PulverizadorAutomatico = false, PulverizadorAutomatico = false,
FrenagemAutomatica = true,
RPM_Max = 100, RPM_Max = 100,
RPM_Min = 15, RPM_Min = 15,
Angulo_Max = 25, Angulo_Max = 25,
@ -386,6 +390,7 @@ namespace AgroBase.Models
{ {
MovimentoAutomatico = true, MovimentoAutomatico = true,
PulverizadorAutomatico = true, PulverizadorAutomatico = true,
FrenagemAutomatica = true,
RPM_Max = 50, RPM_Max = 50,
RPM_Min = 20, RPM_Min = 20,
Angulo_Max = 30, Angulo_Max = 30,
@ -486,6 +491,7 @@ namespace AgroBase.Models
{ {
MovimentoAutomatico = true, MovimentoAutomatico = true,
PulverizadorAutomatico = false, PulverizadorAutomatico = false,
FrenagemAutomatica = false,
RPM_Max = 100, RPM_Max = 100,
RPM_Min = 20, RPM_Min = 20,
Angulo_Max = 30, Angulo_Max = 30,
@ -588,6 +594,7 @@ namespace AgroBase.Models
{ {
MovimentoAutomatico = true, MovimentoAutomatico = true,
PulverizadorAutomatico = false, PulverizadorAutomatico = false,
FrenagemAutomatica = true,
RPM_Max = 40, RPM_Max = 40,
RPM_Min = 20, RPM_Min = 20,
Angulo_Max = 30, Angulo_Max = 30,
@ -948,7 +955,11 @@ namespace AgroBase.Models
{ {
case T_Code.Mov: case T_Code.Mov:
{ {
if (_Controle.RPM_SP == 0) if (_Controle.FrenagemAutomatica && _Controle.EmFreio)
{
_Controle.Direcao = Direcao.EmFreio;
}
else if (_Controle.RPM_SP == 0)
{ {
_Controle.Direcao = Direcao.Parado; _Controle.Direcao = Direcao.Parado;
} }
@ -976,6 +987,7 @@ namespace AgroBase.Models
_ControleAnterior.PercentualVelocidadeSP = _Controle.PercentualVelocidadeSP; _ControleAnterior.PercentualVelocidadeSP = _Controle.PercentualVelocidadeSP;
_ControleAnterior.Direcao = _Controle.Direcao; _ControleAnterior.Direcao = _Controle.Direcao;
_ControleAnterior.EmFreio = _Controle.EmFreio;
RedisService.AtualizarCampos( RedisService.AtualizarCampos(
CtxKey.DadosControle, CtxKey.DadosControle,
@ -1085,9 +1097,12 @@ namespace AgroBase.Models
if (Variaveis.OperacaoEmAndamento.Modo == ModoOperacao.Manual) if (Variaveis.OperacaoEmAndamento.Modo == ModoOperacao.Manual)
{ {
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual; var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
bool deveParar = (Sonar.Analises.matriz_confianca?.block?.decision?.parar ?? false); Sonar?.Resumo?.AtualizarStatusBloqueio(true);
bool emMovimento = Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Mov)?.UltimaDirecao != Direcao.Parado; if (Sonar?.Resumo?.EnviarComandoParada ?? false)
if (Variaveis.OperacaoEmAndamento.Controle.SonarAtivado && Sonar.Iniciado && Sonar.Status == StatusModulo.Operante && deveParar && emMovimento) {
GeneralJoystick.EnviaComandoMotor(Keys.Space, T_Code.Mov);
}
else if (Sonar?.Resumo?.EnviarComandoRetomada ?? false)
{ {
GeneralJoystick.EnviaComandoMotor(Keys.Escape, T_Code.Mov); GeneralJoystick.EnviaComandoMotor(Keys.Escape, T_Code.Mov);
} }
@ -1528,6 +1543,7 @@ namespace AgroBase.Models
return FuncoesMatematicas.Map(RPM_Max, 0, VariaveisEquipamento.RPM_Max_Roda, 0, 100); return FuncoesMatematicas.Map(RPM_Max, 0, VariaveisEquipamento.RPM_Max_Roda, 0, 100);
} }
} }
public bool EmFreio { get; set; } = false;
public Direcao Direcao { get; set; } = Direcao.Parado; public Direcao Direcao { get; set; } = Direcao.Parado;
private TipoMovimentoDirecional _tipoMovimento = TipoMovimentoDirecional.Diagnostico; private TipoMovimentoDirecional _tipoMovimento = TipoMovimentoDirecional.Diagnostico;
public TipoMovimentoDirecional TipoMovimento public TipoMovimentoDirecional TipoMovimento
@ -1601,8 +1617,8 @@ namespace AgroBase.Models
_pulverizadorAutomatico = value; _pulverizadorAutomatico = value;
} }
} }
//public bool MovimentoAutomatico { get; set; }
public bool MovimentoAutomatico { get; set; } public bool MovimentoAutomatico { get; set; }
public bool FrenagemAutomatica { get; set; }
public TiposControladorDirecional TipoControleDirecional { get; set; } = TiposControladorDirecional.PID; public TiposControladorDirecional TipoControleDirecional { get; set; } = TiposControladorDirecional.PID;
public List<MPCSimulacaoModel> SimulacaoMPC { get; set; } = new List<MPCSimulacaoModel>(); public List<MPCSimulacaoModel> SimulacaoMPC { get; set; } = new List<MPCSimulacaoModel>();
@ -1632,9 +1648,11 @@ namespace AgroBase.Models
SimulacaoMPC = new List<MPCSimulacaoModel>(SimulacaoMPC), SimulacaoMPC = new List<MPCSimulacaoModel>(SimulacaoMPC),
PulverizadorAutomatico = PulverizadorAutomatico, PulverizadorAutomatico = PulverizadorAutomatico,
MovimentoAutomatico = MovimentoAutomatico, MovimentoAutomatico = MovimentoAutomatico,
FrenagemAutomatica = FrenagemAutomatica,
heartbeat = heartbeat, heartbeat = heartbeat,
ticks_sem_resposta = ticks_sem_resposta, ticks_sem_resposta = ticks_sem_resposta,
Latencia = Latencia, Latencia = Latencia,
EmFreio = EmFreio,
}; };
} }
} }

View File

@ -24,5 +24,6 @@ namespace AgroBase.Models.Operacoes
public int QtdCamerasSolo { get; set; } public int QtdCamerasSolo { get; set; }
public bool MovimentoAutomatico { get; set; } public bool MovimentoAutomatico { get; set; }
public bool PulverizadorAutomatico { get; set; } public bool PulverizadorAutomatico { get; set; }
public bool FrenagemAtuomatica { get; set; }
} }
} }

View File

@ -48,6 +48,7 @@ namespace AgroBase.Models.Operadores
public class ManagerWorkerMessageResponseComandoModel public class ManagerWorkerMessageResponseComandoModel
{ {
public double percentual_velocidade { get; set; } public double percentual_velocidade { get; set; }
public bool em_freio { get; set; }
public double angulo { get; set; } public double angulo { get; set; }
public TipoMovimentoDirecional tipo_movimento { get; set; } public TipoMovimentoDirecional tipo_movimento { get; set; }
public List<double[]> simulacao { get; set; } public List<double[]> simulacao { get; set; }

View File

@ -17,6 +17,7 @@ namespace AgroBase.Models.Operadores
public VisualWorkerMessageAnaliseModel Analises { get; set; } = new VisualWorkerMessageAnaliseModel(); public VisualWorkerMessageAnaliseModel Analises { get; set; } = new VisualWorkerMessageAnaliseModel();
public VisualWorkerMessageIMUModel Imu { get; set; } = new VisualWorkerMessageIMUModel(); public VisualWorkerMessageIMUModel Imu { get; set; } = new VisualWorkerMessageIMUModel();
public StatusModulo Status { get; set; } public StatusModulo Status { get; set; }
public VisualWorkerResumoModel Resumo { get; set; }
public VisualWorkerModel Clone() public VisualWorkerModel Clone()
{ {
@ -30,7 +31,8 @@ namespace AgroBase.Models.Operadores
Analises = Analises?.Clone(), Analises = Analises?.Clone(),
Imu = Imu?.Clone(), Imu = Imu?.Clone(),
UltimaMensagem = UltimaMensagem, UltimaMensagem = UltimaMensagem,
Status = Status Status = Status,
Resumo = Resumo?.Clone()
}; };
} }
@ -43,10 +45,65 @@ namespace AgroBase.Models.Operadores
CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>(); CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
Analises = new VisualWorkerMessageAnaliseModel(); Analises = new VisualWorkerMessageAnaliseModel();
Imu = new VisualWorkerMessageIMUModel(); Imu = new VisualWorkerMessageIMUModel();
Resumo = new VisualWorkerResumoModel();
Status = StatusModulo.Desconectado; Status = StatusModulo.Desconectado;
} }
} }
public class VisualWorkerResumoModel
{
public bool ObstaculoDetectado { get; set; } = false;
public bool DeveParar { get; set; } = false;
public bool EnviarComandoParada { get; set; } = false;
public bool EnviarComandoRetomada { get; set; } = false;
private bool _comandoParadaEnviado { get; set; } = false;
public void AtualizarStatusBloqueio(bool consideraEmMovimento)
{
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
ObstaculoDetectado = (Sonar.Analises?.matriz_confianca?.block?.decision?.parar ?? false);
if (!Variaveis.OperacaoEmAndamento.Controle.SonarAtivado)
{
_comandoParadaEnviado = false;
DeveParar = false;
EnviarComandoParada = false;
EnviarComandoRetomada = false;
}
else
{
List<Direcao> _direcoesInterromperMovimento = new List<Direcao> { Direcao.Frente, Direcao.Tras };
Direcao _ultimaDirecaoControle = Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Mov)?.UltimaDirecao ?? Direcao.Parado;
bool _carroEmMovimento = _direcoesInterromperMovimento.Contains(_ultimaDirecaoControle);
bool emMovimento = consideraEmMovimento ? _carroEmMovimento : true;
DeveParar = Sonar.Status == StatusModulo.Operante && ObstaculoDetectado;
EnviarComandoParada = DeveParar && emMovimento;
if (EnviarComandoParada)
{
_comandoParadaEnviado = true;
}
EnviarComandoRetomada = !ObstaculoDetectado && _comandoParadaEnviado;
if (EnviarComandoRetomada)
{
_comandoParadaEnviado = false;
}
}
}
public VisualWorkerResumoModel Clone()
{
return new VisualWorkerResumoModel()
{
ObstaculoDetectado = ObstaculoDetectado,
DeveParar = DeveParar,
EnviarComandoParada = EnviarComandoParada,
EnviarComandoRetomada = EnviarComandoRetomada,
_comandoParadaEnviado = _comandoParadaEnviado,
};
}
}
public class VisualWorkerDadosModel public class VisualWorkerDadosModel
{ {
public bool DesvioNecessario { get; set; } public bool DesvioNecessario { get; set; }

View File

@ -696,6 +696,7 @@ namespace AgroBase.Models
var dictParams = JObject.Parse(controleStr); var dictParams = JObject.Parse(controleStr);
dictParams.TryGetValue("angulo_sp", out var _angulo); dictParams.TryGetValue("angulo_sp", out var _angulo);
dictParams.TryGetValue("velocidade_sp", out var _velocidade); dictParams.TryGetValue("velocidade_sp", out var _velocidade);
dictParams.TryGetValue("em_freio", out var _em_freio);
dictParams.TryGetValue("tipo_movimento_direcional", out var _movimento); dictParams.TryGetValue("tipo_movimento_direcional", out var _movimento);
dictParams.TryGetValue("simulacao", out var _simulacao); dictParams.TryGetValue("simulacao", out var _simulacao);
dictParams.TryGetValue("heartbeat", out var _heartbeat); dictParams.TryGetValue("heartbeat", out var _heartbeat);
@ -704,6 +705,7 @@ namespace AgroBase.Models
{ {
angulo = Convert.ToDouble(_angulo), angulo = Convert.ToDouble(_angulo),
percentual_velocidade = Convert.ToDouble(_velocidade), percentual_velocidade = Convert.ToDouble(_velocidade),
em_freio = Convert.ToBoolean(_em_freio),
tipo_movimento = (TipoMovimentoDirecional)Convert.ToInt32(_movimento), tipo_movimento = (TipoMovimentoDirecional)Convert.ToInt32(_movimento),
simulacao = JsonConvert.DeserializeObject<List<double[]>>((_simulacao ?? "").ToString()), simulacao = JsonConvert.DeserializeObject<List<double[]>>((_simulacao ?? "").ToString()),
heartbeat = Convert.ToInt32(_heartbeat), heartbeat = Convert.ToInt32(_heartbeat),
@ -718,13 +720,14 @@ namespace AgroBase.Models
DateTime agora = DateTime.Now; DateTime agora = DateTime.Now;
var _Controle = Variaveis.OperacaoEmAndamento.Controle; var _Controle = Variaveis.OperacaoEmAndamento.Controle;
bool comandoMudou = (_Controle.Angulo != novoComando.angulo || _Controle.PercentualVelocidadeSP != novoComando.percentual_velocidade || _Controle.TipoMovimento != novoComando.tipo_movimento); bool comandoMudou = (_Controle.Angulo != novoComando.angulo || _Controle.PercentualVelocidadeSP != novoComando.percentual_velocidade || _Controle.TipoMovimento != novoComando.tipo_movimento || _Controle.EmFreio != novoComando.em_freio);
bool mangerDestravou = (_Controle.ticks_sem_resposta.AddMilliseconds(min_ticks_sem_resposta) < agora && novoComando.heartbeat != _Controle.heartbeat); bool mangerDestravou = (_Controle.ticks_sem_resposta.AddMilliseconds(min_ticks_sem_resposta) < agora && novoComando.heartbeat != _Controle.heartbeat);
if (novoComando != null && (comandoMudou || mangerDestravou)) if (novoComando != null && (comandoMudou || mangerDestravou))
{ {
_Controle.Angulo = novoComando.angulo; _Controle.Angulo = novoComando.angulo;
_Controle.TipoMovimento = novoComando.tipo_movimento; _Controle.TipoMovimento = novoComando.tipo_movimento;
_Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade; _Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade;
_Controle.EmFreio = novoComando.em_freio;
_Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List<MPCSimulacaoModel>(); _Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List<MPCSimulacaoModel>();
_Controle.Latencia = novoComando.latencia; _Controle.Latencia = novoComando.latencia;
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao(); Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();

View File

@ -6,7 +6,7 @@ namespace AgroBase.Services
{ {
public class CanManager public class CanManager
{ {
public static bool UseCanSerial = false; public static bool UseCanSerial = true;
private static CanServiceWaveshare CanWaveshare = new CanServiceWaveshare(); private static CanServiceWaveshare CanWaveshare = new CanServiceWaveshare();
private static CanServiceSerial CanSerial = new CanServiceSerial(); private static CanServiceSerial CanSerial = new CanServiceSerial();

View File

@ -8,7 +8,6 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using static AgroBase.Models.Enums; using static AgroBase.Models.Enums;
using static AgroBase.Services.LoRaEspService;
namespace AgroBase.Services namespace AgroBase.Services
{ {
@ -102,36 +101,42 @@ namespace AgroBase.Services
_PortaCAN.DiscardInBuffer(); _PortaCAN.DiscardInBuffer();
_PortaCAN.DiscardOutBuffer(); _PortaCAN.DiscardOutBuffer();
UltimoRx = DateTime.Now;
UltimoTx = DateTime.Now;
tmrOuvirCAN?.Dispose();
tmrOuvirCAN = new AsyncTaskTimerModel("tmrOuvirCAN", OuvirCAN, 1);
tmrOuvirCAN.Start();
tmrEnviarCAN?.Dispose();
tmrEnviarCAN = new AsyncTaskTimerModel("tmrEnviarCAN", EnviarCAN, 3);
tmrEnviarCAN.Start();
tmrProcessarCAN?.Dispose();
tmrProcessarCAN = new AsyncTaskTimerModel("tmrProcessarCAN", ProcessarCAN, 5);
tmrProcessarCAN.Start();
IsConnected = true;
} }
UltimoRx = DateTime.Now;
UltimoTx = DateTime.Now;
tmrOuvirCAN?.Dispose();
tmrOuvirCAN = new AsyncTaskTimerModel("tmrOuvirCAN", OuvirCAN, 1);
tmrOuvirCAN.Start();
tmrEnviarCAN?.Dispose();
tmrEnviarCAN = new AsyncTaskTimerModel("tmrEnviarCAN", EnviarCAN, 3);
tmrEnviarCAN.Start();
tmrProcessarCAN?.Dispose();
tmrProcessarCAN = new AsyncTaskTimerModel("tmrProcessarCAN", ProcessarCAN, 5);
tmrProcessarCAN.Start();
IsConnected = true;
} }
if (_PortaCAN != null && !_PortaCAN.IsOpen) lock (_lock)
{ {
_PortaCAN.Open(); if (_PortaCAN != null && !_PortaCAN.IsOpen)
{
_PortaCAN.Open();
}
} }
return IsConnected; return IsConnected;
} }
catch (Exception ex) catch (Exception ex)
{ {
_PortaCAN = null; lock (_lock)
{
_PortaCAN = null;
}
return false; return false;
} }
} }
@ -434,14 +439,17 @@ namespace AgroBase.Services
private bool EnviarComando(string comando) private bool EnviarComando(string comando)
{ {
if (_PortaCAN?.IsOpen == true) lock (_lock)
{ {
_PortaCAN.Write(comando); if (_PortaCAN?.IsOpen == true)
//Console.WriteLine($"[CAN] Frame enviado: {comando}"); {
UltimoTx = DateTime.Now; _PortaCAN.Write(comando);
return true; //Console.WriteLine($"[CAN] Frame enviado: {comando}");
UltimoTx = DateTime.Now;
return true;
}
return false;
} }
return false;
} }
private void LimparMensagensAntigas() private void LimparMensagensAntigas()
@ -473,16 +481,7 @@ namespace AgroBase.Services
UltimoRx = Agora; UltimoRx = Agora;
UltimoTx = Agora; UltimoTx = Agora;
MostrarLog("Muito tempo sem receber novos dados, reiniciando conexao CAN...", 0); MostrarLog("Muito tempo sem receber novos dados, reiniciando conexao CAN...", 0);
try { _PortaCAN?.Close(); } catch { } ReabrirPortaSegura();
try
{
_PortaCAN?.Open();
EnviarComando("C\r"); Thread.Sleep(50);
EnviarComando("Z0\r"); Thread.Sleep(50);
EnviarComando(ComandoBitRate(_bitRate)); Thread.Sleep(50);
EnviarComando("O\r"); Thread.Sleep(50);
}
catch { }
} }
} }
@ -556,8 +555,6 @@ namespace AgroBase.Services
} }
} }
private string ComandoBitRate(int rate) private string ComandoBitRate(int rate)
{ {
switch (rate) switch (rate)
@ -585,5 +582,37 @@ namespace AgroBase.Services
} }
} }
private void ReabrirPortaSegura()
{
tmrEnviarCAN?.Stop();
tmrOuvirCAN?.Stop();
tmrProcessarCAN?.Stop();
lock (_LockMensagens)
{
Mensagens.Clear();
}
lock (_lock)
{
try { _PortaCAN?.Close(); } catch { }
try
{
_PortaCAN?.Open();
_PortaCAN.DiscardInBuffer();
_PortaCAN.DiscardOutBuffer();
EnviarComando("C\r"); Thread.Sleep(50);
EnviarComando("Z0\r"); Thread.Sleep(50);
EnviarComando(ComandoBitRate(_bitRate)); Thread.Sleep(50);
EnviarComando("O\r"); Thread.Sleep(50);
}
catch { /* log */ }
}
tmrEnviarCAN?.Start();
tmrOuvirCAN?.Start();
tmrProcessarCAN?.Start();
}
} }
} }

View File

@ -39,10 +39,7 @@ namespace AgroBase.Services
public List<(int, CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(PinoutDataModel Pinout, bool conectar) public List<(int, CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(PinoutDataModel Pinout, bool conectar)
{ {
List<byte> config1 = new List<byte>() List<byte> config1 = new List<byte>();
{
Variaveis.LoraBaseParametros?.address ?? 0x01
};
var _pinout = Pinout.Clone(); var _pinout = Pinout.Clone();
_pinout.Pinos = _pinout.Pinos.Where(x => x.ComponenteID == ID).ToList(); _pinout.Pinos = _pinout.Pinos.Where(x => x.ComponenteID == ID).ToList();
if (_pinout.Pinos.Count > 0) if (_pinout.Pinos.Count > 0)
@ -53,6 +50,7 @@ namespace AgroBase.Services
List<byte> config2 = new List<byte> List<byte> config2 = new List<byte>
{ {
Variaveis.LoraBaseParametros?.address ?? 0x01,
ParametrosSet.address, ParametrosSet.address,
ParametrosSet.baudAndAirRate, ParametrosSet.baudAndAirRate,
ParametrosSet.packetSizeAndPower, ParametrosSet.packetSizeAndPower,

View File

@ -271,7 +271,8 @@ namespace AgroBase.Services.Operadores
RedisService.AtualizarCampos( RedisService.AtualizarCampos(
CtxKey.DadosControle, CtxKey.DadosControle,
("pulverizador_automatico", Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico), ("pulverizador_automatico", Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico),
("movimento_automatico", Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico) ("movimento_automatico", Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico),
("frenagem_automatica", Variaveis.OperacaoEmAndamento.Controle.FrenagemAutomatica)
); );
} }

View File

@ -55,6 +55,7 @@ namespace AgroBase.Services.Operadores
{ {
dictParams.TryGetValue("angulo_sp", out object _angulo); dictParams.TryGetValue("angulo_sp", out object _angulo);
dictParams.TryGetValue("velocidade_sp", out object _velocidade); dictParams.TryGetValue("velocidade_sp", out object _velocidade);
dictParams.TryGetValue("em_freio", out object _em_freio);
dictParams.TryGetValue("tipo_movimento_direcional", out object _movimento); dictParams.TryGetValue("tipo_movimento_direcional", out object _movimento);
dictParams.TryGetValue("simulacao", out object _simulacao); dictParams.TryGetValue("simulacao", out object _simulacao);
dictParams.TryGetValue("heartbeat", out object _heartbeat); dictParams.TryGetValue("heartbeat", out object _heartbeat);
@ -62,6 +63,7 @@ namespace AgroBase.Services.Operadores
{ {
angulo = Convert.ToDouble(_angulo), angulo = Convert.ToDouble(_angulo),
percentual_velocidade = Convert.ToDouble(_velocidade), percentual_velocidade = Convert.ToDouble(_velocidade),
em_freio = Convert.ToBoolean(_em_freio),
tipo_movimento = (Enums.TipoMovimentoDirecional)Convert.ToInt32(_movimento), tipo_movimento = (Enums.TipoMovimentoDirecional)Convert.ToInt32(_movimento),
simulacao = JsonConvert.DeserializeObject<List<double[]>>((_simulacao ?? "").ToString()), simulacao = JsonConvert.DeserializeObject<List<double[]>>((_simulacao ?? "").ToString()),
heartbeat = Convert.ToInt32(_heartbeat) heartbeat = Convert.ToInt32(_heartbeat)
@ -73,12 +75,13 @@ namespace AgroBase.Services.Operadores
} }
var _Controle = Variaveis.OperacaoEmAndamento.Controle; var _Controle = Variaveis.OperacaoEmAndamento.Controle;
bool comandoMudou = (_Controle.Angulo != novoComando.angulo || _Controle.PercentualVelocidadeSP != novoComando.percentual_velocidade || _Controle.TipoMovimento != novoComando.tipo_movimento); bool comandoMudou = (_Controle.Angulo != novoComando.angulo || _Controle.PercentualVelocidadeSP != novoComando.percentual_velocidade || _Controle.TipoMovimento != novoComando.tipo_movimento || _Controle.EmFreio != novoComando.em_freio);
if (novoComando != null && comandoMudou) if (novoComando != null && comandoMudou)
{ {
_Controle.Angulo = novoComando.angulo; _Controle.Angulo = novoComando.angulo;
_Controle.TipoMovimento = novoComando.tipo_movimento; _Controle.TipoMovimento = novoComando.tipo_movimento;
_Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade; _Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade;
_Controle.EmFreio = novoComando.em_freio;
_Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List<MPCSimulacaoModel>(); _Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List<MPCSimulacaoModel>();
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao(); Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
} }

View File

@ -39,6 +39,7 @@ namespace AgroBase.Services.Operadores
if (pronto()) if (pronto())
{ {
MostrarLog("Processamento iniciado com sucesso"); MostrarLog("Processamento iniciado com sucesso");
DadosLeitura.Iniciado = true;
return true; return true;
} }

View File

@ -1,12 +1,5 @@
{ {
"epochs": [ { "epochs": [ {
"calculation_time": "13399827811771001",
"config_version": 0,
"model_version": "0",
"padded_top_topics_start_index": 0,
"taxonomy_version": 0,
"top_topics_and_observing_domains": [ ]
}, {
"calculation_time": "13400595140854297", "calculation_time": "13400595140854297",
"config_version": 0, "config_version": 0,
"model_version": "0", "model_version": "0",
@ -27,7 +20,14 @@
"padded_top_topics_start_index": 0, "padded_top_topics_start_index": 0,
"taxonomy_version": 0, "taxonomy_version": 0,
"top_topics_and_observing_domains": [ ] "top_topics_and_observing_domains": [ ]
}, {
"calculation_time": "13402425506182172",
"config_version": 0,
"model_version": "0",
"padded_top_topics_start_index": 0,
"taxonomy_version": 0,
"top_topics_and_observing_domains": [ ]
} ], } ],
"hex_encoded_hmac_key": "40F346D3248C3AFDF2BEE1FE496DBD32F7CED6E5AE98B881ABC421AA7E7B5642", "hex_encoded_hmac_key": "40F346D3248C3AFDF2BEE1FE496DBD32F7CED6E5AE98B881ABC421AA7E7B5642",
"next_scheduled_calculation_time": "13402424980889277" "next_scheduled_calculation_time": "13403030306182389"
} }

View File

@ -1,3 +1,3 @@
2025/09/09-15:46:04.235 680c Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001 2025/09/15-17:35:19.244 585c Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2025/09/09-15:46:04.241 680c Recovering log #3 2025/09/15-17:35:19.253 585c Recovering log #3
2025/09/09-15:46:04.244 680c Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log 2025/09/15-17:35:19.256 585c Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log

View File

@ -1,3 +1,3 @@
2025/09/09-15:09:11.525 3c58 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001 2025/09/15-15:57:42.267 2cc0 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2025/09/09-15:09:11.532 3c58 Recovering log #3 2025/09/15-15:57:42.276 2cc0 Recovering log #3
2025/09/09-15:09:11.536 3c58 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log 2025/09/15-15:57:42.279 2cc0 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log

View File

@ -1 +1 @@
{"net":{"http_server_properties":{"servers":[{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13402003564945866","port":443,"protocol_str":"quic"}],"anonymization":["DAAAAAcAAABmaWxlOi8vAA==",false,0],"network_stats":{"srtt":37908},"server":"https://tile.openstreetmap.org","supports_spdy":true}],"supports_quic":{"address":"2804:d78:6a8:5d00:593a:511a:74dd:807b","used_quic":true},"version":5},"network_qualities":{"CAASABiAgICA+P////8B":"4G","CAESABiAgICA+P////8B":"4G","CAISABiAgICA+P////8B":"4G","CAYSABiAgICA+P////8B":"Offline"}}} {"net":{"http_server_properties":{"servers":[{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13402522885929406","port":443,"protocol_str":"quic"}],"anonymization":["DAAAAAcAAABmaWxlOi8vAA==",false,0],"network_stats":{"srtt":27069},"server":"https://tile.openstreetmap.org","supports_spdy":true}],"supports_quic":{"address":"2804:d78:67d:1400:60e0:3daf:3723:e31f","used_quic":true},"version":5},"network_qualities":{"CAASABiAgICA+P////8B":"4G","CAESABiAgICA+P////8B":"4G","CAISABiAgICA+P////8B":"4G","CAYSABiAgICA+P////8B":"Offline"}}}

View File

@ -1 +1 @@
{"sts":[{"expiry":1788979564.946284,"host":"bWGAftl61rqoc0YzqPncsLvQQh/iC2Bdp3ejUeGC83w=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1757443564.946287}],"version":2} {"sts":[{"expiry":1789498662.856284,"host":"bWGAftl61rqoc0YzqPncsLvQQh/iC2Bdp3ejUeGC83w=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1757962662.856286}],"version":2}

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
2025/09/09-15:58:01.007 680c Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001 2025/09/15-17:36:02.774 585c Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2025/09/09-15:58:01.008 680c Recovering log #3 2025/09/15-17:36:02.775 585c Recovering log #3
2025/09/09-15:58:01.011 680c Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log 2025/09/15-17:36:02.778 585c Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log

View File

@ -1,3 +1,3 @@
2025/09/09-15:44:08.465 3c58 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001 2025/09/15-16:16:16.964 2cc0 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2025/09/09-15:44:08.467 3c58 Recovering log #3 2025/09/15-16:16:16.966 2cc0 Recovering log #3
2025/09/09-15:44:08.470 3c58 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log 2025/09/15-16:16:16.969 2cc0 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log

View File

@ -1,3 +1,3 @@
2025/09/09-15:46:04.142 58d8 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001 2025/09/15-17:35:19.173 1788 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2025/09/09-15:46:04.143 58d8 Recovering log #7 2025/09/15-17:35:19.176 1788 Recovering log #7
2025/09/09-15:46:04.144 58d8 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log 2025/09/15-17:35:19.176 1788 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log

View File

@ -1,3 +1,3 @@
2025/09/09-15:09:11.448 1b60 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001 2025/09/15-15:57:42.197 4e88 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2025/09/09-15:09:11.449 1b60 Recovering log #7 2025/09/15-15:57:42.199 4e88 Recovering log #7
2025/09/09-15:09:11.450 1b60 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log 2025/09/15-15:57:42.199 4e88 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log

View File

@ -1 +1 @@
140.0.3485.54 140.0.3485.66

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"hashes":{"00AF3F07B5ABB71F6D30337E1EEF62FA280F06EF19485C0CF6B72171F92CCC0A":{"appid":"kpfehajjjbbcifeehjgfgnabifknmdad","fp":"1.00AF3F07B5ABB71F6D30337E1EEF62FA280F06EF19485C0CF6B72171F92CCC0A"},"452064dcff76e03e0e81b4bb3c48ab1c432e040094f7546c7261a90d4a1c1bbf":{"appid":"fgbafbciocncjfbbonhocjaohoknlaco","fp":""},"4B81B4DF3AD971287E1AE02C449344FCFA5D20431DE17B2BA8854CC9CDCE4089":{"appid":"ahmaebgpfccdhgidjaidaoojjcijckba","fp":"1.4B81B4DF3AD971287E1AE02C449344FCFA5D20431DE17B2BA8854CC9CDCE4089"},"8482d8cbe30fdc7c561f12ce566b64102191a99798dae98132c35714020e1aad":{"appid":"jbfaflocpnkhbgcijpkiafdpbjkedane","fp":""},"89f43cb3df807293de2772d5f01ac2fc1482b38ccc8fdaee859b80642b7a0487":{"appid":"pghocgajpebopihickglahgebcmkcekh","fp":""},"95FD9D48E4FC245A3F3A99A3A16ECD1355050BA3F4AFC555F19A97C7F9B49677":{"appid":"ohckeflnhegojcjlcpbfpciadgikcohk","fp":"1.95FD9D48E4FC245A3F3A99A3A16ECD1355050BA3F4AFC555F19A97C7F9B49677"},"A81D1959892AE4180554347DF1B97834ABBA2E1A5E6B9AEBA000ECEA26EABECC":{"appid":"fppmbhmldokgmleojlplaaodlkibgikh","fp":"1.A81D1959892AE4180554347DF1B97834ABBA2E1A5E6B9AEBA000ECEA26EABECC"},"A99D66CFCE8CA170740CE0403956F4DFAF4683829A89F4B7AD9C95303871E284":{"appid":"eeobbhfgfagbclfofmgbdfoicabjdbkn","fp":"1.A99D66CFCE8CA170740CE0403956F4DFAF4683829A89F4B7AD9C95303871E284"},"b987bdc4f2ad2a409b964921d4a5db1cdbe07f9c98f868293b4cc32acdc42cec":{"appid":"alpjnmnfbgfkmmpcfpejmmoebdndedno","fp":""},"bcb93cba8636743d1fbd32be3bd8ce8ff602323895bf4d136c26b9bc64b0a6a4":{"appid":"ndikpojcjlepofdkaaldkinkjbeeebkl","fp":""},"fa29a6d5775ff340900a65b39b02fc8b4b77d403c048d8debf22f2f5d09c61a0":{"appid":"oankkpibpaokgecfckkdkgaoafllipag","fp":""}}} {"hashes":{"00AF3F07B5ABB71F6D30337E1EEF62FA280F06EF19485C0CF6B72171F92CCC0A":{"appid":"kpfehajjjbbcifeehjgfgnabifknmdad","fp":"1.00AF3F07B5ABB71F6D30337E1EEF62FA280F06EF19485C0CF6B72171F92CCC0A"},"452064dcff76e03e0e81b4bb3c48ab1c432e040094f7546c7261a90d4a1c1bbf":{"appid":"fgbafbciocncjfbbonhocjaohoknlaco","fp":""},"4B81B4DF3AD971287E1AE02C449344FCFA5D20431DE17B2BA8854CC9CDCE4089":{"appid":"ahmaebgpfccdhgidjaidaoojjcijckba","fp":"1.4B81B4DF3AD971287E1AE02C449344FCFA5D20431DE17B2BA8854CC9CDCE4089"},"89f43cb3df807293de2772d5f01ac2fc1482b38ccc8fdaee859b80642b7a0487":{"appid":"pghocgajpebopihickglahgebcmkcekh","fp":""},"95FD9D48E4FC245A3F3A99A3A16ECD1355050BA3F4AFC555F19A97C7F9B49677":{"appid":"ohckeflnhegojcjlcpbfpciadgikcohk","fp":"1.95FD9D48E4FC245A3F3A99A3A16ECD1355050BA3F4AFC555F19A97C7F9B49677"},"A81D1959892AE4180554347DF1B97834ABBA2E1A5E6B9AEBA000ECEA26EABECC":{"appid":"fppmbhmldokgmleojlplaaodlkibgikh","fp":"1.A81D1959892AE4180554347DF1B97834ABBA2E1A5E6B9AEBA000ECEA26EABECC"},"A99D66CFCE8CA170740CE0403956F4DFAF4683829A89F4B7AD9C95303871E284":{"appid":"eeobbhfgfagbclfofmgbdfoicabjdbkn","fp":"1.A99D66CFCE8CA170740CE0403956F4DFAF4683829A89F4B7AD9C95303871E284"},"b987bdc4f2ad2a409b964921d4a5db1cdbe07f9c98f868293b4cc32acdc42cec":{"appid":"alpjnmnfbgfkmmpcfpejmmoebdndedno","fp":""},"bcb93cba8636743d1fbd32be3bd8ce8ff602323895bf4d136c26b9bc64b0a6a4":{"appid":"ndikpojcjlepofdkaaldkinkjbeeebkl","fp":""},"fa29a6d5775ff340900a65b39b02fc8b4b77d403c048d8debf22f2f5d09c61a0":{"appid":"oankkpibpaokgecfckkdkgaoafllipag","fp":""},"ff87fddb54d7bdc8ab8c2697bc92337c914803fb22cd32e445389e8042159ce9":{"appid":"jbfaflocpnkhbgcijpkiafdpbjkedane","fp":""}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,7 @@
<meta name="viewport" content="width=device-width, <meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style> <style>
#map_0d47d5844cb03a1b59409c5f2e45d89e { #map_413b17cf3f148cf9e5299ab727cb1cef {
position: relative; position: relative;
width: 100.0%; width: 100.0%;
height: 100.0%; height: 100.0%;
@ -54,14 +54,14 @@
<body> <body>
<div class="folium-map" id="map_0d47d5844cb03a1b59409c5f2e45d89e" ></div> <div class="folium-map" id="map_413b17cf3f148cf9e5299ab727cb1cef" ></div>
</body> </body>
<script> <script>
var map_0d47d5844cb03a1b59409c5f2e45d89e = L.map( var map_413b17cf3f148cf9e5299ab727cb1cef = L.map(
"map_0d47d5844cb03a1b59409c5f2e45d89e", "map_413b17cf3f148cf9e5299ab727cb1cef",
{ {
center: [0.0, 0.0], center: [0.0, 0.0],
crs: L.CRS.EPSG3857, crs: L.CRS.EPSG3857,
@ -77,26 +77,6 @@
var tile_layer_833f84bdc2b417e2650cc33bb5c7c348 = L.tileLayer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
{
"minZoom": 0,
"maxZoom": 19,
"maxNativeZoom": 19,
"noWrap": false,
"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors",
"subdomains": "abc",
"detectRetina": false,
"tms": false,
"opacity": 1,
}
);
tile_layer_833f84bdc2b417e2650cc33bb5c7c348.addTo(map_0d47d5844cb03a1b59409c5f2e45d89e);
</script> </script>
<script> <script>
@ -116,7 +96,7 @@
} }
trajeto_json_add({"features": []}); trajeto_json_add({"features": []});
trajeto_json.addTo(map_0d47d5844cb03a1b59409c5f2e45d89e); trajeto_json.addTo(map_413b17cf3f148cf9e5299ab727cb1cef);
function adicionarGeometria(novaGeometria) { function adicionarGeometria(novaGeometria) {
trajeto_json.addData(novaGeometria); trajeto_json.addData(novaGeometria);
@ -179,9 +159,9 @@
var marcadorEquipamento = L.marker([0, 0], { var marcadorEquipamento = L.marker([0, 0], {
icon: customIcon icon: customIcon
}).addTo(map_0d47d5844cb03a1b59409c5f2e45d89e); }).addTo(map_413b17cf3f148cf9e5299ab727cb1cef);
var marcadorBase = L.marker([0, 0], {}).addTo(map_0d47d5844cb03a1b59409c5f2e45d89e); var marcadorBase = L.marker([0, 0], {}).addTo(map_413b17cf3f148cf9e5299ab727cb1cef);
var icon = L.AwesomeMarkers.icon( var icon = L.AwesomeMarkers.icon(
{"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "red", "prefix": "glyphicon"} {"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "red", "prefix": "glyphicon"}
); );
@ -246,7 +226,7 @@
} }
if (foco) { if (foco) {
map_0d47d5844cb03a1b59409c5f2e45d89e.setView(novaPosicao, map_0d47d5844cb03a1b59409c5f2e45d89e.getZoom()); map_413b17cf3f148cf9e5299ab727cb1cef.setView(novaPosicao, map_413b17cf3f148cf9e5299ab727cb1cef.getZoom());
} }
} }
@ -268,7 +248,7 @@
marcadorDinamico.setRotationAngle(angulo); marcadorDinamico.setRotationAngle(angulo);
adicionarCoordenada("Tj", [novaLongitude, novaLatitude]); adicionarCoordenada("Tj", [novaLongitude, novaLatitude]);
map_0d47d5844cb03a1b59409c5f2e45d89e.setView(novaPosicao, map_0d47d5844cb03a1b59409c5f2e45d89e.getZoom());*/ map_413b17cf3f148cf9e5299ab727cb1cef.setView(novaPosicao, map_413b17cf3f148cf9e5299ab727cb1cef.getZoom());*/
}); });
function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) { function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) {

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool):
if not _snapshot_vw: if not _snapshot_vw:
visual_worker_atualizado = False visual_worker_atualizado = False
else: else:
visual_worker_atualizado = (time.time() - _snapshot_vw.get("ts", 0.0) <= 0.15) visual_worker_atualizado = (time.perf_counter() - _snapshot_vw.get("ts", 0.0) <= 1.0)
if visual_worker_atualizado: if visual_worker_atualizado:
custo, conf, anom, nav = unpack_snapshot(_snapshot_vw) custo, conf, anom, nav = unpack_snapshot(_snapshot_vw)
dists = _snapshot_vw.get("row_dist_m", None) dists = _snapshot_vw.get("row_dist_m", None)
@ -169,7 +169,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool):
except Exception as e: except Exception as e:
mostrar_log(f"❌ Erro ao definir comando direcional: {e}") mostrar_log(f"❌ Erro ao definir comando direcional: {e}")
def _comando_direcional_parado(definido: bool): def _comando_direcional_parado(definido: bool, frear: bool = False):
try: try:
angulo, tipo = comando_parado() angulo, tipo = comando_parado()
_cmd = { _cmd = {
@ -180,7 +180,8 @@ def _comando_direcional_parado(definido: bool):
"latencia": 0.0, "latencia": 0.0,
"angulo": angulo, "angulo": angulo,
"tipo": tipo.value, "tipo": tipo.value,
"simulacao": [] "simulacao": [],
"frear": frear
} }
return _cmd return _cmd
except Exception as e: except Exception as e:
@ -229,7 +230,7 @@ def _regras_taticas(contexto):
if decision.get("parar", False): if decision.get("parar", False):
mostrar_log(f"🟥 Parada necessaria por {reason}.") mostrar_log(f"🟥 Parada necessaria por {reason}.")
return _comando_direcional_parado(True) return _comando_direcional_parado(True, frear=True)
# motivo narrow: não para, mas dá dica lateral # motivo narrow: não para, mas dá dica lateral
if isinstance(block, dict) and reason == "narrow": if isinstance(block, dict) and reason == "narrow":

View File

@ -1,9 +1,10 @@
from shared.enums import ModoOperacao, StatusOperacao, StatusCarroMapa import time
from shared.enums import ModoOperacao, StatusModulo, StatusOperacao, StatusCarroMapa, T_Code
from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey
from manager_worker.config import mostrar_log from manager_worker.config import mostrar_log
from manager_worker.filtros import FiltroVelocidade from manager_worker.filtros import FiltroVelocidade
def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVelocidade): def definir_comando(parada_necessaria: bool, frear: bool, erro: bool, filtro_vel: FiltroVelocidade):
try: try:
_operacao = ContextoGlobalRedis.get_operacao() _operacao = ContextoGlobalRedis.get_operacao()
status_operacao = StatusOperacao(_operacao.get("status", StatusOperacao.NaoIniciado.value)) status_operacao = StatusOperacao(_operacao.get("status", StatusOperacao.NaoIniciado.value))
@ -11,15 +12,28 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc
if erro: if erro:
mostrar_log("🟥 Movimento parado: erro ao definir comando direcional.") mostrar_log("🟥 Movimento parado: erro ao definir comando direcional.")
return 0.0 return _montar_comando_retorno(0.0, False)
if parada_necessaria: if parada_necessaria:
mostrar_log("🟥 Movimento parado: direcional sem possibilidade de desvio.") mostrar_log("🟥 Movimento parado: direcional sem possibilidade de desvio.")
return 0.0 frenagem_automatica = ContextoGlobalRedis.get_controle().get("frenagem_automatica", False)
deve_frear = frenagem_automatica and frear
return _montar_comando_retorno(0.0, deve_frear)
if (status_operacao != StatusOperacao.EmAndamento) or finalizando: if (status_operacao != StatusOperacao.EmAndamento) or finalizando:
mostrar_log(f"🟥 Movimento parado: operação não está em andamento ou finalizando: {status_operacao.name}") mostrar_log(f"🟥 Movimento parado: operação não está em andamento ou finalizando: {status_operacao.name}")
return 0.0 return _montar_comando_retorno(0.0, False)
_dados_ww = ContextoGlobalRedis.get(CtxKey.DadosWeedWorker, {}).get("analise", {})
_snr = ContextoGlobalRedis.get_modulo(T_Code.Snr)
sonar_ativado = _operacao.get("Snr", {}).get("sonar_ativado", False)
visual_worker_operante = (_snr.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)) == StatusModulo.OPERANTE.value
analise_deteccao_atualizada = (time.perf_counter() - _dados_vw.get("matriz_confianca", {}).get("ts", 10.0) <= 1.0)
obstaculo_detectado = _dados_vw.get("matriz_confianca", {}).get("block", {}).get("decision", {}).get("parar", False) if analise_deteccao_atualizada else False
if (sonar_ativado and visual_worker_operante and obstaculo_detectado):
mostrar_log(f"🟥 Movimento parado: obstaculo proximo detectado no sonar")
return _montar_comando_retorno(0.0, True)
op_modo = ModoOperacao(_operacao.get("modo", ModoOperacao.NaoDefinido.value)) op_modo = ModoOperacao(_operacao.get("modo", ModoOperacao.NaoDefinido.value))
_contexto = ContextoGlobalRedis.get_contexto() _contexto = ContextoGlobalRedis.get_contexto()
@ -27,7 +41,7 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc
pulverizador_automatico = _controle.get("pulverizador_automatico", False) pulverizador_automatico = _controle.get("pulverizador_automatico", False)
#ervas_no_radar = _contexto.get("Gerais", {}).get("ervas_no_radar", False) #ervas_no_radar = _contexto.get("Gerais", {}).get("ervas_no_radar", False)
#percentual_ervas_no_radar = (_contexto.get("Gerais", {}).get("percentual_ervas_no_radar", 0)) * 100.0 #percentual_ervas_no_radar = (_contexto.get("Gerais", {}).get("percentual_ervas_no_radar", 0)) * 100.0
_dados_ww = ContextoGlobalRedis.get(CtxKey.DadosWeedWorker, {}).get("analise", {})
ervas_no_radar = _dados_ww.get("ervas_no_radar", False) ervas_no_radar = _dados_ww.get("ervas_no_radar", False)
percentual_ervas_no_radar = _dados_ww.get("estatisticas", {}).get("ema_global", 0.0) percentual_ervas_no_radar = _dados_ww.get("estatisticas", {}).get("ema_global", 0.0)
@ -41,6 +55,7 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc
status_carro = StatusCarroMapa.Parado status_carro = StatusCarroMapa.Parado
erro = 0 erro = 0
manobrando = False manobrando = False
reduzir_para_pulverizar = False
if op_modo == ModoOperacao.MapaGPS: if op_modo == ModoOperacao.MapaGPS:
_trajetoria = _contexto.get("Trajetoria", {}) _trajetoria = _contexto.get("Trajetoria", {})
@ -64,7 +79,8 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc
elif status_carro in [StatusCarroMapa.EntrandoRua, StatusCarroMapa.SaindoRua, StatusCarroMapa.Manobrando]: elif status_carro in [StatusCarroMapa.EntrandoRua, StatusCarroMapa.SaindoRua, StatusCarroMapa.Manobrando]:
velocidade_sp = min(vel_min, vel_com_ervas) velocidade_sp = min(vel_min, vel_com_ervas)
elif status_carro == StatusCarroMapa.CaminhandoRua: elif status_carro == StatusCarroMapa.CaminhandoRua:
if pulverizador_automatico and ervas_no_radar and percentual_ervas_no_radar > ervas_min_percenet: reduzir_para_pulverizar = pulverizador_automatico and ervas_no_radar and percentual_ervas_no_radar > ervas_min_percenet
if reduzir_para_pulverizar:
velocidade_sp = vel_com_ervas velocidade_sp = vel_com_ervas
else: else:
velocidade_sp = calcular_velocidade_relativa(vel_com_ervas, vel_sem_ervas, ang_max, erro) velocidade_sp = calcular_velocidade_relativa(vel_com_ervas, vel_sem_ervas, ang_max, erro)
@ -72,14 +88,14 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc
# Aplica limites # Aplica limites
velocidade_sp = max(vel_com_ervas, min(vel_sem_ervas, velocidade_sp)) velocidade_sp = max(vel_com_ervas, min(vel_sem_ervas, velocidade_sp))
if velocidade_sp < 1.0: if velocidade_sp < 1.0 or reduzir_para_pulverizar:
filtro_vel.reset(velocidade_sp) filtro_vel.reset(velocidade_sp)
else: else:
velocidade_sp = filtro_vel.filtrar(velocidade_sp) velocidade_sp = filtro_vel.filtrar(velocidade_sp)
#mostrar_log(f"🚗 Velocidade definida: {velocidade_sp:.1f}%") #mostrar_log(f"🚗 Velocidade definida: {velocidade_sp:.1f}%")
return velocidade_sp return _montar_comando_retorno(velocidade_sp, False)
except Exception as e: except Exception as e:
mostrar_log(f"Erro ao definir o comando de movimentacao: {e}") mostrar_log(f"Erro ao definir o comando de movimentacao: {e}")
@ -90,3 +106,9 @@ def calcular_velocidade_relativa(vel_min, vel_max, ang_max, erro_orientacao):
faixa = vel_max - vel_min faixa = vel_max - vel_min
velocidade = vel_max - (faixa * penalidade) velocidade = vel_max - (faixa * penalidade)
return round(velocidade, 2) return round(velocidade, 2)
def _montar_comando_retorno(velocidade_sp: float, frear: bool):
return {
"velocidade": velocidade_sp,
"frear": frear
}

View File

@ -21,19 +21,20 @@ class ProcessadorEmAndamento(ProcessadorBase):
saida_min=-ang_max, saida_min=-ang_max,
saida_max=ang_max saida_max=ang_max
) )
self.ultimo_comando_enviado = time.time() self.ultimo_comando_enviado = time.perf_counter()
def processar(self): def processar(self):
try: try:
agora = time.time() agora = time.perf_counter()
envio_necessario = (agora - self.ultimo_comando_enviado) > 0.3 envio_necessario = (agora - self.ultimo_comando_enviado) > 0.3
comando_dir = definir_comando_dir(self.pid_dir, envio_necessario) comando_dir = definir_comando_dir(self.pid_dir, envio_necessario)
if comando_dir.get("enviar_comando", False): if comando_dir.get("enviar_comando", False):
self.ultimo_comando_enviado = agora self.ultimo_comando_enviado = agora
velocidade_sp = definir_comando_mov(comando_dir.get("parada_necessaria", False), comando_dir.get("erro", False), self.filtro_mov) comando_mov = definir_comando_mov(comando_dir.get("parada_necessaria", False), comando_dir.get("frear", False), comando_dir.get("erro", False), self.filtro_mov)
return comando_controle( return comando_controle(
percentual_velocidade=velocidade_sp, percentual_velocidade=comando_mov.get("velocidade"),
frear=comando_mov.get("frear", False),
angulo=comando_dir.get("angulo"), angulo=comando_dir.get("angulo"),
tipo_movimento=comando_dir.get("tipo"), tipo_movimento=comando_dir.get("tipo"),
simulacao=comando_dir.get("simulacao"), simulacao=comando_dir.get("simulacao"),

View File

@ -3,7 +3,7 @@ from shared.enums import ModoOperacao, StatusOperacao
from manager_worker.config import mostrar_log from manager_worker.config import mostrar_log
from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey
def comando_controle(percentual_velocidade: float, angulo: float, tipo_movimento: int, simulacao = [], erro: bool = False, latencia: float = 0.0): def comando_controle(percentual_velocidade: float, frear: bool, angulo: float, tipo_movimento: int, simulacao = [], erro: bool = False, latencia: float = 0.0):
hb_atual = ContextoGlobalRedis.get_controle().get("heartbeat", 0) hb_atual = ContextoGlobalRedis.get_controle().get("heartbeat", 0)
if erro == False: if erro == False:
try: try:
@ -17,12 +17,14 @@ def comando_controle(percentual_velocidade: float, angulo: float, tipo_movimento
angulo_sp=angulo, angulo_sp=angulo,
tipo_movimento_direcional=tipo_movimento, tipo_movimento_direcional=tipo_movimento,
velocidade_sp=percentual_velocidade, velocidade_sp=percentual_velocidade,
em_freio=frear,
simulacao=simulacao, simulacao=simulacao,
heartbeat=hb_atual, heartbeat=hb_atual,
latencia=latencia latencia=latencia
) )
return { return {
"velocidade_sp": percentual_velocidade, "velocidade_sp": percentual_velocidade,
"em_freio": frear,
"angulo_sp": angulo, "angulo_sp": angulo,
"tipo_movimento_direcional": tipo_movimento, "tipo_movimento_direcional": tipo_movimento,
"simulacao": simulacao, "simulacao": simulacao,

View File

@ -126,10 +126,10 @@ def carregar_labelmap_completo(caminho):
id_para_nome[idx] = nome_classe id_para_nome[idx] = nome_classe
idx += 1 idx += 1
print(f"Mapa: {cor_para_id}") #print(f"Mapa: {cor_para_id}")
print(f"Colormap RGB: {cores_rgb}") #print(f"Colormap RGB: {cores_rgb}")
print(f"Classes: {id_para_nome}") #print(f"Classes: {id_para_nome}")
print(f"Ignore RGB: {ignore_rgb}") #print(f"Ignore RGB: {ignore_rgb}")
return cor_para_id, cores_rgb, id_para_nome, ignore_rgb return cor_para_id, cores_rgb, id_para_nome, ignore_rgb

View File

@ -875,218 +875,222 @@ class CameraManager:
# --- NOVOS (debug/uso opcional) --- # --- NOVOS (debug/uso opcional) ---
det_cov_max, det_conf_max, det_score det_cov_max, det_conf_max, det_score
""" """
if class_ids is None: try:
class_ids = {'rua': 0, 'cana': 1, 'obs': 2} if class_ids is None:
class_ids = {'rua': 0, 'cana': 1, 'obs': 2}
# ---------- defaults detecção ---------- # ---------- defaults detecção ----------
_det = { _det = {
# peso da penalização no custo # peso da penalização no custo
"w4": 0.25, # quão forte a detecção pesa no custo (0..1) "w4": 0.25, # quão forte a detecção pesa no custo (0..1)
# limiar pra "bloquear" navegação só por detecção # limiar pra "bloquear" navegação só por detecção
"thr_det_block": 0.35, # se det_score >= isso, célula deixa de ser navegável "thr_det_block": 0.35, # se det_score >= isso, célula deixa de ser navegável
# mínimo de interseção da bbox com a célula pra considerar (fração da célula) # mínimo de interseção da bbox com a célula pra considerar (fração da célula)
"min_cell_coverage": 0.10, "min_cell_coverage": 0.10,
# confiança mínima da bbox pra considerar # confiança mínima da bbox pra considerar
"min_det_conf": 0.35, "min_det_conf": 0.35,
# pesos por classe (se não souber o id, usa 1.0) # pesos por classe (se não souber o id, usa 1.0)
"class_weights": {}, # ex: {'person':1.0,'car':0.9,'dog':0.6} "class_weights": {}, # ex: {'person':1.0,'car':0.9,'dog':0.6}
# classes que vetam (tratadas como peso 1.0 e sem atenuação) # classes que vetam (tratadas como peso 1.0 e sem atenuação)
"veto_labels": set(["person"]), "veto_labels": set(["person"]),
# como combinar múltiplas bboxes na célula: "max" ou "sum_clamped" # como combinar múltiplas bboxes na célula: "max" ou "sum_clamped"
"combine": "max", "combine": "max",
# derrubar um pouco a conf_cell quando há detecção # derrubar um pouco a conf_cell quando há detecção
"conf_drop_alpha": 0.15, # 0 = não derruba; 0.15 = derruba 15% * det_score "conf_drop_alpha": 0.15, # 0 = não derruba; 0.15 = derruba 15% * det_score
} }
if det_params: if det_params:
_det.update(det_params) _det.update(det_params)
grid_w, grid_h = grid_shape grid_w, grid_h = grid_shape
H0, W0 = depth_mm.shape H0, W0 = depth_mm.shape
# --- 1) Resize depth para 512x288 --- # --- 1) Resize depth para 512x288 ---
d_small = cv2.resize(depth_mm, (512, 288), interpolation=cv2.INTER_NEAREST).astype(np.float32) d_small = cv2.resize(depth_mm, (512, 288), interpolation=cv2.INTER_NEAREST).astype(np.float32)
d_small[(d_small < valid_mm[0]) | (d_small > valid_mm[1])] = np.nan d_small[(d_small < valid_mm[0]) | (d_small > valid_mm[1])] = np.nan
# --- 2) Bordas da grid --- # --- 2) Bordas da grid ---
x_edges = np.linspace(0, 512, grid_w + 1, dtype=int) x_edges = np.linspace(0, 512, grid_w + 1, dtype=int)
y_edges = np.linspace(0, 288, grid_h + 1, dtype=int) y_edges = np.linspace(0, 288, grid_h + 1, dtype=int)
# --- 3) Saídas --- # --- 3) Saídas ---
pct_rua = np.zeros((grid_h, grid_w), np.float32) pct_rua = np.zeros((grid_h, grid_w), np.float32)
pct_cana = np.zeros((grid_h, grid_w), np.float32) pct_cana = np.zeros((grid_h, grid_w), np.float32)
pct_obs = np.zeros((grid_h, grid_w), np.float32) pct_obs = np.zeros((grid_h, grid_w), np.float32)
z_med = np.full((grid_h, grid_w), np.nan, np.float32) z_med = np.full((grid_h, grid_w), np.nan, np.float32)
depth_valid_frac = np.zeros((grid_h, grid_w), np.float32) depth_valid_frac = np.zeros((grid_h, grid_w), np.float32)
# --- 3b) mapas da detecção (debug/uso) --- # --- 3b) mapas da detecção (debug/uso) ---
det_cov_max = np.zeros((grid_h, grid_w), np.float32) # cobertura máxima (0..1) det_cov_max = np.zeros((grid_h, grid_w), np.float32) # cobertura máxima (0..1)
det_conf_max = np.zeros((grid_h, grid_w), np.float32) # conf máx (0..1) det_conf_max = np.zeros((grid_h, grid_w), np.float32) # conf máx (0..1)
det_score = np.zeros((grid_h, grid_w), np.float32) # score combinado (0..1) det_score = np.zeros((grid_h, grid_w), np.float32) # score combinado (0..1)
det_top_label_id = -np.ones((grid_h, grid_w), np.int32) # -1 = nenhuma det_top_label_id = -np.ones((grid_h, grid_w), np.int32) # -1 = nenhuma
det_top_conf = np.zeros((grid_h, grid_w), np.float32) # conf da dominante det_top_conf = np.zeros((grid_h, grid_w), np.float32) # conf da dominante
# --- 4) grid_ref 2D --- # --- 4) grid_ref 2D ---
if grid_ref.ndim == 1: if grid_ref.ndim == 1:
if grid_ref.shape[0] != grid_h: if grid_ref.shape[0] != grid_h:
raise ValueError(f"grid_ref 1D deve ter len={grid_h}, veio {grid_ref.shape}") raise ValueError(f"grid_ref 1D deve ter len={grid_h}, veio {grid_ref.shape}")
Z_ref = np.repeat(grid_ref[:, None], grid_w, axis=1) Z_ref = np.repeat(grid_ref[:, None], grid_w, axis=1)
else: else:
Z_ref = grid_ref Z_ref = grid_ref
if Z_ref.shape != (grid_h, grid_w): if Z_ref.shape != (grid_h, grid_w):
raise ValueError(f"grid_ref 2D deve ser {(grid_h, grid_w)}, veio {Z_ref.shape}") raise ValueError(f"grid_ref 2D deve ser {(grid_h, grid_w)}, veio {Z_ref.shape}")
# pré-slices por linha # pré-slices por linha
for j in range(grid_h): for j in range(grid_h):
y0, y1 = y_edges[j], y_edges[j+1] y0, y1 = y_edges[j], y_edges[j+1]
seg_row = seg_ids_512x288[y0:y1, :] seg_row = seg_ids_512x288[y0:y1, :]
depth_row = d_small[y0:y1, :] depth_row = d_small[y0:y1, :]
row_h = max(1, y1 - y0) row_h = max(1, y1 - y0)
for i in range(grid_w): for i in range(grid_w):
x0, x1 = x_edges[i], x_edges[i+1] x0, x1 = x_edges[i], x_edges[i+1]
col_w = max(1, x1 - x0) col_w = max(1, x1 - x0)
seg_block = seg_row[:, x0:x1] seg_block = seg_row[:, x0:x1]
depth_block = depth_row[:, x0:x1] depth_block = depth_row[:, x0:x1]
n = seg_block.size n = seg_block.size
if n == 0: if n == 0:
continue continue
# % por classe # % por classe
n_rua = np.count_nonzero(seg_block == ClassesSegmentacao.RUA.value) n_rua = np.count_nonzero(seg_block == ClassesSegmentacao.RUA.value)
n_cana = np.count_nonzero(seg_block == ClassesSegmentacao.CANA.value) n_cana = np.count_nonzero(seg_block == ClassesSegmentacao.CANA.value)
n_obs = np.count_nonzero(seg_block == ClassesSegmentacao.OBSTACULO.value) n_obs = np.count_nonzero(seg_block == ClassesSegmentacao.OBSTACULO.value)
pct_rua[j, i] = n_rua / n pct_rua[j, i] = n_rua / n
pct_cana[j, i] = n_cana / n pct_cana[j, i] = n_cana / n
pct_obs[j, i] = n_obs / n pct_obs[j, i] = n_obs / n
# depth # depth
vals = depth_block[~np.isnan(depth_block)] vals = depth_block[~np.isnan(depth_block)]
valid = vals.size valid = vals.size
depth_valid_frac[j, i] = valid / n depth_valid_frac[j, i] = valid / n
if valid >= max(int(min_valid_frac * n), 1): if valid >= max(int(min_valid_frac * n), 1):
z_med[j, i] = np.nanmedian(vals) / 1000.0 z_med[j, i] = np.nanmedian(vals) / 1000.0
# --- 6) Confiança --- # --- 6) Confiança ---
t0, t1 = conf_params t0, t1 = conf_params
conf_seg = np.maximum.reduce([pct_rua, pct_cana, pct_obs]) conf_seg = np.maximum.reduce([pct_rua, pct_cana, pct_obs])
conf_dep = np.clip((depth_valid_frac - t0) / (t1 - t0), 0.0, 1.0) conf_dep = np.clip((depth_valid_frac - t0) / (t1 - t0), 0.0, 1.0)
conf_cell = 0.6 * conf_seg + 0.4 * conf_dep conf_cell = 0.6 * conf_seg + 0.4 * conf_dep
# --- 6b) Rasterizar detecções (opcional) --- # --- 6b) Rasterizar detecções (opcional) ---
if deteccoes: if deteccoes:
# percorre bboxes e projeta para grid # percorre bboxes e projeta para grid
for det in deteccoes: for det in deteccoes:
conf = float(det.get("conf", 0.0)) conf = float(det.get("conf", 0.0))
if conf < _det["min_det_conf"]: if conf < _det["min_det_conf"]:
continue continue
label = str(det.get("label", "")) label = str(det.get("label", ""))
w_class = _det["class_weights"].get(label, 1.0) w_class = _det["class_weights"].get(label, 1.0)
veto = (label in _det["veto_labels"]) veto = (label in _det["veto_labels"])
# caixa em px (melhor usar bbox_px se já veio arredondado no teu pipeline) # caixa em px (melhor usar bbox_px se já veio arredondado no teu pipeline)
if "bbox_px" in det and det["bbox_px"]: if "bbox_px" in det and det["bbox_px"]:
x0p, y0p, x1p, y1p = det["bbox_px"] x0p, y0p, x1p, y1p = det["bbox_px"]
else: else:
x0n, y0n, x1n, y1n = det["bbox_norm"] x0n, y0n, x1n, y1n = det["bbox_norm"]
x0p = int(np.clip(x0n * 512, 0, 511)); x1p = int(np.clip(x1n * 512, 0, 512)) x0p = int(np.clip(x0n * 512, 0, 511)); x1p = int(np.clip(x1n * 512, 0, 512))
y0p = int(np.clip(y0n * 288, 0, 287)); y1p = int(np.clip(y1n * 288, 0, 288)) y0p = int(np.clip(y0n * 288, 0, 287)); y1p = int(np.clip(y1n * 288, 0, 288))
if x1p <= x0p or y1p <= y0p: if x1p <= x0p or y1p <= y0p:
continue continue
bbox_area = float((x1p - x0p) * (y1p - y0p)) bbox_area = float((x1p - x0p) * (y1p - y0p))
if bbox_area <= 1.0: if bbox_area <= 1.0:
continue continue
# descobre células que sobrepõem a bbox # descobre células que sobrepõem a bbox
# índices i (colunas) e j (linhas) candidatas # índices i (colunas) e j (linhas) candidatas
i0 = max(0, np.searchsorted(x_edges, x0p, side="right") - 1) i0 = max(0, np.searchsorted(x_edges, x0p, side="right") - 1)
i1 = min(grid_w-1, np.searchsorted(x_edges, x1p, side="left")) i1 = min(grid_w-1, np.searchsorted(x_edges, x1p, side="left"))
j0 = max(0, np.searchsorted(y_edges, y0p, side="right") - 1) j0 = max(0, np.searchsorted(y_edges, y0p, side="right") - 1)
j1 = min(grid_h-1, np.searchsorted(y_edges, y1p, side="left")) j1 = min(grid_h-1, np.searchsorted(y_edges, y1p, side="left"))
for j in range(j0, j1+1): for j in range(j0, j1+1):
y0, y1 = y_edges[j], y_edges[j+1] y0, y1 = y_edges[j], y_edges[j+1]
for i in range(i0, i1+1): for i in range(i0, i1+1):
x0, x1 = x_edges[i], x_edges[i+1] x0, x1 = x_edges[i], x_edges[i+1]
# interseção # interseção
ix0 = max(x0, x0p); ix1 = min(x1, x1p) ix0 = max(x0, x0p); ix1 = min(x1, x1p)
iy0 = max(y0, y0p); iy1 = min(y1, y1p) iy0 = max(y0, y0p); iy1 = min(y1, y1p)
if ix1 <= ix0 or iy1 <= iy0: if ix1 <= ix0 or iy1 <= iy0:
continue continue
inter = float((ix1 - ix0) * (iy1 - iy0)) inter = float((ix1 - ix0) * (iy1 - iy0))
# cobertura em relação à célula (mais conservador que em relação à bbox) # cobertura em relação à célula (mais conservador que em relação à bbox)
cell_area = float((x1 - x0) * (y1 - y0)) cell_area = float((x1 - x0) * (y1 - y0))
if cell_area <= 0: if cell_area <= 0:
continue continue
cov = inter / cell_area cov = inter / cell_area
if cov < _det["min_cell_coverage"]: if cov < _det["min_cell_coverage"]:
continue continue
# score local da detecção nesta célula # score local da detecção nesta célula
# se for classe vetada, zera atenuações # se for classe vetada, zera atenuações
base = conf if not veto else 1.0 base = conf if not veto else 1.0
s = base * cov * w_class s = base * cov * w_class
det_cov_max[j, i] = max(det_cov_max[j, i], cov) det_cov_max[j, i] = max(det_cov_max[j, i], cov)
det_conf_max[j, i] = max(det_conf_max[j, i], conf) det_conf_max[j, i] = max(det_conf_max[j, i], conf)
if _det["combine"] == "sum_clamped": if _det["combine"] == "sum_clamped":
det_score[j, i] = np.clip(det_score[j, i] + s, 0.0, 1.0) det_score[j, i] = np.clip(det_score[j, i] + s, 0.0, 1.0)
else: # "max" else: # "max"
det_score[j, i] = max(det_score[j, i], s) det_score[j, i] = max(det_score[j, i], s)
# critério: escolhe como dominante a de MAIOR (conf * cov) # critério: escolhe como dominante a de MAIOR (conf * cov)
keyval = conf * cov keyval = conf * cov
if keyval > det_top_conf[j, i]: if keyval > det_top_conf[j, i]:
det_top_conf[j, i] = keyval det_top_conf[j, i] = keyval
det_top_label_id[j, i] = int(det.get("label_id", -1)) det_top_label_id[j, i] = int(det.get("label_id", -1))
# opcional: derruba um pouco a confiança onde há detecção # opcional: derruba um pouco a confiança onde há detecção
if _det["conf_drop_alpha"] > 0.0: if _det["conf_drop_alpha"] > 0.0:
conf_cell = np.clip(conf_cell * (1.0 - _det["conf_drop_alpha"] * det_score), 0.0, 1.0) conf_cell = np.clip(conf_cell * (1.0 - _det["conf_drop_alpha"] * det_score), 0.0, 1.0)
# --- 7) Anomalia (igual à tua) --- # --- 7) Anomalia (igual à tua) ---
delta = Z_ref - z_med delta = Z_ref - z_med
delta = np.where(np.isnan(z_med), 0.0, np.maximum(delta, 0.0)) delta = np.where(np.isnan(z_med), 0.0, np.maximum(delta, 0.0))
anom_raw = np.clip(delta / anom_satur_m, 0.0, 1.0) anom_raw = np.clip(delta / anom_satur_m, 0.0, 1.0)
anom = anom_raw * (delta > anom_tau_min).astype(np.float32) * conf_dep anom = anom_raw * (delta > anom_tau_min).astype(np.float32) * conf_dep
# --- 8) Custo e navegabilidade --- # --- 8) Custo e navegabilidade ---
nao_rua = 1.0 - pct_rua nao_rua = 1.0 - pct_rua
w1, w2, w3 = w w1, w2, w3 = w
custo = w1 * nao_rua + w2 * anom + w3 * (1.0 - conf_cell) custo = w1 * nao_rua + w2 * anom + w3 * (1.0 - conf_cell)
# penalização por detecção (se houver) # penalização por detecção (se houver)
if deteccoes: if deteccoes:
custo = np.clip(custo + _det["w4"] * det_score, 0.0, 1.0) custo = np.clip(custo + _det["w4"] * det_score, 0.0, 1.0)
# regra de navegabilidade com detecção (bloqueia se score alto) # regra de navegabilidade com detecção (bloqueia se score alto)
if deteccoes: if deteccoes:
navegavel = (pct_rua >= 0.55) & (anom < 0.4) & (conf_cell >= 0.5) & (det_score < _det["thr_det_block"]) navegavel = (pct_rua >= 0.55) & (anom < 0.4) & (conf_cell >= 0.5) & (det_score < _det["thr_det_block"])
else: else:
navegavel = (pct_rua >= 0.55) & (anom < 0.4) & (conf_cell >= 0.5) navegavel = (pct_rua >= 0.55) & (anom < 0.4) & (conf_cell >= 0.5)
return { return {
"pct_rua": pct_rua, "pct_rua": pct_rua,
"pct_cana": pct_cana, "pct_cana": pct_cana,
"pct_obs": pct_obs, "pct_obs": pct_obs,
"z_med": z_med, "z_med": z_med,
"z_ref": Z_ref, "z_ref": Z_ref,
"depth_valid_frac": depth_valid_frac, "depth_valid_frac": depth_valid_frac,
"conf": np.clip(custo*0 + conf_cell, 0.0, 1.0), # garante 0..1 "conf": np.clip(custo*0 + conf_cell, 0.0, 1.0), # garante 0..1
"anom": np.clip(anom, 0.0, 1.0), "anom": np.clip(anom, 0.0, 1.0),
"custo": np.clip(custo, 0.0, 1.0), "custo": np.clip(custo, 0.0, 1.0),
"navegavel": navegavel.astype(np.uint8), "navegavel": navegavel.astype(np.uint8),
# ---- extras p/ debug/telemetria ---- # ---- extras p/ debug/telemetria ----
"det_cov_max": det_cov_max, "det_cov_max": det_cov_max,
"det_conf_max": det_conf_max, "det_conf_max": det_conf_max,
"det_score": det_score, "det_score": det_score,
"det_top_label_id": det_top_label_id, "det_top_label_id": det_top_label_id,
"det_top_conf": det_top_conf, "det_top_conf": det_top_conf,
} }
except Exception as e:
self.mostrar_log(f"Erro ao construir grid de confianca: {e}")
return None
def _put_text_centered(self, img, text, cx, cy, font_scale=0.4, thickness=1, color=(255,255,255), outline=True): def _put_text_centered(self, img, text, cx, cy, font_scale=0.4, thickness=1, color=(255,255,255), outline=True):
font = cv2.FONT_HERSHEY_SIMPLEX font = cv2.FONT_HERSHEY_SIMPLEX
@ -1400,193 +1404,197 @@ class CameraManager:
a_max_freio=0.8, # << NOVO (m/s²) a_max_freio=0.8, # << NOVO (m/s²)
margem_parada=0.25, # << NOVO (m) margem_parada=0.25, # << NOVO (m)
): ):
# --- unpack do snapshot --- try:
custo_f, conf_f, anom_f, nav_f = unpack_snapshot(snapshot) # --- unpack do snapshot ---
row_dist_m = np.asarray(snapshot.get("row_dist_m"), dtype=np.float32) custo_f, conf_f, anom_f, nav_f = unpack_snapshot(snapshot)
row_scale_x_m = np.asarray(snapshot.get("row_scale_x_m"), dtype=np.float32) row_dist_m = np.asarray(snapshot.get("row_dist_m"), dtype=np.float32)
fuse = snapshot.get("fuse", {}) row_scale_x_m = np.asarray(snapshot.get("row_scale_x_m"), dtype=np.float32)
central_cols = fuse.get("central_cols", None) fuse = snapshot.get("fuse", {})
if central_cols is None: central_cols = fuse.get("central_cols", None)
# fallback: terço central if central_cols is None:
H, W = custo_f.shape # fallback: terço central
central_cols = (W//3, 2*W//3) H, W = custo_f.shape
else: central_cols = (W//3, 2*W//3)
central_cols = (int(central_cols[0]), int(central_cols[1]))
# prioriza near_is_bottom do snap, se vier
if "near_is_bottom" in fuse:
near_is_bottom = bool(fuse["near_is_bottom"])
rgb_frame = cv2.resize(rgb_frame, (1280, 720))
Hf, Wf = rgb_frame.shape[:2]
H, W = custo_f.shape
# --- métricas: usa do snap se existir; senão calcula ---
metrics = snapshot.get("block")
blocked = bool(metrics.get("blocked", False))
reason = metrics.get("reason", "none") or "none"
reason_detail = metrics.get("reason_detail", "none") or "none"
d_obs_min = metrics.get("d_obs_true_min_m", None)
j_block = metrics.get("j_block", None)
cov_cent = metrics.get("coverage", {}).get("central_max", 0.0)
cov_glob = metrics.get("coverage", {}).get("global", 0.0)
decision = metrics.get("decision", {})
sb = metrics.get("side_bias", {}) or {}
side_val = float(sb.get("value", 0.0))
left_frac = float(sb.get("left_frac", 0.0))
right_frac= float(sb.get("right_frac", 0.0))
# --- overlays ---
mask_rgb, mask_anom, mask_cost, mask_conf = self._colorize_masks(
anom_f, custo_f, conf_f,
thr_anom_block=thr_anom_block,
thr_cost_block=thr_cost_block,
thr_conf_low=thr_conf_low
)
mask_rgb_resized = cv2.resize(mask_rgb, (Wf, Hf), interpolation=cv2.INTER_NEAREST)
vis = rgb_frame.copy()
vis = cv2.addWeighted(vis, 1.0, mask_rgb_resized, alpha, 0)
# --- desenha linha/retângulo na j_block ---
if j_block is not None and 0 <= j_block < H:
y = int((j_block + 0.5) * Hf / H)
color_line = (0, 0, 255) if blocked else (0, 255, 255)
cv2.line(vis, (0, y), (Wf, y), color_line, 2)
c0, c1 = central_cols
c0 = max(0, min(W-1, int(c0)))
c1 = max(0, min(W, int(c1)))
if c1 <= c0:
c0, c1 = W//3, 2*W//3
width_need_m = robot_width_m + margin_m
sx = row_scale_x_m[j_block] if row_scale_x_m.size == H else (width_need_m / max(1, (c1 - c0)))
if not np.isfinite(sx) or sx <= 1e-6:
ncols = (c1 - c0)
else: else:
ncols = int(np.ceil(width_need_m / sx)) central_cols = (int(central_cols[0]), int(central_cols[1]))
ncols = max(1, min(W, ncols))
mid = (c0 + c1) // 2 # prioriza near_is_bottom do snap, se vier
half = ncols // 2 if "near_is_bottom" in fuse:
a = max(0, mid - half) near_is_bottom = bool(fuse["near_is_bottom"])
b = min(W, a + ncols)
a = max(0, b - ncols)
x1 = int(a * Wf / W) rgb_frame = cv2.resize(rgb_frame, (1280, 720))
x2 = int(b * Wf / W)
cv2.rectangle(vis, (x1, max(0, y-12)), (x2, min(Hf-1, y+12)), (0, 255, 0), 2)
txt = f"{reason.upper()} | d={d_obs_min:.2f} m" if d_obs_min is not None else f"{reason.upper()} | d=" Hf, Wf = rgb_frame.shape[:2]
cv2.putText(vis, txt, (10, max(20, y-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color_line, 2, cv2.LINE_AA) H, W = custo_f.shape
# --- HUDs (legíveis) --- # --- métricas: usa do snap se existir; senão calcula ---
x0, y0 = 10, 30 metrics = snapshot.get("block")
bar_w, bar_h = 200, 12
line_gap = 8
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.60
thick = 2
def put_text_outlined(img, text, org, font, font_scale, color_fg, thickness): blocked = bool(metrics.get("blocked", False))
# contorno preto reason = metrics.get("reason", "none") or "none"
cv2.putText(img, text, org, font, font_scale, (0,0,0), thickness+2, cv2.LINE_AA) reason_detail = metrics.get("reason_detail", "none") or "none"
# texto d_obs_min = metrics.get("d_obs_true_min_m", None)
cv2.putText(img, text, org, font, font_scale, color_fg, thickness, cv2.LINE_AA) j_block = metrics.get("j_block", None)
cov_cent = metrics.get("coverage", {}).get("central_max", 0.0)
cov_glob = metrics.get("coverage", {}).get("global", 0.0)
decision = metrics.get("decision", {})
sb = metrics.get("side_bias", {}) or {}
side_val = float(sb.get("value", 0.0))
left_frac = float(sb.get("left_frac", 0.0))
right_frac= float(sb.get("right_frac", 0.0))
def draw_bar(img, label, frac, top_left, color_fill=(0,255,255)): # --- overlays ---
x, y = top_left mask_rgb, mask_anom, mask_cost, mask_conf = self._colorize_masks(
# label acima da barra anom_f, custo_f, conf_f,
put_text_outlined(img, label, (x, y-2), font, font_scale, (255,255,255), thick) thr_anom_block=thr_anom_block,
# moldura thr_cost_block=thr_cost_block,
cv2.rectangle(img, (x, y+4), (x + bar_w, y + 4 + bar_h), (220,220,220), 1) thr_conf_low=thr_conf_low
# preenchimento )
fw = int(bar_w * float(np.clip(frac, 0, 1))) mask_rgb_resized = cv2.resize(mask_rgb, (Wf, Hf), interpolation=cv2.INTER_NEAREST)
if fw > 0:
cv2.rectangle(img, (x, y+4), (x + fw, y + 4 + bar_h), color_fill, -1)
# mede a altura ocupada pelo bloco para pintar um painel ao fundo vis = rgb_frame.copy()
panel_h = ( vis = cv2.addWeighted(vis, 1.0, mask_rgb_resized, alpha, 0)
# 2 barras (cada uma tem label+barra) + gaps
(bar_h + 4) * 2 + (line_gap + 14) * 2
)
panel_w = max(260, bar_w + 70)
# painel semi-transparente # --- desenha linha/retângulo na j_block ---
overlay = vis.copy() if j_block is not None and 0 <= j_block < H:
cv2.rectangle(overlay, (x0-6, y0-6), (x0-6 + panel_w, y0-6 + panel_h), (0,0,0), -1) y = int((j_block + 0.5) * Hf / H)
cv2.addWeighted(overlay, 0.35, vis, 0.65, 0, vis) color_line = (0, 0, 255) if blocked else (0, 255, 255)
cv2.line(vis, (0, y), (Wf, y), color_line, 2)
# barras Global / Central c0, c1 = central_cols
draw_bar(vis, f"Global {cov_glob:.2f}", cov_glob, (x0, y0)) c0 = max(0, min(W-1, int(c0)))
y0 += bar_h + line_gap + 14 c1 = max(0, min(W, int(c1)))
draw_bar(vis, f"Central {cov_cent:.2f}", cov_cent, (x0, y0)) if c1 <= c0:
y0 += bar_h + line_gap + 14 c0, c1 = W//3, 2*W//3
# SideBias width_need_m = robot_width_m + margin_m
put_text_outlined(vis, f"SideBias {side_val:+.2f}", (x0, y0), sx = row_scale_x_m[j_block] if row_scale_x_m.size == H else (width_need_m / max(1, (c1 - c0)))
font, font_scale, (255,255,255), thick) if not np.isfinite(sx) or sx <= 1e-6:
cx = x0 + bar_w//2 ncols = (c1 - c0)
y_bar = y0 + 14 else:
# linha base -1..+1 ncols = int(np.ceil(width_need_m / sx))
cv2.line(vis, (x0, y_bar), (x0+bar_w, y_bar), (220,220,220), 1) ncols = max(1, min(W, ncols))
# marca central
cv2.line(vis, (cx, y_bar-4), (cx, y_bar+4), (255,255,255), 1)
# cursor do bias
bx = int(cx + (bar_w//2) * float(np.clip(side_val, -1, 1)))
cv2.circle(vis, (bx, y_bar), 5, (0,255,0), -1)
# L / R mid = (c0 + c1) // 2
put_text_outlined(vis, f"L:{left_frac:.2f} R:{right_frac:.2f}", (x0, y_bar + 20), half = ncols // 2
font, font_scale, (255,255,255), thick) a = max(0, mid - half)
b = min(W, a + ncols)
a = max(0, b - ncols)
# --- DECISION HUD: PARAR / LIVRE --- x1 = int(a * Wf / W)
# empurra um pouco pra baixo do L/R x2 = int(b * Wf / W)
y0_dec = y_bar + 50 cv2.rectangle(vis, (x1, max(0, y-12)), (x2, min(Hf-1, y+12)), (0, 255, 0), 2)
parada_necessaria = decision.get("parar", False) txt = f"{reason.upper()} | d={d_obs_min:.2f} m" if d_obs_min is not None else f"{reason.upper()} | d=-"
dec_txt = "PARAR" if parada_necessaria else "LIVRE" cv2.putText(vis, txt, (10, max(20, y-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color_line, 2, cv2.LINE_AA)
dec_col = (0, 0, 255) if parada_necessaria else (0, 200, 0)
dec_info = (f"v={velocidade_media:.3f} m/s d_obs={('-' if d_obs_min is None else f'{d_obs_min:.2f} m')} "
f"d_necess={decision.get('dist_necessaria', 0.0):.2f} m")
# painel por trás para legibilidade # --- HUDs (legíveis) ---
panel_w2 = max(280, bar_w + 100) x0, y0 = 10, 30
overlay2 = vis.copy() bar_w, bar_h = 200, 12
cv2.rectangle(overlay2, (x0-6, y0_dec-24), (x0-6 + panel_w2, y0_dec+26), (0,0,0), -1) line_gap = 8
cv2.addWeighted(overlay2, 0.35, vis, 0.65, 0, vis) font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.60
thick = 2
# linha 1: PARAR / LIVRE (grande) def put_text_outlined(img, text, org, font, font_scale, color_fg, thickness):
put_text_outlined(vis, f"{dec_txt}", (x0, y0_dec-4), font, 0.80, dec_col, thick) # contorno preto
cv2.putText(img, text, org, font, font_scale, (0,0,0), thickness+2, cv2.LINE_AA)
# texto
cv2.putText(img, text, org, font, font_scale, color_fg, thickness, cv2.LINE_AA)
# linha 2: detalhes (menor) def draw_bar(img, label, frac, top_left, color_fill=(0,255,255)):
put_text_outlined(vis, dec_info, (x0, y0_dec+18), font, 0.58, (255,255,255), thick) x, y = top_left
# label acima da barra
put_text_outlined(img, label, (x, y-2), font, font_scale, (255,255,255), thick)
# moldura
cv2.rectangle(img, (x, y+4), (x + bar_w, y + 4 + bar_h), (220,220,220), 1)
# preenchimento
fw = int(bar_w * float(np.clip(frac, 0, 1)))
if fw > 0:
cv2.rectangle(img, (x, y+4), (x + fw, y + 4 + bar_h), color_fill, -1)
# linha 3: detalhes (menor) # mede a altura ocupada pelo bloco para pintar um painel ao fundo
put_text_outlined(vis, reason_detail, (x0, y0_dec+50), font, 0.58, (255,255,255), thick) panel_h = (
# 2 barras (cada uma tem label+barra) + gaps
(bar_h + 4) * 2 + (line_gap + 14) * 2
)
panel_w = max(260, bar_w + 70)
# painel semi-transparente
overlay = vis.copy()
cv2.rectangle(overlay, (x0-6, y0-6), (x0-6 + panel_w, y0-6 + panel_h), (0,0,0), -1)
cv2.addWeighted(overlay, 0.35, vis, 0.65, 0, vis)
# barras Global / Central
draw_bar(vis, f"Global {cov_glob:.2f}", cov_glob, (x0, y0))
y0 += bar_h + line_gap + 14
draw_bar(vis, f"Central {cov_cent:.2f}", cov_cent, (x0, y0))
y0 += bar_h + line_gap + 14
# SideBias
put_text_outlined(vis, f"SideBias {side_val:+.2f}", (x0, y0),
font, font_scale, (255,255,255), thick)
cx = x0 + bar_w//2
y_bar = y0 + 14
# linha base -1..+1
cv2.line(vis, (x0, y_bar), (x0+bar_w, y_bar), (220,220,220), 1)
# marca central
cv2.line(vis, (cx, y_bar-4), (cx, y_bar+4), (255,255,255), 1)
# cursor do bias
bx = int(cx + (bar_w//2) * float(np.clip(side_val, -1, 1)))
cv2.circle(vis, (bx, y_bar), 5, (0,255,0), -1)
# L / R
put_text_outlined(vis, f"L:{left_frac:.2f} R:{right_frac:.2f}", (x0, y_bar + 20),
font, font_scale, (255,255,255), thick)
# --- DECISION HUD: PARAR / LIVRE ---
# empurra um pouco pra baixo do L/R
y0_dec = y_bar + 50
parada_necessaria = decision.get("parar", False)
dec_txt = "PARAR" if parada_necessaria else "LIVRE"
dec_col = (0, 0, 255) if parada_necessaria else (0, 200, 0)
dec_info = (f"v={velocidade_media:.3f} m/s d_obs={('-' if d_obs_min is None else f'{d_obs_min:.2f} m')} "
f"d_necess={decision.get('dist_necessaria', 0.0):.2f} m")
# painel por trás para legibilidade
panel_w2 = max(280, bar_w + 100)
overlay2 = vis.copy()
cv2.rectangle(overlay2, (x0-6, y0_dec-24), (x0-6 + panel_w2, y0_dec+26), (0,0,0), -1)
cv2.addWeighted(overlay2, 0.35, vis, 0.65, 0, vis)
# linha 1: PARAR / LIVRE (grande)
put_text_outlined(vis, f"{dec_txt}", (x0, y0_dec-4), font, 0.80, dec_col, thick)
# linha 2: detalhes (menor)
put_text_outlined(vis, dec_info, (x0, y0_dec+18), font, 0.58, (255,255,255), thick)
# linha 3: detalhes (menor)
put_text_outlined(vis, reason_detail, (x0, y0_dec+50), font, 0.58, (255,255,255), thick)
legend = [ legend = [
("Anom >= thr", (255, 0, 255)), ("Anom >= thr", (255, 0, 255)),
("Custo >= thr", (0,165,255)), ("Custo >= thr", (0,165,255)),
("Conf < thr", (255, 0, 0)), ("Conf < thr", (255, 0, 0)),
] ]
lx, ly = 10, Hf - 10 - 18*len(legend) lx, ly = 10, Hf - 10 - 18*len(legend)
for i, (txt, col) in enumerate(legend): for i, (txt, col) in enumerate(legend):
y = ly + i*18 y = ly + i*18
cv2.rectangle(vis, (lx, y-12), (lx+18, y+2), col, -1) cv2.rectangle(vis, (lx, y-12), (lx+18, y+2), col, -1)
cv2.putText(vis, txt, (lx+24, y), cv2.FONT_HERSHEY_SIMPLEX, 0.48, (255,255,255), 1, cv2.LINE_AA) cv2.putText(vis, txt, (lx+24, y), cv2.FONT_HERSHEY_SIMPLEX, 0.48, (255,255,255), 1, cv2.LINE_AA)
status_txt = f"BLOCKED: {blocked} ({reason})" status_txt = f"BLOCKED: {blocked} ({reason})"
status_col = (0,0,255) if blocked else (0,255,0) status_col = (0,0,255) if blocked else (0,255,0)
cv2.putText(vis, status_txt, (Wf - 40 - 8*len(status_txt), 24), cv2.FONT_HERSHEY_SIMPLEX, 0.6, status_col, 2, cv2.LINE_AA) cv2.putText(vis, status_txt, (Wf - 40 - 8*len(status_txt), 24), cv2.FONT_HERSHEY_SIMPLEX, 0.6, status_col, 2, cv2.LINE_AA)
cv2.imshow(win_name, vis) cv2.imshow(win_name, vis)
cv2.waitKey(1) cv2.waitKey(1)
return vis, metrics return vis, metrics
except Exception as e:
self.mostrar_log(f"Erro ao criar debug blockage imshow: {e}")
return None, None
def _overlay_deteccoes( def _overlay_deteccoes(
@ -1610,99 +1618,102 @@ class CameraManager:
} }
Retorna: (frame_com_overlay, fps_state, keep_loop_bool) Retorna: (frame_com_overlay, fps_state, keep_loop_bool)
""" """
img = cv2.resize(rgb_frame.copy(), (1280, 720)) try:
H, W = img.shape[:2] img = cv2.resize(rgb_frame.copy(), (1280, 720))
H, W = img.shape[:2]
# paleta simples por classe # paleta simples por classe
palette = [ palette = [
(255, 56, 56), (255, 157, 151), (72, 249, 10), (0, 255, 0), (0, 0, 255), (255, 56, 56), (255, 157, 151), (72, 249, 10), (0, 255, 0), (0, 0, 255),
(255, 0, 255), (0, 255, 255), (255, 191, 0), (52, 148, 230), (147, 112, 219) (255, 0, 255), (0, 255, 255), (255, 191, 0), (52, 148, 230), (147, 112, 219)
] ]
def _map_bbox_norm_to_full(bn): def _map_bbox_norm_to_full(bn):
# bn é [x0n,y0n,x1n,y1n] relativo ao input da ROI (0..1) # bn é [x0n,y0n,x1n,y1n] relativo ao input da ROI (0..1)
x0n, y0n, x1n, y1n = bn x0n, y0n, x1n, y1n = bn
if roi_frac is not None:
rx1, ry1, rx2, ry2 = roi_frac
sx, sy = (rx2 - rx1), (ry2 - ry1)
x0 = int(round((rx1 + x0n * sx) * W))
y0 = int(round((ry1 + y0n * sy) * H))
x1 = int(round((rx1 + x1n * sx) * W))
y1 = int(round((ry1 + y1n * sy) * H))
else:
x0 = int(round(x0n * W))
y0 = int(round(y0n * H))
x1 = int(round(x1n * W))
y1 = int(round(y1n * H))
# clamp
x0 = max(0, min(W - 1, x0)); x1 = max(0, min(W - 1, x1))
y0 = max(0, min(H - 1, y0)); y1 = max(0, min(H - 1, y1))
return x0, y0, x1, y1
def _put_label(img, text, x, y, bg):
(tw, th), _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
cv2.rectangle(img, (x, max(0, y - th - 6)), (x + tw + 6, y), bg, -1)
cv2.putText(img, text, (x + 3, y - 4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)
# desenhar ROI (opcional, ajuda debug)
if roi_frac is not None: if roi_frac is not None:
rx1, ry1, rx2, ry2 = roi_frac rx1, ry1, rx2, ry2 = roi_frac
sx, sy = (rx2 - rx1), (ry2 - ry1) x0r, y0r = int(rx1 * W), int(ry1 * H)
x0 = int(round((rx1 + x0n * sx) * W)) x1r, y1r = int(rx2 * W), int(ry2 * H)
y0 = int(round((ry1 + y0n * sy) * H)) cv2.rectangle(img, (x0r, y0r), (x1r, y1r), (60, 60, 60), 1)
x1 = int(round((rx1 + x1n * sx) * W))
y1 = int(round((ry1 + y1n * sy) * H))
else:
x0 = int(round(x0n * W))
y0 = int(round(y0n * H))
x1 = int(round(x1n * W))
y1 = int(round(y1n * H))
# clamp
x0 = max(0, min(W - 1, x0)); x1 = max(0, min(W - 1, x1))
y0 = max(0, min(H - 1, y0)); y1 = max(0, min(H - 1, y1))
return x0, y0, x1, y1
def _put_label(img, text, x, y, bg): # desenhar detecções
(tw, th), _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1) for d in dets:
cv2.rectangle(img, (x, max(0, y - th - 6)), (x + tw + 6, y), bg, -1) if d.get("conf", 0.0) < conf_thr:
cv2.putText(img, text, (x + 3, y - 4), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)
# desenhar ROI (opcional, ajuda debug)
if roi_frac is not None:
rx1, ry1, rx2, ry2 = roi_frac
x0r, y0r = int(rx1 * W), int(ry1 * H)
x1r, y1r = int(rx2 * W), int(ry2 * H)
cv2.rectangle(img, (x0r, y0r), (x1r, y1r), (60, 60, 60), 1)
# desenhar detecções
for d in dets:
if d.get("conf", 0.0) < conf_thr:
continue
# bbox em px do frame
if "bbox_full" in d and d["bbox_full"]:
x0, y0, x1, y1 = d["bbox_full"]
# clamp se necessário
x0 = max(0, min(W - 1, int(x0))); x1 = max(0, min(W - 1, int(x1)))
y0 = max(0, min(H - 1, int(y0))); y1 = max(0, min(H - 1, int(y1)))
else:
bn = d.get("bbox_norm", None)
if not bn:
continue continue
x0, y0, x1, y1 = _map_bbox_norm_to_full(bn)
if x1 <= x0 or y1 <= y0: # bbox em px do frame
continue if "bbox_full" in d and d["bbox_full"]:
x0, y0, x1, y1 = d["bbox_full"]
# clamp se necessário
x0 = max(0, min(W - 1, int(x0))); x1 = max(0, min(W - 1, int(x1)))
y0 = max(0, min(H - 1, int(y0))); y1 = max(0, min(H - 1, int(y1)))
else:
bn = d.get("bbox_norm", None)
if not bn:
continue
x0, y0, x1, y1 = _map_bbox_norm_to_full(bn)
lid = int(d.get("label_id", -1)) if x1 <= x0 or y1 <= y0:
color = palette[lid % len(palette)] if lid >= 0 else (0, 255, 0) continue
cv2.rectangle(img, (x0, y0), (x1, y1), color, 2) lid = int(d.get("label_id", -1))
color = palette[lid % len(palette)] if lid >= 0 else (0, 255, 0)
name = d.get("label", None) cv2.rectangle(img, (x0, y0), (x1, y1), color, 2)
txt = f"{name or f'id:{lid}'} {d.get('conf', 0.0):.2f}"
_put_label(img, txt, x0, y0, color)
# FPS (EMA) name = d.get("label", None)
now = time.monotonic() txt = f"{name or f'id:{lid}'} {d.get('conf', 0.0):.2f}"
if fps_state is None: _put_label(img, txt, x0, y0, color)
fps_state = {}
t_prev = fps_state.get("t_prev")
fps_ema = fps_state.get("fps_ema")
if t_prev is not None:
dt = now - t_prev
if dt > 0:
fps_inst = 1.0 / dt
alpha = 0.90
fps_ema = fps_inst if fps_ema is None else (alpha * fps_ema + (1 - alpha) * fps_inst)
fps_state["t_prev"] = now
fps_state["fps_ema"] = fps_ema
if fps_ema: # FPS (EMA)
cv2.putText(img, f"FPS: {fps_ema:.1f}", (10, 22), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (50, 220, 50), 2, cv2.LINE_AA) now = time.monotonic()
if fps_state is None:
fps_state = {}
t_prev = fps_state.get("t_prev")
fps_ema = fps_state.get("fps_ema")
if t_prev is not None:
dt = now - t_prev
if dt > 0:
fps_inst = 1.0 / dt
alpha = 0.90
fps_ema = fps_inst if fps_ema is None else (alpha * fps_ema + (1 - alpha) * fps_inst)
fps_state["t_prev"] = now
fps_state["fps_ema"] = fps_ema
keep = True if fps_ema:
if show: cv2.putText(img, f"FPS: {fps_ema:.1f}", (10, 22), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (50, 220, 50), 2, cv2.LINE_AA)
cv2.imshow(janela, img)
k = cv2.waitKey(1) & 0xFF
keep = (k != 27) # ESC para sair
return img, fps_state, keep keep = True
if show:
cv2.imshow(janela, img)
k = cv2.waitKey(1) & 0xFF
keep = (k != 27) # ESC para sair
return img, fps_state, keep
except Exception as e:
self.mostrar_log(f"Erro ao gerar overlay de deteccoes")

View File

@ -62,6 +62,7 @@
this.cmbConfiguracaoUltrassom = new System.Windows.Forms.ComboBox(); this.cmbConfiguracaoUltrassom = new System.Windows.Forms.ComboBox();
this.btnConfigurar = new System.Windows.Forms.Button(); this.btnConfigurar = new System.Windows.Forms.Button();
this.gpbLocomocao = new System.Windows.Forms.GroupBox(); this.gpbLocomocao = new System.Windows.Forms.GroupBox();
this.chbMovimentacaoAutomatica = new System.Windows.Forms.CheckBox();
this.nudVelMin = new System.Windows.Forms.NumericUpDown(); this.nudVelMin = new System.Windows.Forms.NumericUpDown();
this.nudVelMax = new System.Windows.Forms.NumericUpDown(); this.nudVelMax = new System.Windows.Forms.NumericUpDown();
this.lblKmh2 = new System.Windows.Forms.Label(); this.lblKmh2 = new System.Windows.Forms.Label();
@ -71,6 +72,7 @@
this.lblVelocidadeComErvas = new System.Windows.Forms.Label(); this.lblVelocidadeComErvas = new System.Windows.Forms.Label();
this.lblVelocidadeSemErvas = new System.Windows.Forms.Label(); this.lblVelocidadeSemErvas = new System.Windows.Forms.Label();
this.gpbAtuador = new System.Windows.Forms.GroupBox(); this.gpbAtuador = new System.Windows.Forms.GroupBox();
this.chbPulverizadorAutomatico = new System.Windows.Forms.CheckBox();
this.txtQtdCameras = new System.Windows.Forms.TextBox(); this.txtQtdCameras = new System.Windows.Forms.TextBox();
this.lblQuantidadeCamerasSolo = new System.Windows.Forms.Label(); this.lblQuantidadeCamerasSolo = new System.Windows.Forms.Label();
this.lblMs = new System.Windows.Forms.Label(); this.lblMs = new System.Windows.Forms.Label();
@ -121,8 +123,7 @@
this.chbMapa = new System.Windows.Forms.CheckBox(); this.chbMapa = new System.Windows.Forms.CheckBox();
this.rtbCam = new System.Windows.Forms.RichTextBox(); this.rtbCam = new System.Windows.Forms.RichTextBox();
this.chbCameraSolo = new System.Windows.Forms.CheckBox(); this.chbCameraSolo = new System.Windows.Forms.CheckBox();
this.chbPulverizadorAutomatico = new System.Windows.Forms.CheckBox(); this.chbFrenagemAutomatica = new System.Windows.Forms.CheckBox();
this.chbMovimentacaoAutomatica = new System.Windows.Forms.CheckBox();
this.gpbModulos.SuspendLayout(); this.gpbModulos.SuspendLayout();
this.pnlModulos.SuspendLayout(); this.pnlModulos.SuspendLayout();
this.tabControl1.SuspendLayout(); this.tabControl1.SuspendLayout();
@ -492,6 +493,7 @@
this.chbSonarAtivado.TabIndex = 13; this.chbSonarAtivado.TabIndex = 13;
this.chbSonarAtivado.Text = "Utilizar dados visuais do Sonar"; this.chbSonarAtivado.Text = "Utilizar dados visuais do Sonar";
this.chbSonarAtivado.UseVisualStyleBackColor = true; this.chbSonarAtivado.UseVisualStyleBackColor = true;
this.chbSonarAtivado.CheckedChanged += new System.EventHandler(this.chbSonarAtivado_CheckedChanged);
// //
// rtbDescricao // rtbDescricao
// //
@ -535,6 +537,7 @@
// //
// gpbLocomocao // gpbLocomocao
// //
this.gpbLocomocao.Controls.Add(this.chbFrenagemAutomatica);
this.gpbLocomocao.Controls.Add(this.chbMovimentacaoAutomatica); this.gpbLocomocao.Controls.Add(this.chbMovimentacaoAutomatica);
this.gpbLocomocao.Controls.Add(this.nudVelMin); this.gpbLocomocao.Controls.Add(this.nudVelMin);
this.gpbLocomocao.Controls.Add(this.nudVelMax); this.gpbLocomocao.Controls.Add(this.nudVelMax);
@ -551,6 +554,16 @@
this.gpbLocomocao.TabStop = false; this.gpbLocomocao.TabStop = false;
this.gpbLocomocao.Text = "Locomoção"; this.gpbLocomocao.Text = "Locomoção";
// //
// chbMovimentacaoAutomatica
//
this.chbMovimentacaoAutomatica.AutoSize = true;
this.chbMovimentacaoAutomatica.Location = new System.Drawing.Point(9, 85);
this.chbMovimentacaoAutomatica.Name = "chbMovimentacaoAutomatica";
this.chbMovimentacaoAutomatica.Size = new System.Drawing.Size(191, 17);
this.chbMovimentacaoAutomatica.TabIndex = 8;
this.chbMovimentacaoAutomatica.Text = "Controle de Movimento Automático";
this.chbMovimentacaoAutomatica.UseVisualStyleBackColor = true;
//
// nudVelMin // nudVelMin
// //
this.nudVelMin.Location = new System.Drawing.Point(358, 55); this.nudVelMin.Location = new System.Drawing.Point(358, 55);
@ -650,6 +663,16 @@
this.gpbAtuador.TabStop = false; this.gpbAtuador.TabStop = false;
this.gpbAtuador.Text = "Atuador"; this.gpbAtuador.Text = "Atuador";
// //
// chbPulverizadorAutomatico
//
this.chbPulverizadorAutomatico.AutoSize = true;
this.chbPulverizadorAutomatico.Location = new System.Drawing.Point(9, 192);
this.chbPulverizadorAutomatico.Name = "chbPulverizadorAutomatico";
this.chbPulverizadorAutomatico.Size = new System.Drawing.Size(209, 17);
this.chbPulverizadorAutomatico.TabIndex = 15;
this.chbPulverizadorAutomatico.Text = "Pulverizador Com Ativação Automática";
this.chbPulverizadorAutomatico.UseVisualStyleBackColor = true;
//
// txtQtdCameras // txtQtdCameras
// //
this.txtQtdCameras.Location = new System.Drawing.Point(358, 163); this.txtQtdCameras.Location = new System.Drawing.Point(358, 163);
@ -1183,25 +1206,15 @@
this.chbCameraSolo.UseVisualStyleBackColor = false; this.chbCameraSolo.UseVisualStyleBackColor = false;
this.chbCameraSolo.CheckedChanged += new System.EventHandler(this.chbParametro_CheckedChanged); this.chbCameraSolo.CheckedChanged += new System.EventHandler(this.chbParametro_CheckedChanged);
// //
// chbPulverizadorAutomatico // chbFrenagemAutomatica
// //
this.chbPulverizadorAutomatico.AutoSize = true; this.chbFrenagemAutomatica.AutoSize = true;
this.chbPulverizadorAutomatico.Location = new System.Drawing.Point(9, 192); this.chbFrenagemAutomatica.Location = new System.Drawing.Point(235, 85);
this.chbPulverizadorAutomatico.Name = "chbPulverizadorAutomatico"; this.chbFrenagemAutomatica.Name = "chbFrenagemAutomatica";
this.chbPulverizadorAutomatico.Size = new System.Drawing.Size(209, 17); this.chbFrenagemAutomatica.Size = new System.Drawing.Size(281, 17);
this.chbPulverizadorAutomatico.TabIndex = 15; this.chbFrenagemAutomatica.TabIndex = 9;
this.chbPulverizadorAutomatico.Text = "Pulverizador Com Ativação Automática"; this.chbFrenagemAutomatica.Text = "Frenagem automática ao detectar obstáculos no radar";
this.chbPulverizadorAutomatico.UseVisualStyleBackColor = true; this.chbFrenagemAutomatica.UseVisualStyleBackColor = true;
//
// chbMovimentacaoAutomatica
//
this.chbMovimentacaoAutomatica.AutoSize = true;
this.chbMovimentacaoAutomatica.Location = new System.Drawing.Point(9, 85);
this.chbMovimentacaoAutomatica.Name = "chbMovimentacaoAutomatica";
this.chbMovimentacaoAutomatica.Size = new System.Drawing.Size(191, 17);
this.chbMovimentacaoAutomatica.TabIndex = 8;
this.chbMovimentacaoAutomatica.Text = "Controle de Movimento Automático";
this.chbMovimentacaoAutomatica.UseVisualStyleBackColor = true;
// //
// frmAjustesOperacao // frmAjustesOperacao
// //
@ -1346,5 +1359,6 @@
private System.Windows.Forms.CheckBox chbLoRa_M; private System.Windows.Forms.CheckBox chbLoRa_M;
private System.Windows.Forms.CheckBox chbMovimentacaoAutomatica; private System.Windows.Forms.CheckBox chbMovimentacaoAutomatica;
private System.Windows.Forms.CheckBox chbPulverizadorAutomatico; private System.Windows.Forms.CheckBox chbPulverizadorAutomatico;
private System.Windows.Forms.CheckBox chbFrenagemAutomatica;
} }
} }

View File

@ -17,6 +17,7 @@ namespace AgroMonitor.Forms
string path = Variaveis.CaminhoSistema + Variaveis.CaminhoOperacoes + "\\" + MapasVariaveisModel.NomeArquivoMapaInterativoSaida; string path = Variaveis.CaminhoSistema + Variaveis.CaminhoOperacoes + "\\" + MapasVariaveisModel.NomeArquivoMapaInterativoSaida;
UltrasonicA05Configuracoes ConfigUltrassom = UltrasonicA05Helper.CarregarConfiguracaoPadrao(ConfiguracaoSensorUltrassonico.NaoUtilizado); UltrasonicA05Configuracoes ConfigUltrassom = UltrasonicA05Helper.CarregarConfiguracaoPadrao(ConfiguracaoSensorUltrassonico.NaoUtilizado);
bool carregarOpPadrao = true; bool carregarOpPadrao = true;
bool carregandoOperacao = false;
MapaDinamicoModel MapaDinamico; MapaDinamicoModel MapaDinamico;
public frmAjustesOperacao() public frmAjustesOperacao()
@ -55,6 +56,8 @@ namespace AgroMonitor.Forms
private void AtualizarDadosOperacao() private void AtualizarDadosOperacao()
{ {
carregandoOperacao = true;
if (carregarOpPadrao) if (carregarOpPadrao)
{ {
OperacaoModel.CarregarParametrosOperacaoPadrao((ModoOperacao)cmbModosOperacao.SelectedIndex); OperacaoModel.CarregarParametrosOperacaoPadrao((ModoOperacao)cmbModosOperacao.SelectedIndex);
@ -68,7 +71,12 @@ namespace AgroMonitor.Forms
T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), disp); T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), disp);
var P = Variaveis.OperacaoEmAndamento.ModulosMandatorios.FirstOrDefault(x => x.Dispositivo == Dispositivo); var P = Variaveis.OperacaoEmAndamento.ModulosMandatorios.FirstOrDefault(x => x.Dispositivo == Dispositivo);
chb.Checked = P?.Utilizar ?? false; chb.Checked = P?.Utilizar ?? false;
FuncoesGlobais.FindControlRecursive<CheckBox>(pnlModulos, chb.Name + "_M").Checked = P?.Mandatorio ?? false; var chbMandatorio = FuncoesGlobais.FindControlRecursive<CheckBox>(pnlModulos, chb.Name + "_M");
if (chb.Checked)
{
chbMandatorio.Enabled = chb.Checked;
chbMandatorio.Checked = P?.Mandatorio ?? false;
}
} }
foreach (var chb in pnlParametrosMandatorios.Controls.OfType<CheckBox>().Where(x => !x.Name.Contains("_M"))) foreach (var chb in pnlParametrosMandatorios.Controls.OfType<CheckBox>().Where(x => !x.Name.Contains("_M")))
@ -77,7 +85,12 @@ namespace AgroMonitor.Forms
ParametrosOperacao Parametro = (ParametrosOperacao)Enum.Parse(typeof(ParametrosOperacao), parametro); ParametrosOperacao Parametro = (ParametrosOperacao)Enum.Parse(typeof(ParametrosOperacao), parametro);
var P = Variaveis.OperacaoEmAndamento.ParametrosMandatorios.FirstOrDefault(x => x.Parametro == Parametro); var P = Variaveis.OperacaoEmAndamento.ParametrosMandatorios.FirstOrDefault(x => x.Parametro == Parametro);
chb.Checked = P?.Utilizar ?? false; chb.Checked = P?.Utilizar ?? false;
FuncoesGlobais.FindControlRecursive<CheckBox>(pnlParametrosMandatorios, chb.Name + "_M").Checked = P?.Mandatorio ?? false; var chbMandatorio = FuncoesGlobais.FindControlRecursive<CheckBox>(pnlParametrosMandatorios, chb.Name + "_M");
if (chb.Checked)
{
chbMandatorio.Enabled = chb.Checked;
chbMandatorio.Checked = P?.Mandatorio ?? false;
}
} }
var _Controle = Variaveis.OperacaoEmAndamento.Controle; var _Controle = Variaveis.OperacaoEmAndamento.Controle;
@ -106,6 +119,9 @@ namespace AgroMonitor.Forms
cmbConfiguracaoUltrassom.SelectedIndex = (int)ConfigUltrassom.Configuracao; cmbConfiguracaoUltrassom.SelectedIndex = (int)ConfigUltrassom.Configuracao;
} }
chbSonarAtivado.Checked = _Controle.SonarAtivado; chbSonarAtivado.Checked = _Controle.SonarAtivado;
chbFrenagemAutomatica.Checked = _Controle.FrenagemAutomatica;
carregandoOperacao = false;
} }
private void btnProximo_Click(object sender, EventArgs e) private void btnProximo_Click(object sender, EventArgs e)
@ -199,7 +215,8 @@ namespace AgroMonitor.Forms
qtdCameras, qtdCameras,
(TiposControladorDirecional)cmbTipoMovimentoDirecional.SelectedIndex, (TiposControladorDirecional)cmbTipoMovimentoDirecional.SelectedIndex,
chbMovimentacaoAutomatica.Checked, chbMovimentacaoAutomatica.Checked,
chbPulverizadorAutomatico.Checked chbPulverizadorAutomatico.Checked,
chbFrenagemAutomatica.Checked
); );
if (!sucesso) if (!sucesso)
{ {
@ -236,6 +253,7 @@ namespace AgroMonitor.Forms
chbMovimentacaoAutomatica.Checked = Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico; chbMovimentacaoAutomatica.Checked = Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico;
chbPulverizadorAutomatico.Checked = Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico; chbPulverizadorAutomatico.Checked = Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico;
chbFrenagemAutomatica.Checked = Variaveis.OperacaoEmAndamento.Controle.FrenagemAutomatica;
MessageBox.Show("Operação carregada com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information); MessageBox.Show("Operação carregada com sucesso!", "Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information);
@ -258,6 +276,8 @@ namespace AgroMonitor.Forms
private void chbModulo_CheckedChanged(object sender, EventArgs e) private void chbModulo_CheckedChanged(object sender, EventArgs e)
{ {
if (carregandoOperacao) return;
CheckBox chb = (CheckBox)sender; CheckBox chb = (CheckBox)sender;
string ModID = chb.Name.Replace("chb", ""); string ModID = chb.Name.Replace("chb", "");
T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), ModID); T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), ModID);
@ -288,6 +308,8 @@ namespace AgroMonitor.Forms
private void chbModuloMandatorio_CheckedChanged(object sender, EventArgs e) private void chbModuloMandatorio_CheckedChanged(object sender, EventArgs e)
{ {
if (carregandoOperacao) return;
CheckBox chb = (CheckBox)sender; CheckBox chb = (CheckBox)sender;
string ModID = chb.Name.Replace("chb", "").Replace("_M", ""); string ModID = chb.Name.Replace("chb", "").Replace("_M", "");
T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), ModID); T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), ModID);
@ -313,6 +335,8 @@ namespace AgroMonitor.Forms
private void chbParametro_CheckedChanged(object sender, EventArgs e) private void chbParametro_CheckedChanged(object sender, EventArgs e)
{ {
if (carregandoOperacao) return;
CheckBox chb = (CheckBox)sender; CheckBox chb = (CheckBox)sender;
string parametro = chb.Name.Replace("chb", ""); string parametro = chb.Name.Replace("chb", "");
ParametrosOperacao Parametro = (ParametrosOperacao)Enum.Parse(typeof(ParametrosOperacao), parametro); ParametrosOperacao Parametro = (ParametrosOperacao)Enum.Parse(typeof(ParametrosOperacao), parametro);
@ -346,6 +370,8 @@ namespace AgroMonitor.Forms
private void chbParametroMandatorio_CheckedChanged(object sender, EventArgs e) private void chbParametroMandatorio_CheckedChanged(object sender, EventArgs e)
{ {
if (carregandoOperacao) return;
CheckBox chb = (CheckBox)sender; CheckBox chb = (CheckBox)sender;
string parametro = chb.Name.Replace("chb", "").Replace("_M", ""); string parametro = chb.Name.Replace("chb", "").Replace("_M", "");
ParametrosOperacao Parametro = (ParametrosOperacao)Enum.Parse(typeof(ParametrosOperacao), parametro); ParametrosOperacao Parametro = (ParametrosOperacao)Enum.Parse(typeof(ParametrosOperacao), parametro);
@ -405,6 +431,13 @@ namespace AgroMonitor.Forms
pnlZoomMapa.Visible = chbMapaDinamico.Checked; pnlZoomMapa.Visible = chbMapaDinamico.Checked;
} }
private void chbSonarAtivado_CheckedChanged(object sender, EventArgs e)
{
chbFrenagemAutomatica.Enabled = chbSonarAtivado.Checked;
if (!chbFrenagemAutomatica.Enabled)
{
chbFrenagemAutomatica.Checked = false;
}
}
} }
} }

View File

@ -1,21 +1,4 @@
0:02:15 Microsoft.Shutdown.TabStripModel.RunUnloadListenerBeforeClosing_false 0:09:19 Microsoft.Shutdown.TabStripModel.SendDetachWebContentsNotifications
0:02:15 Microsoft.Shutdown.TabStripModel.InternalCloseTabsImpl_ClosedAll
0:02:15 Microsoft.Shutdown.TabStripModel.SendDetachWebContentsNotifications
0:02:15 Microsoft.UnloadController.ClearUnloadState
0:02:15 Browser1 Close Tab1 at 0
0:02:15 Tab1 WebContentsDestroyed
0:02:15 Microsoft.UnloadController.TabStripEmpty
0:02:15 Microsoft.UnloadController.IsUnclosableApp_IsNotWebApp
0:02:15 Microsoft.UnloadController.HasCompletedUnloadProcessing_True
0:02:15 Microsoft.Shutdown.OnWindowClosing
0:02:15 Microsoft.UnloadController.IsUnclosableApp_IsNotWebApp
0:02:15 Microsoft.UnloadController.HasCompletedUnloadProcessing_True
0:02:15 Microsoft.Shutdown.OnWindowClosingPostClearBrowsingData_NoBrowsingDataCleared
0:02:15 Widget Closed: BrowserFrame
0:02:15 Microsoft.UnloadController.HasCompletedUnloadProcessing_True
0:02:15 Microsoft.Shutdown.OnWindowClosing
0:02:15 Microsoft.Shutdown.OnWindowClosing_DeleteScheduled
0:02:15 Microsoft.Last_Browser_Removed
0:00:00 Startup 0:00:00 Startup
0:00:00 Microsoft.DeleteProfileHelper.CleanUpEphemeralProfiles 0:00:00 Microsoft.DeleteProfileHelper.CleanUpEphemeralProfiles
0:00:00 Microsoft.DeleteProfileHelper.CleanUpDeletedProfiles 0:00:00 Microsoft.DeleteProfileHelper.CleanUpDeletedProfiles
@ -23,62 +6,40 @@
0:00:00 Microsoft.BrowserList.AddBrowser 0:00:00 Microsoft.BrowserList.AddBrowser
0:00:00 Browser1 Insert active Tab1 at 0 0:00:00 Browser1 Insert active Tab1 at 0
0:00:00 Tab1 StartNav1 #auto_toplevel 0:00:00 Tab1 StartNav1 #auto_toplevel
0:00:00 Tab1 StartNav2 #typed
0:00:00 Tab1 FinishNav1 0:00:00 Tab1 FinishNav1
0:00:00 Tab1 PageLoad 0:00:00 Tab1 PageLoad
0:00:00 Tab1 FinishNav2 0:00:01 Memory Pressure: Critical
0:00:00 Tab1 PageLoad 0:00:11 Tab1 StartNav2 #typed
0:00:25 Memory Pressure: Critical 0:00:11 Tab1 FinishNav2
0:01:35 Microsoft.NewBrowser_Popup 0:00:12 Tab1 PageLoad
0:01:35 Microsoft.BrowserList.AddBrowser 0:00:35 Microsoft.NewBrowser_Popup
0:01:35 Browser2 Insert active Tab2 at 0 0:00:35 Microsoft.BrowserList.AddBrowser
0:01:35 Tab2 StartNav3 #auto_toplevel 0:00:35 Browser2 Insert active Tab2 at 0
0:01:35 Tab2 StartNav4 #typed 0:00:35 Tab2 StartNav3 #auto_toplevel
0:01:36 Tab2 FinishNav3 0:00:35 Tab2 StartNav4 #typed
0:01:36 Tab2 PageLoad 0:00:35 Tab2 FinishNav3
0:01:36 Tab2 FinishNav4 0:00:35 Tab2 PageLoad
0:01:36 Tab2 PageLoad 0:00:35 Tab2 FinishNav4
0:01:57 Memory Pressure: Critical 0:00:35 Tab2 PageLoad
0:03:34 Microsoft.NewBrowser_Popup 0:00:41 Memory Pressure: Critical
0:03:34 Microsoft.BrowserList.AddBrowser 0:01:48 Microsoft.NewBrowser_Popup
0:03:34 Browser3 Insert active Tab3 at 0 0:01:48 Microsoft.BrowserList.AddBrowser
0:03:34 Tab3 StartNav5 #auto_toplevel 0:01:48 Browser3 Insert active Tab3 at 0
0:03:34 Tab3 StartNav6 #typed 0:01:48 Tab3 StartNav5 #auto_toplevel
0:03:34 Tab3 FinishNav5 0:01:48 Tab3 FinishNav5
0:03:34 Tab3 PageLoad 0:01:48 Tab3 PageLoad
0:03:34 Tab3 FinishNav6 0:01:50 Tab3 StartNav6 #typed
0:03:35 Tab3 PageLoad 0:01:50 Tab3 FinishNav6
0:04:19 Memory Pressure: Critical 0:01:50 Tab3 PageLoad
0:05:10 Microsoft.NewBrowser_Popup 0:02:04 Memory Pressure: Critical
0:05:10 Microsoft.BrowserList.AddBrowser 0:02:56 Microsoft.NewBrowser_Popup
0:05:10 Browser4 Insert active Tab4 at 0 0:02:56 Microsoft.BrowserList.AddBrowser
0:05:10 Tab4 StartNav7 #auto_toplevel 0:02:56 Browser4 Insert active Tab4 at 0
0:05:10 Tab4 StartNav8 #typed 0:02:56 Tab4 StartNav7 #auto_toplevel
0:05:10 Tab4 FinishNav7 0:02:56 Tab4 StartNav8 #typed
0:05:10 Tab4 PageLoad 0:02:56 Tab4 FinishNav7
0:05:10 Tab4 FinishNav8 0:02:56 Tab4 PageLoad
0:05:10 Tab4 PageLoad 0:02:56 Tab4 FinishNav8
0:05:47 Memory Pressure: Critical 0:02:56 Tab4 PageLoad
0:00:00 Startup 0:05:15 Memory Pressure: Critical
0:00:00 Microsoft.DeleteProfileHelper.CleanUpEphemeralProfiles 0:05:16 Microsoft.UnloadController.IsUnclosableApp_IsNotWebApp
0:00:00 Microsoft.DeleteProfileHelper.CleanUpDeletedProfiles
0:00:00 Microsoft.NewBrowser_Popup
0:00:00 Microsoft.BrowserList.AddBrowser
0:00:00 Browser1 Insert active Tab1 at 0
0:00:00 Tab1 StartNav1 #auto_toplevel
0:00:00 Tab1 StartNav2 #typed
0:00:00 Tab1 FinishNav1
0:00:00 Tab1 PageLoad
0:00:00 Tab1 FinishNav2
0:00:00 Tab1 PageLoad
0:00:25 Memory Pressure: Critical
0:02:59 Microsoft.NewBrowser_Popup
0:02:59 Microsoft.BrowserList.AddBrowser
0:02:59 Browser2 Insert active Tab2 at 0
0:02:59 Tab2 StartNav3 #auto_toplevel
0:02:59 Tab2 StartNav4 #typed
0:02:59 Tab2 FinishNav3
0:02:59 Tab2 PageLoad
0:02:59 Tab2 FinishNav4
0:02:59 Tab2 PageLoad
0:05:10 Memory Pressure: Critical

View File

@ -1,5 +1,5 @@
{ {
"description": "Microsoft CRLSet", "description": "Microsoft CRLSet",
"name": "MicrosoftCRLSet", "name": "MicrosoftCRLSet",
"version": "6498.2024.12.2" "version": "6498.2025.9.4"
} }

View File

@ -1,13 +1,13 @@
{ {
"epochs": [ { "epochs": [ {
"calculation_time": "13399989621907661", "calculation_time": "13400859163413956",
"config_version": 0, "config_version": 0,
"model_version": "0", "model_version": "0",
"padded_top_topics_start_index": 0, "padded_top_topics_start_index": 0,
"taxonomy_version": 0, "taxonomy_version": 0,
"top_topics_and_observing_domains": [ ] "top_topics_and_observing_domains": [ ]
}, { }, {
"calculation_time": "13400859163413956", "calculation_time": "13402493510652849",
"config_version": 0, "config_version": 0,
"model_version": "0", "model_version": "0",
"padded_top_topics_start_index": 0, "padded_top_topics_start_index": 0,
@ -15,5 +15,5 @@
"top_topics_and_observing_domains": [ ] "top_topics_and_observing_domains": [ ]
} ], } ],
"hex_encoded_hmac_key": "171DAE543B88106F5155169E0A8C7502CB2A0757E4948C32E2A04D196E23BE70", "hex_encoded_hmac_key": "171DAE543B88106F5155169E0A8C7502CB2A0757E4948C32E2A04D196E23BE70",
"next_scheduled_calculation_time": "13401463963414108" "next_scheduled_calculation_time": "13403098310652891"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Some files were not shown because too many files have changed in this diff Show More