Adicionado método de retorno à base por pontos manuais

This commit is contained in:
Diego Freitas 2026-03-26 22:42:40 -03:00
parent e230176950
commit e42e1e6109
7 changed files with 182 additions and 23 deletions

View File

@ -344,6 +344,7 @@ namespace AgroBase.Models
IP = VariaveisEquipamento.Parametros.rover_ip, IP = VariaveisEquipamento.Parametros.rover_ip,
RuasPercorrer = null, RuasPercorrer = null,
Mapa = null, Mapa = null,
PontosRetorno = null,
DadosLeitura = new OperacaoParametrosDadosModel(), DadosLeitura = new OperacaoParametrosDadosModel(),
}; };
@ -1130,6 +1131,7 @@ namespace AgroBase.Models
p.QtdCamerasSolo = Parametros.QtdCamerasSolo; p.QtdCamerasSolo = Parametros.QtdCamerasSolo;
p.Mapa = Parametros.Mapa; p.Mapa = Parametros.Mapa;
p.RuasPercorrer = Parametros.RuasPercorrer; p.RuasPercorrer = Parametros.RuasPercorrer;
p.PontosRetorno = Parametros.PontosRetorno;
p.ModulosMandatorios = Parametros.ModulosMandatorios; p.ModulosMandatorios = Parametros.ModulosMandatorios;
p.ParametrosMandatorios = Parametros.ParametrosMandatorios; p.ParametrosMandatorios = Parametros.ParametrosMandatorios;
@ -1221,6 +1223,13 @@ namespace AgroBase.Models
Variaveis.OperacaoEmAndamento.Finalizando = false; Variaveis.OperacaoEmAndamento.Finalizando = false;
Variaveis.OperacaoEmAndamento.Trajetoria?.AutonomiaCorredor?.Parar(); Variaveis.OperacaoEmAndamento.Trajetoria?.AutonomiaCorredor?.Parar();
Variaveis.OperacaoEmAndamento.DispSen?.Dados?.ContadorCarga?.FinalizarOperacao(); Variaveis.OperacaoEmAndamento.DispSen?.Dados?.ContadorCarga?.FinalizarOperacao();
if (Variaveis.OperacaoEmAndamento.Parametros.Modo == ModoOperacao.RetornoBase)
{
var p = CarregarParametrosOperacaoPadrao(ModoOperacao.MapaGPS, false);
Variaveis.OperacaoEmAndamento.Parametros = p;
RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false));
}
} }
public void ReiniciarOperacao(bool daBase) public void ReiniciarOperacao(bool daBase)
@ -1835,8 +1844,9 @@ namespace AgroBase.Models
if (controleBase.Dispositivo == T_Code.Trj) if (controleBase.Dispositivo == T_Code.Trj)
{ {
var (lat, lon, pontosRetorno) = ((JObject)controleBase._comp_value).ToObject<(double?, double?, List<double[]>)>(); var (lat, lon, pontosRetorno) = ((JObject)controleBase._comp_value).ToObject<(double?, double?, List<double[]>)>();
if (lat == null || lon == null) return; GPSModel posicaoBase = null;
GPSModel posicaoBase = new GPSModel() { Latitude = lat.Value, Longitude = lon.Value }; if (lat != null && lon != null)
posicaoBase = new GPSModel() { Latitude = lat.Value, Longitude = lon.Value };
List<GPSModel> pontosRetornoPos = null; List<GPSModel> pontosRetornoPos = null;
if (pontosRetorno?.Any() ?? false) if (pontosRetorno?.Any() ?? false)
pontosRetornoPos = pontosRetorno.Select(x => new GPSModel() { Latitude = x[0], Longitude = x[1] }).ToList(); pontosRetornoPos = pontosRetorno.Select(x => new GPSModel() { Latitude = x[0], Longitude = x[1] }).ToList();

View File

@ -148,6 +148,7 @@ namespace AgroBase.Models.Operacoes
public MapaFeatureCollectionModel Mapa { get; set; } public MapaFeatureCollectionModel Mapa { get; set; }
public List<string> RuasPercorrer { get; set; } public List<string> RuasPercorrer { get; set; }
public List<double[]> PontosRetorno { get; set; }
public OperacaoParametrosDadosModel DadosLeitura { get; set; } public OperacaoParametrosDadosModel DadosLeitura { get; set; }

View File

@ -1752,11 +1752,8 @@ namespace AgroBase.Models
// Retorno a base automatico // Retorno a base automatico
public void IniciarRetornoBase(GPSModel baseGps, List<GPSModel> waypointsManual = null) public void IniciarRetornoBase(GPSModel baseGps, List<GPSModel> waypointsManual = null)
{ {
if (baseGps == null)
throw new ArgumentNullException(nameof(baseGps));
bool valido = false; bool valido = false;
List<GPSModel> pontosRetorno; List<GPSModel> pontosRetorno = null;
// ========================= // =========================
// MODO MANUAL (operador) // MODO MANUAL (operador)
@ -1772,6 +1769,7 @@ namespace AgroBase.Models
// ========================= // =========================
// MODO AUTOMÁTICO // MODO AUTOMÁTICO
// ========================= // =========================
if (baseGps != null)
(valido, pontosRetorno) = GerarTrajetoriaRetornoAutomatico(baseGps); (valido, pontosRetorno) = GerarTrajetoriaRetornoAutomatico(baseGps);
} }

View File

@ -32,6 +32,7 @@ using Mapsui.Extensions;
using OperationControl.Models; using OperationControl.Models;
using static AgroBase.Models.Enums; using static AgroBase.Models.Enums;
using System.Windows.Input; using System.Windows.Input;
using AgroBase.Models;
namespace OperationControl.Controls namespace OperationControl.Controls
@ -545,6 +546,10 @@ namespace OperationControl.Controls
if (ParametrizandoOperacao) if (ParametrizandoOperacao)
HighlightRoad(roadFeature); HighlightRoad(roadFeature);
} }
else if (EmModoRetorno)
{
AlternarPontoNoMapa(sp);
}
else else
{ {
OnMarkerClicked(null); OnMarkerClicked(null);
@ -566,6 +571,8 @@ namespace OperationControl.Controls
Mapa.Cursor = System.Windows.Input.Cursors.Hand; Mapa.Cursor = System.Windows.Input.Cursors.Hand;
else if (feat != null && info?.Layer == MapaPlantacao_Layer && feat is MIFeature roadFeature && ParametrizandoOperacao) else if (feat != null && info?.Layer == MapaPlantacao_Layer && feat is MIFeature roadFeature && ParametrizandoOperacao)
Mapa.Cursor = System.Windows.Input.Cursors.Hand; Mapa.Cursor = System.Windows.Input.Cursors.Hand;
else if (feat != null && info?.Layer == _layerPontosSelecionados && feat is PointFeature pointFeature && EmModoRetorno)
Mapa.Cursor = System.Windows.Input.Cursors.Hand;
else else
Mapa.Cursor = System.Windows.Input.Cursors.Arrow; Mapa.Cursor = System.Windows.Input.Cursors.Arrow;
} }
@ -577,6 +584,120 @@ namespace OperationControl.Controls
} }
#region RETORNO A BASE MANUAL
private MemoryLayer _layerPontosSelecionados;
public List<GPSModel> _pontosSelecionados = new List<GPSModel>();
double ToleranciaRemocaoMetros = 2.0;
private bool EmModoRetorno =>
!SemRoverFocado &&
!(VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Iniciada ?? false) &&
(VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Status ?? StatusOperacao.NaoIniciado) == StatusOperacao.Parametrizando &&
Models.Variaveis.Dock?._vm?._viewOperacaoRight?._vm?.SecaoAtual == ViewModels.Views.Operacao.SecaoRightBar.Parametrizacao &&
Models.Variaveis.Dock?._vm?._viewOperacaoRight?.areaParametrizacao?._vm?.Parametros?.Modo == ModoOperacao.RetornoBase;
private void AlternarPontoNoMapa(ScreenPosition sp)
{
try
{
// Dependendo da versão do Mapsui, pode ser:
// var world = Mapa.Navigator.Viewport.ScreenToWorld(sp.X, sp.Y);
// ou:
var world = Mapa.Map.Navigator.Viewport.ScreenToWorld(sp.X, sp.Y);
// Normalmente o mapa está em EPSG:3857
var lonLat = Mapsui.Projections.SphericalMercator.ToLonLat(world.X, world.Y);
GPSModel ponto = new GPSModel() { Latitude = lonLat.lat, Longitude = lonLat.lon };
var existente = _pontosSelecionados
.FirstOrDefault(p => GPSUtils.DistanciaEntrePontos(ponto, p) <= ToleranciaRemocaoMetros);
if (existente != null)
{
_pontosSelecionados.Remove(existente);
}
else
{
_pontosSelecionados.Add(ponto);
}
RedesenharPontosSelecionados();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Erro ao alternar ponto no mapa: {ex.Message}");
}
finally
{
Models.Variaveis.MostrarLog($"Pontos: {_pontosSelecionados.Count}");
}
}
private void RedesenharPontosSelecionados()
{
var features = new List<Mapsui.IFeature>();
for (int i = 0; i < _pontosSelecionados.Count; i++)
{
var p = _pontosSelecionados[i];
var mercator = Mapsui.Projections.SphericalMercator.FromLonLat(p.Longitude, p.Latitude);
var feature = new PointFeature(mercator.x, mercator.y);
// número do ponto
feature["label"] = (i + 1).ToString();
// círculo
feature.Styles.Add(new SymbolStyle
{
SymbolType = SymbolType.Ellipse,
SymbolScale = 1.2,
Fill = new Brush(Color.Red),
Outline = new Pen(Color.White, 2)
});
// texto (número)
feature.Styles.Add(new LabelStyle
{
LabelColumn = "label",
ForeColor = Color.White,
BackColor = null,
HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center,
VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Center,
Offset = new Offset(0, 0),
Font = new Font { Size = 12 }
});
features.Add(feature);
}
if (_layerPontosSelecionados == null)
{
_layerPontosSelecionados = new MemoryLayer
{
Name = "PontosSelecionados"
};
Mapa.Map.Layers.Add(_layerPontosSelecionados);
}
_layerPontosSelecionados.Features = features;
Mapa.Refresh();
}
public void LimparPontosSelecionados()
{
_pontosSelecionados = new List<GPSModel>();
RedesenharPontosSelecionados();
VariaveisControleOperacao.RoverEmFoco.PontosRetorno = null;
}
#endregion
private void EnsureBaseLayer() private void EnsureBaseLayer()
{ {
try try
@ -802,7 +923,7 @@ namespace OperationControl.Controls
} }
catch (Exception ex) catch (Exception ex)
{ {
Variaveis.MostrarLog($"Erro ao carregar coordenadas do mapa: {ex.Message}"); Models.Variaveis.MostrarLog($"Erro ao carregar coordenadas do mapa: {ex.Message}");
} }
} }
@ -915,7 +1036,7 @@ namespace OperationControl.Controls
return _mapa; return _mapa;
} }
public void CarregarDadosMapa(AgroBase.Models.MapaFeatureCollectionModel Mapa, List<string> RuasSelecionadas) public void CarregarDadosMapa(AgroBase.Models.MapaFeatureCollectionModel Mapa, List<string> RuasSelecionadas, List<double[]> pontosSelecionados)
{ {
if (RuasMapaCarregado.Any()) if (RuasMapaCarregado.Any())
{ {
@ -928,6 +1049,8 @@ namespace OperationControl.Controls
AtualizarStylesRuas(); AtualizarStylesRuas();
} }
_pontosSelecionados = (pontosSelecionados ?? new List<double[]>()).Select(x => new GPSModel() { Latitude = x[0], Longitude = x[1] }).ToList();
RedesenharPontosSelecionados();
} }

