Pequenos ajustes ao reiniciar MPC e retorno a base

This commit is contained in:
Diego Freitas 2026-03-16 14:17:38 -03:00
parent 79ea971a9b
commit 88d5ac701e
10 changed files with 99 additions and 30 deletions

View File

@ -747,7 +747,7 @@ namespace AgroBase
if (!Forcar) if (!Forcar)
{ {
if (!Variaveis.OperacaoEmAndamento.Iniciado) return; if (!Variaveis.OperacaoEmAndamento.Iniciado) return;
bool componente_em_uso = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == T_Code.Atu && x.ComponentesEmUso != null && x.ComponentesEmUso[ID].Item2); bool componente_em_uso = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == T_Code.Atu && (x.ComponentesEmUso?.ContainsKey(ID) ?? false) && x.ComponentesEmUso[ID].Item2);
if (!componente_em_uso && (Status ?? false)) return; // Impede execucao de comandos que liguem componentes quando estiver marcado para nao utilizar if (!componente_em_uso && (Status ?? false)) return; // Impede execucao de comandos que liguem componentes quando estiver marcado para nao utilizar
} }
@ -803,7 +803,7 @@ namespace AgroBase
if (!Forcar) if (!Forcar)
{ {
bool componente_em_uso = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == T_Code.Sen && x.ComponentesEmUso != null && x.ComponentesEmUso[ID].Item2); bool componente_em_uso = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == T_Code.Sen && (x.ComponentesEmUso?.ContainsKey(ID) ?? false) && x.ComponentesEmUso[ID].Item2);
if (!componente_em_uso) if (!componente_em_uso)
{ {
// Impede execucao de comandos que liguem componentes quando estiver marcado para nao utilizar // Impede execucao de comandos que liguem componentes quando estiver marcado para nao utilizar

View File

@ -1075,6 +1075,7 @@ namespace AgroBase.Models
SalvarLogs(false); SalvarLogs(false);
Variaveis.OperacaoEmAndamento.Finalizando = false; Variaveis.OperacaoEmAndamento.Finalizando = false;
Variaveis.OperacaoEmAndamento.Trajetoria?.AutonomiaCorredor?.Parar();
} }
public async Task RealizarCalibragemInicialAsync(bool forcar) public async Task RealizarCalibragemInicialAsync(bool forcar)
@ -1659,8 +1660,13 @@ namespace AgroBase.Models
if (controleBase.Dispositivo == T_Code.Trj) if (controleBase.Dispositivo == T_Code.Trj)
{ {
var (posicaoBase, pontosRetorno) = ((JObject)controleBase._comp_value).ToObject<(GPSModel, List<GPSModel>)>(); var (lat, lon, pontosRetorno) = ((JObject)controleBase._comp_value).ToObject<(double?, double?, List<double[]>)>();
Variaveis.OperacaoEmAndamento.Trajetoria?.IniciarRetornoBase(posicaoBase, pontosRetorno); if (lat == null || lon == null) return;
GPSModel posicaoBase = new GPSModel() { Latitude = lat.Value, Longitude = lon.Value };
List<GPSModel> pontosRetornoPos = null;
if (pontosRetorno?.Any() ?? false)
pontosRetornoPos = pontosRetorno.Select(x => new GPSModel() { Latitude = x[0], Longitude = x[1] }).ToList();
Variaveis.OperacaoEmAndamento.Trajetoria?.IniciarRetornoBase(posicaoBase, pontosRetornoPos);
return; return;
} }

View File

