From 09af9634988e193ea2ce9b3104ca52f3e69e3216 Mon Sep 17 00:00:00 2001 From: Diego Freitas Date: Tue, 24 Mar 2026 12:36:48 -0300 Subject: [PATCH 1/2] ajustes finais no controle e adicao dos itens no controle da operacao --- .../Models/Operacoes/OperacaoModel.cs | 8 ++-- AgroBase/AgroBase/Services/GPSService.cs | 2 +- .../Services/ManualControlSender.cs | 4 +- .../Diagnostico/DiagnosticoViewModel.cs | 37 +++++++++++++------ .../Monitoramento/MonitoramentoViewModel.cs | 4 +- .../Views/Operacao/OperacaoLeftViewModel.cs | 4 +- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs index 4f62e18ad..b143e58ec 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs @@ -1702,8 +1702,8 @@ namespace AgroBase.Models var cmdRover = GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.botaoJoy == controleBase.Tecla); - if (cmdRover?.Dispositivo == T_Code.Mov && Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico && Variaveis.OperacaoEmAndamento.Iniciado) return; - if (cmdRover?.Dispositivo == T_Code.Dir && Variaveis.OperacaoEmAndamento.Parametros.Controle.DirecionalAutomatico && Variaveis.OperacaoEmAndamento.Iniciado) return; + if (cmdRover?.Dispositivo == T_Code.Mov && (Variaveis.OperacaoEmAndamento.Parametros?.Controle?.MovimentoAutomatico ?? false) && Variaveis.OperacaoEmAndamento.Iniciado) return; + if (cmdRover?.Dispositivo == T_Code.Dir && (Variaveis.OperacaoEmAndamento.Parametros?.Controle?.DirecionalAutomatico ?? false) && Variaveis.OperacaoEmAndamento.Iniciado) return; var _Controle = Variaveis.OperacaoEmAndamento.Controle; if (controleBase.Controle.PercentualVelocidadeSP != null) _Controle.PercentualVelocidadeSP = (double)controleBase.Controle.PercentualVelocidadeSP; @@ -1716,10 +1716,10 @@ namespace AgroBase.Models switch (cmdRover?.Dispositivo) { case T_Code.Mov: - GeneralJoystick.ProcessarDadosControle(cmdRover.botaoJoy, controleBase.Solto, valorDesejado: _Controle.PercentualVelocidadeSP); + GeneralJoystick.ProcessarDadosControle(cmdRover.botaoJoy, controleBase.Solto, valorDesejado: _Controle.PercentualVelocidadeSP, ForcarComando: true); break; case T_Code.Dir: - GeneralJoystick.ProcessarDadosControle(cmdRover.botaoJoy, controleBase.Solto, valorDesejado: _Controle.Angulo); + GeneralJoystick.ProcessarDadosControle(cmdRover.botaoJoy, controleBase.Solto, valorDesejado: _Controle.Angulo, ForcarComando: true); break; } } diff --git a/AgroBase/AgroBase/Services/GPSService.cs b/AgroBase/AgroBase/Services/GPSService.cs index ae9976b14..f37763126 100644 --- a/AgroBase/AgroBase/Services/GPSService.cs +++ b/AgroBase/AgroBase/Services/GPSService.cs @@ -1214,7 +1214,7 @@ namespace AgroBase.Services double headingDeg, // OrientacaoReal (antena/corpo) double angMovDeg, // OrientacaoMovimento (calculada acima) double distLinearJanela, // UltimaLeitura.Distancia (Δpos linear entre 1ª e última amostra) - double velPercent = 0.0, // se tiver velocidade filtrada, passe aqui; senão 0 + double velPercent = 0.0, // se tiver velocidade filtrada, passe aqui; senão 0 bool rtkFix = true, // se tiver essa info double angFundidoAnterior = double.NaN, // para low-pass; passe double.NaN para desabilitar double alfaLowPass = 0.25 // 0→sem low-pass; 0.2–0.35 costuma ser bom diff --git a/AgroBase/OperationControl/Services/ManualControlSender.cs b/AgroBase/OperationControl/Services/ManualControlSender.cs index f3f9ffbd4..4494b59cb 100644 --- a/AgroBase/OperationControl/Services/ManualControlSender.cs +++ b/AgroBase/OperationControl/Services/ManualControlSender.cs @@ -147,7 +147,7 @@ public sealed class ManualControlSender : IDisposable } private static bool IsNeutral(UdpCtrlMessage msg) - => msg.Key == AgroBase.Models.Enums.BotoesJoystick.Vazio; + => msg.Key == AgroBase.Models.Enums.BotoesJoystick.Vazio || msg.released; private UdpCtrlMessage BuildStopMsg() { @@ -156,6 +156,7 @@ public sealed class ManualControlSender : IDisposable Device = _device, Flags = UdpCtrlFlags.HasKey | UdpCtrlFlags.HasPayload, Key = AgroBase.Models.Enums.BotoesJoystick.Vazio, + released = false, P1 = 0, P2 = 0 }; @@ -169,4 +170,5 @@ public sealed class ManualControlSender : IDisposable _cts = null; _loop = null; } + } \ No newline at end of file diff --git a/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/Diagnostico/DiagnosticoViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/Diagnostico/DiagnosticoViewModel.cs index e784a1fe1..0c038ddbb 100644 --- a/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/Diagnostico/DiagnosticoViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/Diagnostico/DiagnosticoViewModel.cs @@ -140,30 +140,35 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico // ATUADOR / SISTEMA DE PULVERIZAÇÃO // ============================= + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_BMBAGT", Modulo = T_Code.Atu, LabelModulo = "BMBAGT", SCode = S_Code.sBMB, TextoBase = "AGIT", Left = 315, Top = 570 }); DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_PRSLN", Modulo = T_Code.Atu, LabelModulo = "PRSLN", SCode = S_Code.sPRS, TextoBase = "PRS", Left = 230, Top = 610 }); DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU", Modulo = T_Code.Atu, LabelModulo = "", SCode = S_Code.sMOD, TextoBase = "ATU", Left = 315, Top = 610 }); DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_FLXLN", Modulo = T_Code.Atu, LabelModulo = "FLXLN", SCode = S_Code.sFLX, TextoBase = "FLX", Left = 400, Top = 610 }); - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_BOMBA", Modulo = T_Code.Atu, LabelModulo = "BOMBA", SCode = S_Code.sBMB, TextoBase = "BMB", Left = 230, Top = 650 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_BMBLN", Modulo = T_Code.Atu, LabelModulo = "BOMBA", SCode = S_Code.sBMB, TextoBase = "BMB", Left = 230, Top = 650 }); DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MASRS", Modulo = T_Code.Atu, LabelModulo = "MASRS", SCode = S_Code.sMAS, TextoBase = "MAS", Left = 400, Top = 650 }); DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "CAM", Modulo = T_Code.Cam, LabelModulo = "", SCode = S_Code.sVZO, TextoBase = "CAM", Left = 315, Top = 650 }); + // ============================= + // SENSORES BARRA PULVERIZADORA + // ============================= + + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MAGESQ", Modulo = T_Code.Atu, LabelModulo = "MAGESQ", SCode = S_Code.sMAG, TextoBase = "MAG", Left = 165, Top = 705 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MAGALT", Modulo = T_Code.Atu, LabelModulo = "MAGALT", SCode = S_Code.sMAG, TextoBase = "MAG", Left = 315, Top = 705 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MAGDIR", Modulo = T_Code.Atu, LabelModulo = "MAGDIR", SCode = S_Code.sMAG, TextoBase = "MAG", Left = 465, Top = 705 }); + // ============================= // BICOS // ============================= - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_SRVB1", Modulo = T_Code.Atu, LabelModulo = "SRVB1", SCode = S_Code.sSRV, TextoBase = "SVB1", Left = 110, Top = 705 }); - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B01", Modulo = T_Code.Atu, LabelModulo = "B01", SCode = S_Code.sBIC, TextoBase = "B01", Left = 110, Top = 745 }); - - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MAGESQ", Modulo = T_Code.Atu, LabelModulo = "MAGESQ", SCode = S_Code.sMAG, TextoBase = "MAG", Left = 215, Top = 730 }); - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MAGALT", Modulo = T_Code.Atu, LabelModulo = "MAGALT", SCode = S_Code.sMAG, TextoBase = "MAG", Left = 315, Top = 705 }); - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_MAGDIR", Modulo = T_Code.Atu, LabelModulo = "MAGDIR", SCode = S_Code.sMAG, TextoBase = "MAG", Left = 415, Top = 730 }); - - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B02", Modulo = T_Code.Atu, LabelModulo = "B02", SCode = S_Code.sBIC, TextoBase = "B02", Left = 315, Top = 745 }); - - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_SRVB3", Modulo = T_Code.Atu, LabelModulo = "SRVB3", SCode = S_Code.sSRV, TextoBase = "SVB3", Left = 520, Top = 705 }); - DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B03", Modulo = T_Code.Atu, LabelModulo = "B03", SCode = S_Code.sBIC, TextoBase = "B03", Left = 520, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B01", Modulo = T_Code.Atu, LabelModulo = "B01", SCode = S_Code.sBIC, TextoBase = "B01", Left = 90, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B02", Modulo = T_Code.Atu, LabelModulo = "B02", SCode = S_Code.sBIC, TextoBase = "B02", Left = 165, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B03", Modulo = T_Code.Atu, LabelModulo = "B03", SCode = S_Code.sBIC, TextoBase = "B03", Left = 240, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B04", Modulo = T_Code.Atu, LabelModulo = "B04", SCode = S_Code.sBIC, TextoBase = "B04", Left = 315, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B05", Modulo = T_Code.Atu, LabelModulo = "B05", SCode = S_Code.sBIC, TextoBase = "B05", Left = 390, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B06", Modulo = T_Code.Atu, LabelModulo = "B06", SCode = S_Code.sBIC, TextoBase = "B06", Left = 465, Top = 745 }); + DiagnosticoModulos.Add(new DiagnosticoModuloItemViewModel { IdVisual = "ATU_B07", Modulo = T_Code.Atu, LabelModulo = "B07", SCode = S_Code.sBIC, TextoBase = "B07", Left = 540, Top = 745 }); } @@ -586,6 +591,14 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico { mod.Mandatorio = MandatorioSelecionado; mod.Utilizar = EmUsoSelecionado; + if (mod.ComponentesEmUso != null) + { + var chaves = mod.ComponentesEmUso.Keys.ToList(); + foreach (var key in chaves) + { + mod.ComponentesEmUso[key] = (MandatorioSelecionado, EmUsoSelecionado); + } + } } else { diff --git a/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs index 1f6a12922..05a0db0b4 100644 --- a/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs @@ -160,9 +160,9 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento Task.Run(async () => { await VariaveisControleOperacao.EnviarComandoParadaUDP(pausa: true); - await Task.Delay(500); + await Task.Delay(2000); VariaveisControleOperacao.EnviarComandoRetornoBase(lat, lon); - await Task.Delay(1000); + await Task.Delay(2000); await VariaveisControleOperacao.EnviarComandoParadaUDP(pausa: false); }); diff --git a/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs index ffb6272a6..ad97b1c8f 100644 --- a/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs @@ -342,9 +342,9 @@ namespace OperationControl.ViewModels.Views.Operacao if ((dadosRover?.Operacao?.Status ?? StatusOperacao.NaoIniciado) == StatusOperacao.Concluido) { VariaveisControleOperacao.EnviarComandoIniciarOperacao(false, false); - await Task.Delay(500); + await Task.Delay(2000); } - bool simulador = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Gnss?.Iniciado != true; + bool simulador = AppShell.Mock || AppShell.AddRover; // || VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Gnss?.Iniciado != true; VariaveisControleOperacao.EnviarComandoIniciarOperacao(true, simulador); await Task.Delay(1000); if (!(dadosRover?.Operacao?.Liberada ?? false)) From ae5f8b215bbc941b7dbb79c674a255a5cc76345a Mon Sep 17 00:00:00 2001 From: Diego Freitas Date: Tue, 24 Mar 2026 17:01:33 -0300 Subject: [PATCH 2/2] iniciado aplicacao de offset na base --- .../Models/Operacoes/OperacaoModel.cs | 6 +- AgroBase/AgroBase/Models/Variaveis.cs | 4 +- AgroBase/AgroBase/Services/GPSService.cs | 139 +++++----- .../OperationControl/Services/GpsService.cs | 4 +- .../ConfigConexao/ConfigConexaoViewModel.cs | 6 +- .../Views/Operacao/OperacaoLeftViewModel.cs | 21 +- .../PreparacaoMapaBottomViewModel.cs | 254 +++++++++++------- .../ViewModels/Windows/DockWindowViewModel.cs | 2 +- .../Views/Operacao/OperacaoLeftView.xaml | 82 ++---- .../PreparacaoMapaBottomView.xaml | 148 ++++++---- 10 files changed, 374 insertions(+), 292 deletions(-) diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs index b143e58ec..94d706ef6 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs @@ -1582,12 +1582,8 @@ namespace AgroBase.Models if (controleBase.Dispositivo == T_Code.Gps) { var (la_frontal, la_lateral) = ((JObject)controleBase._comp_value).ToObject<(double?, double?)>(); - if (la_frontal != null) VariaveisEquipamento.LeverArmFrontal = (double)la_frontal; - if (la_lateral != null) VariaveisEquipamento.LeverArmLateral = (double)la_lateral; - GPSService.UltimaLeitura.LeverArmFrontal = VariaveisEquipamento.LeverArmFrontal; - GPSService.UltimaLeitura.LeverArmLateral = VariaveisEquipamento.LeverArmLateral; if (la_lateral != null || la_frontal != null) - GPSService.LeverArm = new GeoLeverArm(VariaveisEquipamento.LeverArmFrontal, VariaveisEquipamento.LeverArmLateral); + GPSService.LeverArm = new GeoLeverArm(la_frontal ?? 0, la_lateral ?? 0); return; } diff --git a/AgroBase/AgroBase/Models/Variaveis.cs b/AgroBase/AgroBase/Models/Variaveis.cs index 826538ec1..c0e95167e 100644 --- a/AgroBase/AgroBase/Models/Variaveis.cs +++ b/AgroBase/AgroBase/Models/Variaveis.cs @@ -449,8 +449,8 @@ namespace AgroBase.Models public static double ComprimentoFrente { get; } = 7.0; // 7 public static double ComprimentoTras { get; } = 107.0; // 107 public static double DistanciaEntreEixos { get; } = 92.0; - public static double LeverArmFrontal { get; set; } = 100.0; // cm - public static double LeverArmLateral { get; set; } = 0.0; // cm + public static double LeverArmFrontalCm { get; } = 100.0; // cm + public static double LeverArmLateralCm { get; } = 0.0; // cm public static double LarguraEquipamentoMm { get diff --git a/AgroBase/AgroBase/Services/GPSService.cs b/AgroBase/AgroBase/Services/GPSService.cs index f37763126..6b82f49a6 100644 --- a/AgroBase/AgroBase/Services/GPSService.cs +++ b/AgroBase/AgroBase/Services/GPSService.cs @@ -49,7 +49,7 @@ namespace AgroBase.Services private static bool LoopRTK_Ntrip = false; public static bool CorrecaoRTK_Ntrip = false; public static DateTime UltimoEnvioCorrecaoRTK = DateTime.MinValue; - public static GeoLeverArm LeverArm = new GeoLeverArm(VariaveisEquipamento.LeverArmFrontal, VariaveisEquipamento.LeverArmLateral); + public static GeoLeverArm LeverArm = new GeoLeverArm(); public static void AtualizarPortaCOM(SerialPort Porta) { @@ -969,8 +969,8 @@ namespace AgroBase.Services UltimaLeitura.Ntrip_ativado = CorrecaoRTK_Ntrip; UltimaLeitura.Heartbeat = (UltimaLeitura.Heartbeat + 1) % 10; - UltimaLeitura.LeverArmFrontal = VariaveisEquipamento.LeverArmFrontal; - UltimaLeitura.LeverArmLateral = VariaveisEquipamento.LeverArmLateral; + UltimaLeitura.LeverArmFrontal = LeverArm?.FrontalTotalCm ?? 0; + UltimaLeitura.LeverArmLateral = LeverArm?.LateralTotalCm ?? 0; if (Variaveis.IsAgroMonitor) { @@ -1359,26 +1359,82 @@ namespace AgroBase.Services } } - + public class GeoLeverArm { - public GeoLeverArm(double _xbCm = 0, double _ybCm = 0, bool _invH = false, bool _mirrL = false) + // Lever arm físico fixo do equipamento + private readonly double xFisico; // +frente (m) + private readonly double yFisico; // +direita (m) + + // Offset operacional/de campo + private readonly double xCampo; // +frente (m) + private readonly double yCampo; // +direita (m) + + private readonly bool invertHeading; + private readonly bool mirrorLateral; + + public GeoLeverArm(double offsetCampoFrontalCm = 0, double offsetCampoLateralCm = 0, bool invH = false, bool mirrL = false) { - xB = _xbCm / 100.0; - yB = _ybCm / 100.0; - invertHeading = _invH; - mirrorLateral = _mirrL; + // fixos do equipamento + xFisico = VariaveisEquipamento.LeverArmFrontalCm / 100.0; + yFisico = VariaveisEquipamento.LeverArmLateralCm / 100.0; + + // ajustes de campo + xCampo = offsetCampoFrontalCm / 100.0; + yCampo = offsetCampoLateralCm / 100.0; + + invertHeading = invH; + mirrorLateral = mirrL; } - const double R = 6378137.0; // WGS84 - private readonly double xB; // +frente (m) - private readonly double yB; // +direita (m) - private readonly bool invertHeading = false; - private readonly bool mirrorLateral = false; - private double ToRad(double deg) => deg * Math.PI / 180.0; - private double ToDeg(double rad) => rad * 180.0 / Math.PI; + + public double FrontalTotalCm => (xFisico + xCampo) * 100.0; + public double LateralTotalCm => (yFisico + yCampo) * 100.0; + + /// + /// Convenção: + /// - Entrada = posição da antena GNSS + /// - Saída = posição corrigida do centro/VRP + /// - heading: 0° = Norte, 90° = Leste, sentido horário + /// - frontal positivo = antena à frente do centro + /// - lateral positivo = antena à direita do centro + /// Consequência: + /// - frontal positivo desloca a posição corrigida para trás do robô + /// - lateral positivo desloca a posição corrigida para a esquerda do robô + /// + public (double lat, double lon) FixLeverArmLatLon_Fast(double latAnt_deg, double lonAnt_deg, double headingDeg) + { + double xTotal = xFisico + xCampo; + double yTotal = yFisico + yCampo; + + if (mirrorLateral) + yTotal = -yTotal; + + double th = ToRad(headingDeg); + if (invertHeading) + th = -th; + + // Convenção NAV + double fE = Math.Sin(th); // forward east + double fN = Math.Cos(th); // forward north + + double rE = fN; // right east + double rN = -fE; // right north + + // deslocamento da antena no mundo + double dE = xTotal * fE + yTotal * rE; + double dN = xTotal * fN + yTotal * rN; + + double latRad = ToRad(latAnt_deg); + + double dLat_deg = (dN / GPSUtils.RaioDaTerra) * 180.0 / Math.PI; + double dLon_deg = (dE / (GPSUtils.RaioDaTerra * Math.Cos(latRad))) * 180.0 / Math.PI; + + // retorna o centro/VRP + return (latAnt_deg - dLat_deg, lonAnt_deg - dLon_deg); + } // lat/lon -> ENU (aproximação local, boa para ~km) public (double x, double y) GeodeticToENU(double lat, double lon, double lat0, double lon0) @@ -1386,58 +1442,11 @@ namespace AgroBase.Services double latR = ToRad(lat), lonR = ToRad(lon); double lat0R = ToRad(lat0), lon0R = ToRad(lon0); double dLat = latR - lat0R, dLon = lonR - lon0R; - double xEast = dLon * Math.Cos(lat0R) * R; - double yNorth = dLat * R; + double xEast = dLon * Math.Cos(lat0R) * GPSUtils.RaioDaTerra; + double yNorth = dLat * GPSUtils.RaioDaTerra; return (xEast, yNorth); } - public (double lat, double lon) ENUToGeodetic(double x, double y, double lat0, double lon0) - { - double lat0R = ToRad(lat0); - double dLat = y / R; - double dLon = x / (R * Math.Cos(lat0R)); - double lat = lat0 + ToDeg(dLat); - double lon = lon0 + ToDeg(dLon); - return (lat, lon); - } - - // Aplica lever arm: retorna o CENTRO dado ANTENA + heading. - // Convenção: θ=0 norte; +horário→leste (igual ao seu modelo: x+=sinθ, y+=cosθ). - public (double xCtr, double yCtr) ApplyLeverArmENU(double xAnt, double yAnt, double thetaRad, double lFwd, double lLeft) - { - double s = Math.Sin(thetaRad), c = Math.Cos(thetaRad); - // vetores no mundo - double fx = s, fy = c; // frente - double lx = -c, ly = s; // esquerda - // vetor centro->antena no mundo - double rx = lFwd * fx + lLeft * lx; - double ry = lFwd * fy + lLeft * ly; - // centro = antena - (centro->antena) - return (xAnt - rx, yAnt - ry); - } - - public (double lat, double lon) FixLeverArmLatLon_Fast(double latAnt_deg, double lonAnt_deg, double headingDeg) - { - double _yB = (mirrorLateral) ? -yB : yB; // espelha lateral (D<->E) - - double th = headingDeg * Math.PI / 180.0; - if (invertHeading) th = -th; // inverte sentido do ângulo - - // Convenção NAV: 0°=Norte, cresce horário - double fE = Math.Sin(th), fN = Math.Cos(th); // forward (E,N) - double rE = fN, rN = -fE; // right (E,N) - - double dE = xB * fE + _yB * rE; // body -> ENU - double dN = xB * fN + _yB * rN; - - double latRad = latAnt_deg * Math.PI / 180.0; - double dLat_deg = (dN / R) * 180.0 / Math.PI; - double dLon_deg = (dE / (R * Math.Cos(latRad))) * 180.0 / Math.PI; - - // antena -> VRP (subtrai o offset da antena) - return (latAnt_deg - dLat_deg, lonAnt_deg - dLon_deg); - } - } } diff --git a/AgroBase/OperationControl/Services/GpsService.cs b/AgroBase/OperationControl/Services/GpsService.cs index 57de27536..9f4fac824 100644 --- a/AgroBase/OperationControl/Services/GpsService.cs +++ b/AgroBase/OperationControl/Services/GpsService.cs @@ -246,9 +246,7 @@ namespace OperationControl.Services { Models.Variaveis.MostrarLog("Iniciando configuração do módulo GPS..."); - LeverArm = new GeoLeverArm( - VariaveisControleOperacao.LeverArmFrontal, - VariaveisControleOperacao.LeverArmLateral); + LeverArm = new GeoLeverArm(VariaveisControleOperacao.LeverArmFrontal, VariaveisControleOperacao.LeverArmLateral); BaseFix = new BaseFixService(PortaGps, this); BaseFix.FixLiberado = fixar; diff --git a/AgroBase/OperationControl/ViewModels/Views/ConfigConexao/ConfigConexaoViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/ConfigConexao/ConfigConexaoViewModel.cs index 2b0453d7b..f70ddef50 100644 --- a/AgroBase/OperationControl/ViewModels/Views/ConfigConexao/ConfigConexaoViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/ConfigConexao/ConfigConexaoViewModel.cs @@ -197,14 +197,10 @@ namespace OperationControl.ViewModels TudoOkChanged?.Invoke(TudoOk); } - // ====== STATUS INICIAL (fake por enquanto) ====== + // ====== STATUS INICIAL ====== public void CarregarStatusInicial() { - // aqui você pluga de verdade nos seus serviços: - // var statusRede = NetworkService.Get(); - // var statusGnss = GnssService.Get(); - AtualizarStatusRede(); AtualizarStatusGnss(); } diff --git a/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs index ad97b1c8f..f56225c19 100644 --- a/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoLeftViewModel.cs @@ -17,6 +17,7 @@ namespace OperationControl.ViewModels.Views.Operacao public ICommand AlternarOperacaoCommand { get; } public ICommand ParadaEmergenciaCommand { get; } public ICommand CancelarOperacaoCommand { get; } + public ICommand ReconfigurarGnssCommand { get; } private bool _operacaoPausada => (VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Pausa ?? false); private bool _operacaoEmExecucao; public bool OperacaoEmExecucao @@ -42,10 +43,10 @@ namespace OperationControl.ViewModels.Views.Operacao ? new SolidColorBrush(Color.FromRgb(120, 88, 20)) : new SolidColorBrush(Color.FromRgb(30, 90, 58)); - public System.Windows.Media.Brush BordaBotaoOperacao => + public Brush BordaBotaoOperacao => OperacaoEmExecucao && !_operacaoPausada - ? new SolidColorBrush(System.Windows.Media.Color.FromRgb(170, 130, 40)) - : new SolidColorBrush(System.Windows.Media.Color.FromRgb(74, 138, 91)); + ? new SolidColorBrush(Color.FromRgb(170, 130, 40)) + : new SolidColorBrush(Color.FromRgb(74, 138, 91)); private bool _roverSelecionado; @@ -60,10 +61,19 @@ namespace OperationControl.ViewModels.Views.Operacao OnPropertyChanged(nameof(RoverSelecionado)); OnPropertyChanged(nameof(NomeRover)); OnPropertyChanged(nameof(OpacityPainel)); + OnPropertyChanged(nameof(RoverNaoSelecionado)); + OnPropertyChanged(nameof(VisibilidadeAcoesRover)); + OnPropertyChanged(nameof(VisibilidadeConfiguracaoGnss)); } } } + public bool RoverNaoSelecionado => !RoverSelecionado; + + public Visibility VisibilidadeAcoesRover => RoverSelecionado ? Visibility.Visible : Visibility.Collapsed; + + public Visibility VisibilidadeConfiguracaoGnss => !RoverSelecionado ? Visibility.Visible : Visibility.Collapsed; + private string _nomeRover = "Nenhum rover selecionado"; public string NomeRover { @@ -252,6 +262,7 @@ namespace OperationControl.ViewModels.Views.Operacao AlternarOperacaoCommand = new RelayCommand(_ => AlternarOperacao()); ParadaEmergenciaCommand = new RelayCommand(_ => ExecutarParadaEmergencia()); CancelarOperacaoCommand = new RelayCommand(_ => CancelarOperacao()); + ReconfigurarGnssCommand = new RelayCommand(_ => ReconfigurarGnss()); DefinirSemRover(); } @@ -372,6 +383,10 @@ namespace OperationControl.ViewModels.Views.Operacao } } + private void ReconfigurarGnss() + { + Variaveis.Dock._vm.CurrentStep = DockStep.PreparacaoMapa; + } private string ValorOuTracos(string valor) => RoverSelecionado ? valor : "--"; diff --git a/AgroBase/OperationControl/ViewModels/Views/PreparacaoMapa/PreparacaoMapaBottomViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/PreparacaoMapa/PreparacaoMapaBottomViewModel.cs index 6cfb94529..66ab68662 100644 --- a/AgroBase/OperationControl/ViewModels/Views/PreparacaoMapa/PreparacaoMapaBottomViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/PreparacaoMapa/PreparacaoMapaBottomViewModel.cs @@ -1,4 +1,5 @@ -using OperationControl.Helpers; +using Microsoft.Win32; +using OperationControl.Helpers; using System; using System.Collections.Generic; using System.ComponentModel; @@ -26,7 +27,9 @@ namespace OperationControl.ViewModels public event PropertyChangedEventHandler? PropertyChanged; public event Action? CarregarMapaSolicitado; - public event Action? FixarBaseSolicitado; + + // Método, latitude, longitude, altitude, offset frontal cm, offset lateral cm + public event Action? FixarBaseSolicitado; public List MetodosFixacaoDisponiveis { get; } = new() { @@ -35,45 +38,18 @@ namespace OperationControl.ViewModels new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Manual, Nome = "Preenchimento manual" } }; - private bool _fixacaoEmAndamento; - public bool FixacaoEmAndamento + public ICommand CarregarMapaCommand { get; } + public ICommand FixarBaseCommand { get; } + + public PreparacaoMapaBottomViewModel() { - get => _fixacaoEmAndamento; - set - { - if (_fixacaoEmAndamento != value) - { - _fixacaoEmAndamento = value; - OnPropertyChanged(nameof(FixacaoEmAndamento)); - OnPropertyChanged(nameof(PodeCarregarMapa)); - OnPropertyChanged(nameof(PodeFixarBase)); - OnPropertyChanged(nameof(PodeEditarMetodoFixacao)); - OnPropertyChanged(nameof(PodeEditarCoordenadasManuais)); - } - } - } + CarregarMapaCommand = new RelayCommand(_ => ExecutarCarregarMapa(), _ => PodeCarregarMapa); + FixarBaseCommand = new RelayCommand(_ => ExecutarFixarBase(), _ => PodeFixarBase); - public bool PodeCarregarMapa => !FixacaoEmAndamento; - - public bool PodeEditarMetodoFixacao => !FixacaoEmAndamento; - - public bool PodeEditarCoordenadasManuais => - !FixacaoEmAndamento && MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual; - - public bool PodeFixarBase - { - get - { - if (FixacaoEmAndamento) - return true; // permite "Parar" - - if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual) - return true; - - return LatitudeManual.HasValue && - LongitudeManual.HasValue && - AltitudeManual.HasValue; - } + MetodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip; + OffsetFrontalBaseTexto = "0"; + OffsetLateralBaseTexto = "0"; + StatusTexto = "Pronto para carregar o mapa e fixar a base."; } private MetodoFixacaoBase _metodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip; @@ -88,7 +64,6 @@ namespace OperationControl.ViewModels OnPropertyChanged(nameof(MetodoFixacaoSelecionado)); OnPropertyChanged(nameof(ExibirCamposManuais)); - OnPropertyChanged(nameof(ExibirStatusNormal)); OnPropertyChanged(nameof(ExibirProgresso)); OnPropertyChanged(nameof(PodeEditarCoordenadasManuais)); OnPropertyChanged(nameof(PodeFixarBase)); @@ -112,10 +87,69 @@ namespace OperationControl.ViewModels } } + private bool _fixacaoEmAndamento; + public bool FixacaoEmAndamento + { + get => _fixacaoEmAndamento; + set + { + if (_fixacaoEmAndamento != value) + { + _fixacaoEmAndamento = value; + + OnPropertyChanged(nameof(FixacaoEmAndamento)); + OnPropertyChanged(nameof(PodeCarregarMapa)); + OnPropertyChanged(nameof(PodeEditarMetodoFixacao)); + OnPropertyChanged(nameof(PodeEditarCoordenadasManuais)); + OnPropertyChanged(nameof(PodeEditarOffsetBase)); + OnPropertyChanged(nameof(PodeFixarBase)); + OnPropertyChanged(nameof(TextoBotaoFixarBase)); + } + } + } + + public bool PodeCarregarMapa => !FixacaoEmAndamento; + + public bool PodeEditarMetodoFixacao => !FixacaoEmAndamento; + + public bool PodeEditarCoordenadasManuais => + !FixacaoEmAndamento && MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual; + + public bool PodeEditarOffsetBase => !FixacaoEmAndamento; + public bool ExibirCamposManuais => MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual; - public bool ExibirStatusNormal => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual; + public bool ExibirProgresso => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual; + public bool PodeFixarBase + { + get + { + if (FixacaoEmAndamento) + return true; // botão vira "Parar" + + if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual) + return true; + + return LatitudeManual.HasValue && + LongitudeManual.HasValue && + AltitudeManual.HasValue; + } + } + + public string TextoBotaoFixarBase + { + get + { + if (FixacaoEmAndamento) + return "Parar"; + + return MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual + ? "Aplicar posição manual" + : "Fixar posição da base"; + } + } + private double? _latitudeManual; public double? LatitudeManual { @@ -171,6 +205,7 @@ namespace OperationControl.ViewModels { _latitudeManualTexto = value; LatitudeManual = TryParseDouble(value); + OnPropertyChanged(nameof(LatitudeManualTexto)); OnPropertyChanged(nameof(PodeFixarBase)); } @@ -187,6 +222,7 @@ namespace OperationControl.ViewModels { _longitudeManualTexto = value; LongitudeManual = TryParseDouble(value); + OnPropertyChanged(nameof(LongitudeManualTexto)); OnPropertyChanged(nameof(PodeFixarBase)); } @@ -203,12 +239,73 @@ namespace OperationControl.ViewModels { _altitudeManualTexto = value; AltitudeManual = TryParseDouble(value); + OnPropertyChanged(nameof(AltitudeManualTexto)); OnPropertyChanged(nameof(PodeFixarBase)); } } } + private double? _offsetFrontalBaseCm; + public double? OffsetFrontalBaseCm + { + get => _offsetFrontalBaseCm; + private set + { + if (_offsetFrontalBaseCm != value) + { + _offsetFrontalBaseCm = value; + OnPropertyChanged(nameof(OffsetFrontalBaseCm)); + } + } + } + + private double? _offsetLateralBaseCm; + public double? OffsetLateralBaseCm + { + get => _offsetLateralBaseCm; + private set + { + if (_offsetLateralBaseCm != value) + { + _offsetLateralBaseCm = value; + OnPropertyChanged(nameof(OffsetLateralBaseCm)); + } + } + } + + private string _offsetFrontalBaseTexto = "0"; + public string OffsetFrontalBaseTexto + { + get => _offsetFrontalBaseTexto; + set + { + if (_offsetFrontalBaseTexto != value) + { + _offsetFrontalBaseTexto = value; + OffsetFrontalBaseCm = TryParseDouble(value); + + OnPropertyChanged(nameof(OffsetFrontalBaseTexto)); + } + } + } + + private string _offsetLateralBaseTexto = "0"; + public string OffsetLateralBaseTexto + { + get => _offsetLateralBaseTexto; + set + { + if (_offsetLateralBaseTexto != value) + { + _offsetLateralBaseTexto = value; + OffsetLateralBaseCm = TryParseDouble(value); + + OnPropertyChanged(nameof(OffsetLateralBaseTexto)); + } + } + } + private double _progressoFixacao; public double ProgressoFixacao { @@ -226,7 +323,7 @@ namespace OperationControl.ViewModels public string ProgressoFixacaoTexto => $"{ProgressoFixacao:F0}%"; - private string _statusTexto = "Pronto para carregar o mapa e fixar a base."; + private string _statusTexto = string.Empty; public string StatusTexto { get => _statusTexto; @@ -240,37 +337,15 @@ namespace OperationControl.ViewModels } } - public string TextoBotaoFixarBase - { - get - { - if (FixacaoEmAndamento) - return "Parar"; - - return MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual - ? "Aplicar posição manual" - : "Fixar posição da base"; - } - } - - public ICommand CarregarMapaCommand { get; } - public ICommand FixarBaseCommand { get; } - - public PreparacaoMapaBottomViewModel() - { - CarregarMapaCommand = new RelayCommand(_ => ExecutarCarregarMapa(), _ => PodeCarregarMapa); - FixarBaseCommand = new RelayCommand(_ => ExecutarFixarBase(), _ => PodeFixarBase); - } - private void ExecutarCarregarMapa() { - var dlg = new OpenFileDialog + var dlg = new Microsoft.Win32.OpenFileDialog { Filter = "Arquivos de mapa|*.geojson;*.json;*.shp", Title = "Selecione o arquivo de mapa" }; - if (dlg.ShowDialog() == DialogResult.OK) + if (dlg.ShowDialog() == true) { StatusTexto = $"Mapa selecionado: {System.IO.Path.GetFileName(dlg.FileName)}"; CarregarMapaSolicitado?.Invoke(dlg.FileName); @@ -285,7 +360,9 @@ namespace OperationControl.ViewModels MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, - AltitudeManual); + AltitudeManual, + OffsetFrontalBaseCm, + OffsetLateralBaseCm); return; } @@ -308,19 +385,14 @@ namespace OperationControl.ViewModels MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, - AltitudeManual); - } - - public void AtualizarProgresso(double progresso, string status) - { - ProgressoFixacao = progresso; - StatusTexto = status; + AltitudeManual, + OffsetFrontalBaseCm, + OffsetLateralBaseCm); } public void IniciarFixacao() { FixacaoEmAndamento = true; - OnPropertyChanged(nameof(TextoBotaoFixarBase)); ProgressoFixacao = 0; StatusTexto = MetodoFixacaoSelecionado switch @@ -332,31 +404,29 @@ namespace OperationControl.ViewModels }; } + public void AtualizarProgresso(double progresso, string status) + { + ProgressoFixacao = progresso; + StatusTexto = status; + } + public void FinalizarFixacao(bool sucesso, string? mensagem = null) { FixacaoEmAndamento = false; - OnPropertyChanged(nameof(TextoBotaoFixarBase)); - if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual) - ProgressoFixacao = sucesso ? 100 : ProgressoFixacao; + if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual && sucesso) + ProgressoFixacao = 100; - if (!string.IsNullOrWhiteSpace(mensagem)) - { - StatusTexto = mensagem; - } - else - { - StatusTexto = sucesso + StatusTexto = !string.IsNullOrWhiteSpace(mensagem) + ? mensagem + : sucesso ? "Fixação da base concluída com sucesso." : "Fixação da base encerrada."; - } } public void CancelarFixacao(string? mensagem = null) { FixacaoEmAndamento = false; - OnPropertyChanged(nameof(TextoBotaoFixarBase)); - StatusTexto = mensagem ?? "Fixação da base cancelada."; } @@ -378,14 +448,8 @@ namespace OperationControl.ViewModels texto = texto.Trim().Replace(",", "."); - if (double.TryParse( - texto, - NumberStyles.Any, - CultureInfo.InvariantCulture, - out var valor)) - { + if (double.TryParse(texto, NumberStyles.Any, CultureInfo.InvariantCulture, out var valor)) return valor; - } return null; } diff --git a/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs b/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs index 2dfe24d44..8ad274ba4 100644 --- a/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs @@ -776,7 +776,7 @@ namespace OperationControl.ViewModels } } - private async void OnFixarBaseSolicitado(MetodoFixacaoBase metodoFix, double? lat, double? lon, double? alt) + private async void OnFixarBaseSolicitado(MetodoFixacaoBase metodoFix, double? lat, double? lon, double? alt, double? offsetFrontalCm, double? offsetLateralCm) { try { diff --git a/AgroBase/OperationControl/Views/Operacao/OperacaoLeftView.xaml b/AgroBase/OperationControl/Views/Operacao/OperacaoLeftView.xaml index 4426f2dbd..f40fe3e99 100644 --- a/AgroBase/OperationControl/Views/Operacao/OperacaoLeftView.xaml +++ b/AgroBase/OperationControl/Views/Operacao/OperacaoLeftView.xaml @@ -26,12 +26,8 @@ - - + + @@ -40,12 +36,7 @@ - + @@ -54,24 +45,11 @@ - + - + - + @@ -193,41 +171,25 @@ - - - + -