View File

@ -67,6 +67,7 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
private void ReiniciarOperacao() private void ReiniciarOperacao()
{ {
VariaveisControleOperacao.EnviarComandoIniciarOperacao(false, false); VariaveisControleOperacao.EnviarComandoIniciarOperacao(false, false);
Models.Variaveis.Dock?._vm?._viewOperacaoCenter?.Mapa?.LimparPontosSelecionados();
} }
public void AtualizarParametros(OperacaoParametrosModel origem) public void AtualizarParametros(OperacaoParametrosModel origem)

View File

@ -380,6 +380,7 @@ namespace OperationControl.ViewModels.Views.Operacao
if (System.Windows.MessageBox.Show("Deseja finalizar a operação em andamento?", "Finalizar Operação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) if (System.Windows.MessageBox.Show("Deseja finalizar a operação em andamento?", "Finalizar Operação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{ {
VariaveisControleOperacao.EnviarComandoIniciarOperacao(false); VariaveisControleOperacao.EnviarComandoIniciarOperacao(false);
Models.Variaveis.Dock?._vm?._viewOperacaoCenter?.Mapa?.LimparPontosSelecionados();
} }
} }

View File

@ -1,8 +1,7 @@
using AgroBase.Models.Operacoes; using AgroBase.Models;
using AgroBase.Models.Operacoes;
using AgroBase.Services; using AgroBase.Services;
using Microsoft.VisualBasic.Logging;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using OpenTK.Windowing.Common.Input;
using OperationControl.Controls; using OperationControl.Controls;
using OperationControl.Helpers; using OperationControl.Helpers;
using OperationControl.Models; using OperationControl.Models;
@ -740,7 +739,7 @@ namespace OperationControl.ViewModels
public void AtualizarDadosMapa(OperacaoParametrosModel? dados) public void AtualizarDadosMapa(OperacaoParametrosModel? dados)
{ {
_viewOperacaoCenter?.Mapa?.LoadMapFile(_ultimoMapaCarregado); _viewOperacaoCenter?.Mapa?.LoadMapFile(_ultimoMapaCarregado);
_viewOperacaoCenter?.Mapa?.CarregarDadosMapa(dados?.Mapa, dados?.RuasPercorrer); _viewOperacaoCenter?.Mapa?.CarregarDadosMapa(dados?.Mapa, dados?.RuasPercorrer, dados?.PontosRetorno);
} }
#region TELA 2 #region TELA 2
@ -755,9 +754,9 @@ namespace OperationControl.ViewModels
Mapa?.markers?.AddMarker( Mapa?.markers?.AddMarker(
markerId, markerId,
true, true,
lat: Variaveis.GpsService?.UltimaLeitura?.Latitude, lat: Models.Variaveis.GpsService?.UltimaLeitura?.Latitude,
lon: Variaveis.GpsService?.UltimaLeitura?.Longitude, lon: Models.Variaveis.GpsService?.UltimaLeitura?.Longitude,
heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal, heading: Models.Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal,
label: "Base" label: "Base"
); );
} }
@ -783,11 +782,11 @@ namespace OperationControl.ViewModels
{ {
try try
{ {
if (!(Variaveis.GpsService.BaseFix?.FixLiberado ?? false)) if (!(Models.Variaveis.GpsService.BaseFix?.FixLiberado ?? false))
{ {
bool fixar = false; bool fixar = false;
if (Variaveis.GpsService.BaseFix?.PosicaoBaseFixada ?? false) if (Models.Variaveis.GpsService.BaseFix?.PosicaoBaseFixada ?? false)
{ {
var res = System.Windows.MessageBox.Show( var res = System.Windows.MessageBox.Show(
"Mudar posição da base?", "Mudar posição da base?",
@ -806,12 +805,12 @@ namespace OperationControl.ViewModels
if (fixar) if (fixar)
{ {
_viewPreparacaoMapaBottom?._vm.IniciarFixacao(); _viewPreparacaoMapaBottom?._vm.IniciarFixacao();
await Variaveis.GpsService.ConfigurarModulo(true, metodoFix, lat, lon, alt); await Models.Variaveis.GpsService.ConfigurarModulo(true, metodoFix, lat, lon, alt);
} }
} }
else else
{ {
Variaveis.GpsService.BaseFix.ReiniciarFix(); Models.Variaveis.GpsService.BaseFix.ReiniciarFix();
BaseFixada = false; BaseFixada = false;
} }
} }
@ -852,10 +851,10 @@ namespace OperationControl.ViewModels
if (offsetFrontalCm == null || offsetLateralCm == null) return; if (offsetFrontalCm == null || offsetLateralCm == null) return;
_viewPreparacaoMapaBottom?._vm.IniciarFixacao(); _viewPreparacaoMapaBottom?._vm.IniciarFixacao();
var gps = Variaveis.GpsService; var gps = Models.Variaveis.GpsService;
gps.LeverArm = new GeoLeverArm(offsetCampoFrontalCm: offsetFrontalCm.Value, offsetCampoLateralCm: offsetLateralCm.Value); gps.LeverArm = new GeoLeverArm(offsetCampoFrontalCm: offsetFrontalCm.Value, offsetCampoLateralCm: offsetLateralCm.Value);
(double lat, double lon) = gps.LeverArm.FixLeverArmLatLon_Fast(gps.BaseFix.LatitudeFix, gps.BaseFix.LongitudeFix, gps.BaseFix.OrientacaoFix); (double lat, double lon) = gps.LeverArm.FixLeverArmLatLon_Fast(gps.BaseFix.LatitudeFix, gps.BaseFix.LongitudeFix, gps.BaseFix.OrientacaoFix);
await Variaveis.GpsService.ConfigurarModulo(true, MetodoFixacaoBase.Manual, lat, lon, gps.BaseFix.AltitudeElpsoidalFix, offset: true); await Models.Variaveis.GpsService.ConfigurarModulo(true, MetodoFixacaoBase.Manual, lat, lon, gps.BaseFix.AltitudeElpsoidalFix, offset: true);
} }
#endregion #endregion
@ -1099,9 +1098,34 @@ namespace OperationControl.ViewModels
} }
private void OnSalvarParametrosSolicitado(OperacaoParametrosModel parametros) private void OnSalvarParametrosSolicitado(OperacaoParametrosModel parametros)
{ {
var rover = VariaveisControleOperacao.RoverEmFoco;
if (parametros.Modo == AgroBase.Models.Enums.ModoOperacao.RetornoBase)
{
var pontos = _viewOperacaoCenter?.Mapa?._pontosSelecionados;
if (!(pontos?.Any() ?? false))
{
System.Windows.MessageBox.Show("Clique no mapa para marcar os pontos por onde o equipamento deve seguir", "Pontos não marcados", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (System.Windows.MessageBox.Show($"Deseja iniciar a operação de retorno seguindo os {pontos.Count} pontos marcados no mapa, somando em {GPSUtils.DistanciaDoTrecho(pontos):F2} metros?", "Confirmação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
parametros.PontosRetorno = pontos.Select(x => new double[] { x.Latitude, x.Longitude }).ToList();
VariaveisControleOperacao.EnviarComandoRetornoBase(pontosRetorno: parametros.PontosRetorno);
rover.PontosRetorno = parametros.PontosRetorno;
Task.Run(async () =>
{
await Task.Delay(500);
_viewOperacaoRight?._vm?.SelecionarSecao(SecaoRightBar.Resumo);
});
}
return;
}
var dadosMapa = _viewOperacaoCenter?.Mapa?.CriarDadosMapa(); var dadosMapa = _viewOperacaoCenter?.Mapa?.CriarDadosMapa();
var ruasPercorrer = _viewOperacaoCenter?.Mapa?.RuasMapaCarregado?.Where(x => x.Selected)?.Select(x => x.Id)?.ToList() ?? new List<string>(); var ruasPercorrer = _viewOperacaoCenter?.Mapa?.RuasMapaCarregado?.Where(x => x.Selected)?.Select(x => x.Id)?.ToList() ?? new List<string>();
var rover = VariaveisControleOperacao.RoverEmFoco;
if (rover?.DadosLeitura?.Operacao?.Modo != parametros.Modo && (rover?.DadosLeitura?.Operacao?.Iniciada ?? false)) if (rover?.DadosLeitura?.Operacao?.Modo != parametros.Modo && (rover?.DadosLeitura?.Operacao?.Iniciada ?? false))
{ {
@ -1283,6 +1307,7 @@ namespace OperationControl.ViewModels
rover.ModulosMandatorios = novosParametros.ModulosMandatorios; rover.ModulosMandatorios = novosParametros.ModulosMandatorios;
rover.ParametrosMandatorios = novosParametros.ParametrosMandatorios; rover.ParametrosMandatorios = novosParametros.ParametrosMandatorios;
rover.RuasPercorrer = novosParametros.RuasPercorrer; rover.RuasPercorrer = novosParametros.RuasPercorrer;
rover.PontosRetorno = novosParametros.PontosRetorno;
rover.Mapa = novosParametros.Mapa; rover.Mapa = novosParametros.Mapa;
AtualizarDadosDiagnostico(rover); AtualizarDadosDiagnostico(rover);