@ -750,7 +750,7 @@ namespace AgroBase.Models
private bool VerificaInicioOperacaoMeioRua(bool considerarStatus) private bool VerificaInicioOperacaoMeioRua(bool considerarStatus)
{ {
if (!VerificacaoInicialMeioRuaConcluida && ((considerarStatus && new List<StatusOperacao>() { StatusOperacao.Aguardando, StatusOperacao.EmAndamento }.Contains(Variaveis.OperacaoEmAndamento.StatusAtual)) || !considerarStatus)) if (_TrajetoriaFixaDefinida && !VerificacaoInicialMeioRuaConcluida && ((considerarStatus && new List<StatusOperacao>() { StatusOperacao.Aguardando, StatusOperacao.EmAndamento }.Contains(Variaveis.OperacaoEmAndamento.StatusAtual)) || !considerarStatus))
{ {
VerificacaoInicialMeioRuaConcluida = true; VerificacaoInicialMeioRuaConcluida = true;
(bool noCoredor, var idxPontoMaisProximo) = VerificaEquipamentoDentroCorredorMontado(_TrajetoriaFixa[0].Posicao); (bool noCoredor, var idxPontoMaisProximo) = VerificaEquipamentoDentroCorredorMontado(_TrajetoriaFixa[0].Posicao);
@ -1572,6 +1572,8 @@ namespace AgroBase.Models
RetornandoBase = false; RetornandoBase = false;
CorredorAtual = _Corredores[0];
AutonomiaCorredor.Iniciar(); AutonomiaCorredor.Iniciar();
AtualizarDadosTrajetoria(); AtualizarDadosTrajetoria();
@ -1791,25 +1793,27 @@ namespace AgroBase.Models
}); });
var pontos_corrigidos = RemoverPontosMuitoProximos(pontos, DistanciaEntrePontos, 0, DistanciaEntrePontosCurva); var pontos_corrigidos = RemoverPontosMuitoProximos(pontos, DistanciaEntrePontos, 0, DistanciaEntrePontosCurva);
double distanciaPararAntecipado = 3.5;
int idx = 1; int idx = 1;
int qtdPontosRemoverFinal = (int)(distanciaPararAntecipado / DistanciaEntrePontos);
foreach (var p in pontos_corrigidos) foreach (var p in pontos_corrigidos)
{ {
traj.Add(new PontoTrajetoriaModel(TipoPontoRua.Rua) if (idx < (pontos_corrigidos.Count - qtdPontosRemoverFinal) || idx == pontos_corrigidos.Count - 1)
{ {
idxCorredor = 0, traj.Add(new PontoTrajetoriaModel(TipoPontoRua.Rua)
idxPonto = idx, {
idxPontoCorredor = idx, idxCorredor = 0,
Posicao = p, idxPonto = traj.Count,
Visitado = false, idxPontoCorredor = traj.Count,
LarguraCorredor = 1.5 Posicao = p,
}); Visitado = false,
LarguraCorredor = 1.5
});
}
idx++; idx++;
} }
//traj[traj.Count - 1].LarguraCorredor = 3.0; // Considerar que chegou na base a 2,5 m traj[traj.Count - 1].LarguraCorredor = distanciaPararAntecipado; // Considerar que chegou na base a 2,5 m
DistanciaTotal = GPSUtils.DistanciaDoTrecho(traj.Select(x => x.Posicao).ToList()); DistanciaTotal = GPSUtils.DistanciaDoTrecho(traj.Select(x => x.Posicao).ToList());
DistanciaPercorrida = 0.0; DistanciaPercorrida = 0.0;
@ -2780,6 +2784,7 @@ namespace AgroBase.Models
// ========================== // ==========================
public void Iniciar() public void Iniciar()
{ {
Reiniciar();
Iniciado = true; Iniciado = true;
} }
@ -3028,6 +3033,24 @@ namespace AgroBase.Models
Motivos = res.Motivos; Motivos = res.Motivos;
} }
// ==========================
// Reiniciar
// ==========================
public void Reiniciar()
{
Iniciado = false;
Liberado = false;
Motivos = new List<string>();
Motivo = "";
Status = AutonomiaCorredorStatus.Desconhecido;
DistanciaCorredor_m = 0;
DistanciaSeguraBateria_m = 0;
DistanciaSeguraHerbicida_m = 0;
CorredoresLiberados.Clear();
_corredoresTravados.Clear();
_inicioCriticoUtc.Clear();
}
// ========================== // ==========================
// Clone (mantido) // Clone (mantido)
// ========================== // ==========================
@ -3037,6 +3060,7 @@ namespace AgroBase.Models
{ {
Iniciado = Iniciado, Iniciado = Iniciado,
Liberado = Liberado, Liberado = Liberado,
Motivo = Motivo,
Motivos = new List<string>(Motivos ?? new List<string>()), Motivos = new List<string>(Motivos ?? new List<string>()),
Status = Status, Status = Status,
DistanciaCorredor_m = DistanciaCorredor_m, DistanciaCorredor_m = DistanciaCorredor_m,

View File

@ -76,8 +76,8 @@ class ModuloIPBribge(ModuloDiagnosticoBase):
self._ping_count = 2 # recomendado: 1 (janela já suaviza) self._ping_count = 2 # recomendado: 1 (janela já suaviza)
self._ping_min_interval = 0.6 # não precisa pingar a cada 100ms self._ping_min_interval = 0.6 # não precisa pingar a cada 100ms
self.bw_max_mbps = 3.0 # capacidade aproximada do link (ajuste por teste) self.bw_max_mbps = 10.0 # capacidade aproximada do link (ajuste por teste)
self.bw_safe_mbps = 2.0 # alvo saudável (até aqui não penaliza) self.bw_safe_mbps = 05.0 # alvo saudável (até aqui não penaliza)
self.bw_hard_mbps = 2.5 # acima disso é zona vermelha self.bw_hard_mbps = 2.5 # acima disso é zona vermelha
@ -618,9 +618,9 @@ class ModuloIPBribge(ModuloDiagnosticoBase):
""" """
# fallback quando não há posição válida # fallback quando não há posição válida
if distancia_m is None or distancia_m < 0: if distancia_m is None or distancia_m < 0:
self.bw_max_mbps = 3.0 self.bw_max_mbps = 10.0
self.bw_safe_mbps = 2.0 self.bw_safe_mbps = 05.0
self.bw_hard_mbps = 2.5 self.bw_hard_mbps = 02.5
return return
# limita a curva # limita a curva

View File

@ -59,12 +59,16 @@ def main():
if acao == ManagerWorkerCommandType.IniciarMPC: if acao == ManagerWorkerCommandType.IniciarMPC:
try: try:
_p = dados.get("params") _p = dados.get("params")
if _p is not None:
from manager_worker.modulos.mpc import inicializar as iniciar_mpc, get_iniciado
_mpc_iniciado = get_iniciado()
if _mpc_iniciado and _p is None:
ContextoGlobalRedis()._atualizar_mpc(do_manager=True, iniciar_operacao=True)
elif _p is not None:
parametros = _p.get("parametros") parametros = _p.get("parametros")
mapa = _p.get("mapa") mapa = _p.get("mapa")
iniciar_operacao = _p.get("iniciar_operacao", False) iniciar_operacao = _p.get("iniciar_operacao", False)
p_ref = _p.get("p_ref", []) p_ref = _p.get("p_ref", [])
from manager_worker.modulos.mpc import inicializar as iniciar_mpc
iniciar_mpc(parametros, mapa, p_ref, iniciar_operacao) iniciar_mpc(parametros, mapa, p_ref, iniciar_operacao)
else: else:
ContextoGlobalRedis()._atualizar_mpc(do_manager=True, iniciar_operacao=False) ContextoGlobalRedis()._atualizar_mpc(do_manager=True, iniciar_operacao=False)

View File

@ -13,7 +13,8 @@ _iniciado = False
def inicializar(parametros, mapa, p_ref, forcar): def inicializar(parametros, mapa, p_ref, forcar):
global _mpc, _iniciado global _mpc, _iniciado
if not _iniciado or len(_mpc.pontos_info) != len(mapa) or forcar: mostrar_log(f"[MPC] Inicializar chamado. iniciado: {_iniciado}, len_pontosinfo: {(len(_mpc.pontos_info) if _mpc is not None else 0)}, len_mapa: {len(mapa)}, forcar: {forcar}")
if not _iniciado or (_mpc is not None and len(_mpc.pontos_info) != len(mapa)) or forcar:
_mpc = ControladorMPC(parametros_mpc=parametros, pontos_mapa=mapa, p_ref=p_ref) _mpc = ControladorMPC(parametros_mpc=parametros, pontos_mapa=mapa, p_ref=p_ref)
mostrar_log(f"MPC iniciado! Trajetoria com {len(_mpc.pontos_info)} pontos") mostrar_log(f"MPC iniciado! Trajetoria com {len(_mpc.pontos_info)} pontos")
_iniciado = True _iniciado = True
@ -22,6 +23,10 @@ def get_mpc():
global _mpc global _mpc
return _mpc return _mpc
def get_iniciado():
global _iniciado
return _iniciado
def comando_parado(): def comando_parado():
return 0.0, TipoMovimentoDirecional.RodasDianteiras return 0.0, TipoMovimentoDirecional.RodasDianteiras
@ -77,7 +82,7 @@ class ControladorMPC:
self._precompute_centerline() self._precompute_centerline()
except Exception as e: except Exception as e:
mostrar_log(f"Erro ao inicializar MPC: {e}") mostrar_log(f"Erro ao inicializar __init__ MPC: {e}")
def _precompute_centerline(self): def _precompute_centerline(self):
cl = np.array([p["xy"] for p in self.pontos_info], dtype=float) # N x 2 cl = np.array([p["xy"] for p in self.pontos_info], dtype=float) # N x 2

View File

@ -539,6 +539,17 @@ namespace OperationControl.Models
}); });
} }
public static void EnviarComandoRetornoBase(double? lat = null, double? lon = null, List<double[]> pontosRetorno = null)
{
var cmd = new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Trj,
_comp_value = (lat, lon, pontosRetorno)
};
EnviarDadosControle(SelectedRoverId, cmd);
}
#endregion #endregion
} }

View File

@ -1,7 +1,11 @@
using AgroBase.Models.Operadores; using AgroBase.Models;
using AgroBase.Models.Operadores;
using OperationControl.Helpers;
using OperationControl.Models;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows.Input;
using static AgroBase.Models.Enums; using static AgroBase.Models.Enums;
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
@ -98,6 +102,8 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
public event Action<TipoFrameCamera>? CameraFrontalFrameTipoAlterado; public event Action<TipoFrameCamera>? CameraFrontalFrameTipoAlterado;
public event Action<TipoFrameCamera>? CameraErvasFrameTipoAlterado; public event Action<TipoFrameCamera>? CameraErvasFrameTipoAlterado;
public ICommand RetornoBaseCommand { get; }
public MonitoramentoViewModel() public MonitoramentoViewModel()
{ {
var itens = Enum.GetValues(typeof(TipoFrameCamera)) var itens = Enum.GetValues(typeof(TipoFrameCamera))
@ -114,6 +120,8 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
CameraFrontalFrameTipoSelecionado = CameraFrontalFrameTipos.FirstOrDefault(); CameraFrontalFrameTipoSelecionado = CameraFrontalFrameTipos.FirstOrDefault();
CameraErvasFrameTipoSelecionado = CameraErvasFrameTipos.FirstOrDefault(); CameraErvasFrameTipoSelecionado = CameraErvasFrameTipos.FirstOrDefault();
RetornoBaseCommand = new RelayCommand(_ => ExecutarRetornoBase(), _ => PodeExecutarRetornoBase());
} }
public void AtualizarDadosCameras(CameraWorkerItemModel? snr, CameraWorkerItemModel? cam, StatusCarroMapa? status_carro, double? pct_ervas) public void AtualizarDadosCameras(CameraWorkerItemModel? snr, CameraWorkerItemModel? cam, StatusCarroMapa? status_carro, double? pct_ervas)
@ -134,6 +142,18 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
} }
private void ExecutarRetornoBase()
{
double lat = OperationControl.Models.Variaveis.GpsService.UltimaLeitura.Latitude;
double lon = OperationControl.Models.Variaveis.GpsService.UltimaLeitura.Longitude;
VariaveisControleOperacao.EnviarComandoRetornoBase(lat, lon);
}
private bool PodeExecutarRetornoBase()
{
return true;
}
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)

View File

@ -335,7 +335,6 @@ namespace OperationControl.ViewModels
CenterContent = _viewPreparacaoMapa; CenterContent = _viewPreparacaoMapa;
BottomContent = _viewPreparacaoMapaBottom; BottomContent = _viewPreparacaoMapaBottom;
RightContent = CriarBotaoNextSimples(); RightContent = CriarBotaoNextSimples();
CriarMarcadorBase(_viewPreparacaoMapa?.MapaPreparacao);
break; break;
case DockStep.ParametrizacaoRover: case DockStep.ParametrizacaoRover:
@ -344,7 +343,6 @@ namespace OperationControl.ViewModels
CenterContent = _viewOperacaoCenter; CenterContent = _viewOperacaoCenter;
RightContent = _viewOperacaoRight; RightContent = _viewOperacaoRight;
BottomContent = _viewOperacaoBottom; BottomContent = _viewOperacaoBottom;
CriarMarcadorBase(_viewOperacaoCenter?.Mapa);
AtualizarDadosMapa(null); AtualizarDadosMapa(null);
AtualizarBarraSuperior(StatusModulo.Conectado, "BASE", "VISÃO GERAL", "Selecione um equipamento na lista à direita para configurá-lo", "NORMAL", "Aguardando"); AtualizarBarraSuperior(StatusModulo.Conectado, "BASE", "VISÃO GERAL", "Selecione um equipamento na lista à direita para configurá-lo", "NORMAL", "Aguardando");
break; break;
@ -612,6 +610,7 @@ namespace OperationControl.ViewModels
{ {
_viewPreparacaoMapaTop?._vm?.AtualizarDados(dados); _viewPreparacaoMapaTop?._vm?.AtualizarDados(dados);
} }
CriarMarcadorBase(Mapa);
Mapa?.markers?.UpdateMarkerPosition(VariaveisControleOperacao.BaseMarkerID, lat: dados?.Latitude, lon: dados?.Longitude, heading: dados?.OrientacaoReal); Mapa?.markers?.UpdateMarkerPosition(VariaveisControleOperacao.BaseMarkerID, lat: dados?.Latitude, lon: dados?.Longitude, heading: dados?.OrientacaoReal);
} }

View File

@ -134,7 +134,7 @@
<TextBlock Grid.Row="0" Text="Ações rápidas" Margin="0,0,0,8" FontSize="12" FontWeight="SemiBold" Foreground="#E6E6E6"/> <TextBlock Grid.Row="0" Text="Ações rápidas" Margin="0,0,0,8" FontSize="12" FontWeight="SemiBold" Foreground="#E6E6E6"/>
<UniformGrid Grid.Row="1" Rows="1" Columns="4" Margin="0,4,0,0"> <UniformGrid Grid.Row="1" Rows="1" Columns="4" Margin="0,4,0,0">
<Button Content="Retorno à base" Margin="4"/> <Button Content="Retorno à base" Margin="4" Command="{Binding RetornoBaseCommand}"/>
<Button Content="Parametrização" Margin="4"/> <Button Content="Parametrização" Margin="4"/>
<Button Content="Pausar operação" Margin="4"/> <Button Content="Pausar operação" Margin="4"/>
<Button Content="Diagnóstico" Margin="4"/> <Button Content="Diagnóstico" Margin="4"/>