Compare commits
No commits in common. "19392738f7690391f00dbaf57a734a00b2e958f1" and "7a1b6bd51d6ea72093ca153e3cf6bf1960b45d6a" have entirely different histories.
19392738f7
...
7a1b6bd51d
|
|
@ -206,7 +206,7 @@ namespace AgroBase.Forms.IHM.Operacao
|
||||||
?? operacaoParametrizando.Mapa?.RuasPercorrer?.Count
|
?? operacaoParametrizando.Mapa?.RuasPercorrer?.Count
|
||||||
?? 0;
|
?? 0;
|
||||||
|
|
||||||
if (qtdRuas < 2)
|
if (qtdRuas == 0)
|
||||||
{
|
{
|
||||||
FuncoesIHM.MostrarAlerta(
|
FuncoesIHM.MostrarAlerta(
|
||||||
"Trajetória não parametrizada",
|
"Trajetória não parametrizada",
|
||||||
|
|
@ -217,29 +217,12 @@ namespace AgroBase.Forms.IHM.Operacao
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
if (operacaoIniciada)
|
||||||
{
|
op?.AtualizarParametrosParciais(operacaoParametrizando.Parametros, op);
|
||||||
if (operacaoIniciada)
|
else
|
||||||
{
|
OperacaoModel.CarregarParamerosOperacaoBase(operacaoParametrizando.Parametros);
|
||||||
op?.AtualizarParametrosParciais(operacaoParametrizando.Parametros, op);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
OperacaoModel.CarregarParamerosOperacaoBase(operacaoParametrizando.Parametros);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParametrosSalvos?.Invoke(this, EventArgs.Empty);
|
ParametrosSalvos?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
|
||||||
catch (InvalidOperationException ex)
|
|
||||||
{
|
|
||||||
Variaveis.MostrarLog("[ucOperacaoParametros.BtnSalvar] " + ex);
|
|
||||||
FuncoesIHM.MostrarAlerta("Não foi possível salvar a operação", ex.Message, MessageBoxIcon.Warning);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Variaveis.MostrarLog("[ucOperacaoParametros.BtnSalvar][ERRO] " + ex);
|
|
||||||
FuncoesIHM.MostrarAlerta("Erro ao salvar parâmetros", "Não foi possível aplicar os parâmetros da operação. Consulte os logs para mais detalhes.", MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void BtnRedefinir_Click(object sender, EventArgs e)
|
private async void BtnRedefinir_Click(object sender, EventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,6 @@ namespace AgroBase.Forms.IHM
|
||||||
this.fldEntreEixos = new AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField();
|
this.fldEntreEixos = new AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField();
|
||||||
this.fldAnguloFrontal = new AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField();
|
this.fldAnguloFrontal = new AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField();
|
||||||
this.fldAnguloLateral = new AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField();
|
this.fldAnguloLateral = new AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField();
|
||||||
this.pnlReferenciaImu = new System.Windows.Forms.Panel();
|
|
||||||
this.lblOffsetImuRoll = new System.Windows.Forms.Label();
|
|
||||||
this.lblOffsetImuPitch = new System.Windows.Forms.Label();
|
|
||||||
this.btnReferenciarImu = new AgroBase.Forms.IHM.Controls.HmiSidebarButton();
|
|
||||||
this.pnlBateria = new AgroBase.Forms.IHM.Controls.HmiRoundedPanel();
|
this.pnlBateria = new AgroBase.Forms.IHM.Controls.HmiRoundedPanel();
|
||||||
this.bateriaLayout = new System.Windows.Forms.TableLayoutPanel();
|
this.bateriaLayout = new System.Windows.Forms.TableLayoutPanel();
|
||||||
this.lblBateria = new System.Windows.Forms.Label();
|
this.lblBateria = new System.Windows.Forms.Label();
|
||||||
|
|
@ -98,7 +94,6 @@ namespace AgroBase.Forms.IHM
|
||||||
this.rightLayout.SuspendLayout();
|
this.rightLayout.SuspendLayout();
|
||||||
this.pnlGeometria.SuspendLayout();
|
this.pnlGeometria.SuspendLayout();
|
||||||
this.geometriaLayout.SuspendLayout();
|
this.geometriaLayout.SuspendLayout();
|
||||||
this.pnlReferenciaImu.SuspendLayout();
|
|
||||||
this.pnlBateria.SuspendLayout();
|
this.pnlBateria.SuspendLayout();
|
||||||
this.bateriaLayout.SuspendLayout();
|
this.bateriaLayout.SuspendLayout();
|
||||||
this.pnlReservatorio.SuspendLayout();
|
this.pnlReservatorio.SuspendLayout();
|
||||||
|
|
@ -529,7 +524,6 @@ namespace AgroBase.Forms.IHM
|
||||||
this.geometriaLayout.Controls.Add(this.fldEntreEixos, 2, 1);
|
this.geometriaLayout.Controls.Add(this.fldEntreEixos, 2, 1);
|
||||||
this.geometriaLayout.Controls.Add(this.fldAnguloFrontal, 0, 2);
|
this.geometriaLayout.Controls.Add(this.fldAnguloFrontal, 0, 2);
|
||||||
this.geometriaLayout.Controls.Add(this.fldAnguloLateral, 1, 2);
|
this.geometriaLayout.Controls.Add(this.fldAnguloLateral, 1, 2);
|
||||||
this.geometriaLayout.Controls.Add(this.pnlReferenciaImu, 2, 2);
|
|
||||||
this.geometriaLayout.Dock = System.Windows.Forms.DockStyle.Fill;
|
this.geometriaLayout.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.geometriaLayout.Location = new System.Drawing.Point(10, 6);
|
this.geometriaLayout.Location = new System.Drawing.Point(10, 6);
|
||||||
this.geometriaLayout.Margin = new System.Windows.Forms.Padding(0);
|
this.geometriaLayout.Margin = new System.Windows.Forms.Padding(0);
|
||||||
|
|
@ -666,58 +660,6 @@ namespace AgroBase.Forms.IHM
|
||||||
this.fldAnguloLateral.Titulo = "Ângulo máx. lateral";
|
this.fldAnguloLateral.Titulo = "Ângulo máx. lateral";
|
||||||
this.fldAnguloLateral.Unidade = "°";
|
this.fldAnguloLateral.Unidade = "°";
|
||||||
//
|
//
|
||||||
// pnlReferenciaImu
|
|
||||||
//
|
|
||||||
this.pnlReferenciaImu.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(36)))), ((int)(((byte)(41)))));
|
|
||||||
this.pnlReferenciaImu.Controls.Add(this.lblOffsetImuRoll);
|
|
||||||
this.pnlReferenciaImu.Controls.Add(this.lblOffsetImuPitch);
|
|
||||||
this.pnlReferenciaImu.Controls.Add(this.btnReferenciarImu);
|
|
||||||
this.pnlReferenciaImu.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
||||||
this.pnlReferenciaImu.Location = new System.Drawing.Point(247, 84);
|
|
||||||
this.pnlReferenciaImu.Margin = new System.Windows.Forms.Padding(3, 2, 2, 2);
|
|
||||||
this.pnlReferenciaImu.Name = "pnlReferenciaImu";
|
|
||||||
this.pnlReferenciaImu.Padding = new System.Windows.Forms.Padding(4, 2, 4, 3);
|
|
||||||
this.pnlReferenciaImu.Size = new System.Drawing.Size(119, 54);
|
|
||||||
this.pnlReferenciaImu.TabIndex = 5;
|
|
||||||
//
|
|
||||||
// lblOffsetImuRoll
|
|
||||||
//
|
|
||||||
this.lblOffsetImuRoll.Font = new System.Drawing.Font("Segoe UI", 7F);
|
|
||||||
this.lblOffsetImuRoll.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(218)))), ((int)(((byte)(211)))));
|
|
||||||
this.lblOffsetImuRoll.Location = new System.Drawing.Point(5, 2);
|
|
||||||
this.lblOffsetImuRoll.Name = "lblOffsetImuRoll";
|
|
||||||
this.lblOffsetImuRoll.Size = new System.Drawing.Size(54, 15);
|
|
||||||
this.lblOffsetImuRoll.TabIndex = 0;
|
|
||||||
this.lblOffsetImuRoll.Text = "Roll: 0.00°";
|
|
||||||
this.lblOffsetImuRoll.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
//
|
|
||||||
// lblOffsetImuPitch
|
|
||||||
//
|
|
||||||
this.lblOffsetImuPitch.Font = new System.Drawing.Font("Segoe UI", 7F);
|
|
||||||
this.lblOffsetImuPitch.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(218)))), ((int)(((byte)(211)))));
|
|
||||||
this.lblOffsetImuPitch.Location = new System.Drawing.Point(59, 2);
|
|
||||||
this.lblOffsetImuPitch.Name = "lblOffsetImuPitch";
|
|
||||||
this.lblOffsetImuPitch.Size = new System.Drawing.Size(56, 15);
|
|
||||||
this.lblOffsetImuPitch.TabIndex = 1;
|
|
||||||
this.lblOffsetImuPitch.Text = "Pitch: 0.00°";
|
|
||||||
this.lblOffsetImuPitch.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
//
|
|
||||||
// btnReferenciarImu
|
|
||||||
//
|
|
||||||
this.btnReferenciarImu.AccentColor = System.Drawing.Color.FromArgb(((int)(((byte)(155)))), ((int)(((byte)(106)))), ((int)(((byte)(222)))));
|
|
||||||
this.btnReferenciarImu.BackColor = System.Drawing.Color.Transparent;
|
|
||||||
this.btnReferenciarImu.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(86)))), ((int)(((byte)(170)))));
|
|
||||||
this.btnReferenciarImu.Cursor = System.Windows.Forms.Cursors.Hand;
|
|
||||||
this.btnReferenciarImu.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(36)))), ((int)(((byte)(41)))));
|
|
||||||
this.btnReferenciarImu.IconText = "↻";
|
|
||||||
this.btnReferenciarImu.Location = new System.Drawing.Point(4, 18);
|
|
||||||
this.btnReferenciarImu.Margin = new System.Windows.Forms.Padding(0);
|
|
||||||
this.btnReferenciarImu.MinimumSize = new System.Drawing.Size(60, 34);
|
|
||||||
this.btnReferenciarImu.Name = "btnReferenciarImu";
|
|
||||||
this.btnReferenciarImu.Size = new System.Drawing.Size(111, 34);
|
|
||||||
this.btnReferenciarImu.TabIndex = 2;
|
|
||||||
this.btnReferenciarImu.Text = "ZERAR";
|
|
||||||
//
|
|
||||||
// pnlBateria
|
// pnlBateria
|
||||||
//
|
//
|
||||||
this.pnlBateria.AccentColor = System.Drawing.Color.FromArgb(((int)(((byte)(72)))), ((int)(((byte)(210)))), ((int)(((byte)(122)))));
|
this.pnlBateria.AccentColor = System.Drawing.Color.FromArgb(((int)(((byte)(72)))), ((int)(((byte)(210)))), ((int)(((byte)(122)))));
|
||||||
|
|
@ -1077,7 +1019,6 @@ namespace AgroBase.Forms.IHM
|
||||||
this.rightLayout.ResumeLayout(false);
|
this.rightLayout.ResumeLayout(false);
|
||||||
this.pnlGeometria.ResumeLayout(false);
|
this.pnlGeometria.ResumeLayout(false);
|
||||||
this.geometriaLayout.ResumeLayout(false);
|
this.geometriaLayout.ResumeLayout(false);
|
||||||
this.pnlReferenciaImu.ResumeLayout(false);
|
|
||||||
this.pnlBateria.ResumeLayout(false);
|
this.pnlBateria.ResumeLayout(false);
|
||||||
this.bateriaLayout.ResumeLayout(false);
|
this.bateriaLayout.ResumeLayout(false);
|
||||||
this.pnlReservatorio.ResumeLayout(false);
|
this.pnlReservatorio.ResumeLayout(false);
|
||||||
|
|
@ -1124,10 +1065,6 @@ namespace AgroBase.Forms.IHM
|
||||||
private AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField fldEntreEixos;
|
private AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField fldEntreEixos;
|
||||||
private AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField fldAnguloFrontal;
|
private AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField fldAnguloFrontal;
|
||||||
private AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField fldAnguloLateral;
|
private AgroBase.Forms.IHM.Operacao.Parametros.Controls.HmiCompactNumericField fldAnguloLateral;
|
||||||
private System.Windows.Forms.Panel pnlReferenciaImu;
|
|
||||||
private System.Windows.Forms.Label lblOffsetImuRoll;
|
|
||||||
private System.Windows.Forms.Label lblOffsetImuPitch;
|
|
||||||
private AgroBase.Forms.IHM.Controls.HmiSidebarButton btnReferenciarImu;
|
|
||||||
|
|
||||||
private AgroBase.Forms.IHM.Controls.HmiRoundedPanel pnlBateria;
|
private AgroBase.Forms.IHM.Controls.HmiRoundedPanel pnlBateria;
|
||||||
private System.Windows.Forms.TableLayoutPanel bateriaLayout;
|
private System.Windows.Forms.TableLayoutPanel bateriaLayout;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using AgroBase.Forms.IHM.Controls;
|
using AgroBase.Forms.IHM.Controls;
|
||||||
using AgroBase.Forms.IHM.Operacao.Parametros.Controls;
|
using AgroBase.Forms.IHM.Operacao.Parametros.Controls;
|
||||||
using AgroBase.Models;
|
using AgroBase.Models;
|
||||||
using AgroBase.Models.Components;
|
|
||||||
using AgroBase.Services.Operadores;
|
using AgroBase.Services.Operadores;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
@ -57,7 +56,6 @@ namespace AgroBase.Forms.IHM
|
||||||
public void AtualizarDadosTela()
|
public void AtualizarDadosTela()
|
||||||
{
|
{
|
||||||
lblRover.Text = $"ROVER {VariaveisEquipamento.Parametros.serial_number}\r\nConfiguração local";
|
lblRover.Text = $"ROVER {VariaveisEquipamento.Parametros.serial_number}\r\nConfiguração local";
|
||||||
AtualizarReferenciaImuTela();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -104,11 +102,6 @@ namespace AgroBase.Forms.IHM
|
||||||
await ExecutarSeguroAsync("Erro ao testar comunicação!", TestarComunicacaoAsync);
|
await ExecutarSeguroAsync("Erro ao testar comunicação!", TestarComunicacaoAsync);
|
||||||
};
|
};
|
||||||
|
|
||||||
btnReferenciarImu.Click += async delegate
|
|
||||||
{
|
|
||||||
await ExecutarSeguroAsync("Erro ao referenciar IMU!", ReferenciarImuAsync);
|
|
||||||
};
|
|
||||||
|
|
||||||
cameraFrontal.CameraChanged += cameraFrontal_CameraChanged;
|
cameraFrontal.CameraChanged += cameraFrontal_CameraChanged;
|
||||||
|
|
||||||
cameraErvas.CameraChanged += cameraErvas_CameraChanged;
|
cameraErvas.CameraChanged += cameraErvas_CameraChanged;
|
||||||
|
|
@ -186,94 +179,6 @@ namespace AgroBase.Forms.IHM
|
||||||
campo.DecimalPlaces = casas;
|
campo.DecimalPlaces = casas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void AtualizarReferenciaImuTela()
|
|
||||||
{
|
|
||||||
lblOffsetImuRoll.Text = $"L: {VariaveisEquipamento.Parametros.imu_roll_offset_deg:+0.00;-0.00;0.00}°";
|
|
||||||
lblOffsetImuPitch.Text = $"F: {VariaveisEquipamento.Parametros.imu_pitch_offset_deg:+0.00;-0.00;0.00}°";
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ReferenciarImuAsync()
|
|
||||||
{
|
|
||||||
var resposta = CustomDialog.ShowDialog(
|
|
||||||
"Referenciar IMU",
|
|
||||||
"Posicione o rover em uma superfície nivelada e mantenha-o imóvel.\r\n\r\n" +
|
|
||||||
"A referência atual de inclinação será recalculada.",
|
|
||||||
MessageBoxIcon.Information,
|
|
||||||
new Dictionary<(string, DialogResult?), Action>()
|
|
||||||
{
|
|
||||||
{ ("OK", DialogResult.OK), () => { } },
|
|
||||||
{ ("Cancelar", DialogResult.Cancel), () => { } },
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (resposta != DialogResult.OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
btnReferenciarImu.Enabled = false;
|
|
||||||
btnReferenciarImu.Text = "LENDO...";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const int quantidadeAmostras = 12;
|
|
||||||
const int intervaloMs = 100;
|
|
||||||
var rolls = new List<double>();
|
|
||||||
var pitches = new List<double>();
|
|
||||||
|
|
||||||
for (int i = 0; i < quantidadeAmostras; i++)
|
|
||||||
{
|
|
||||||
var imu = Variaveis.OperacaoEmAndamento?.Sensoriamento?.IMU;
|
|
||||||
|
|
||||||
if (imu != null && imu.valido && imu.IdadeSegundos <= 1.0)
|
|
||||||
{
|
|
||||||
rolls.Add(imu.roll);
|
|
||||||
pitches.Add(imu.pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(intervaloMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rolls.Count < 8)
|
|
||||||
throw new InvalidOperationException("Não há amostras válidas e recentes suficientes do IMU para realizar a referência.");
|
|
||||||
|
|
||||||
double mediaRoll = rolls.Average();
|
|
||||||
double mediaPitch = pitches.Average();
|
|
||||||
|
|
||||||
double desvioRoll = Math.Sqrt(rolls.Average(x => Math.Pow(x - mediaRoll, 2)));
|
|
||||||
double desvioPitch = Math.Sqrt(pitches.Average(x => Math.Pow(x - mediaPitch, 2)));
|
|
||||||
|
|
||||||
if (desvioRoll > 0.50 || desvioPitch > 0.50)
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
$"O rover parece estar em movimento. Estabilidade insuficiente (σ roll {desvioRoll:0.00}°, σ pitch {desvioPitch:0.00}°). Mantenha-o imóvel e tente novamente.");
|
|
||||||
|
|
||||||
double novoRoll = VariaveisEquipamento.Parametros.imu_roll_offset_deg + mediaRoll;
|
|
||||||
double novoPitch = VariaveisEquipamento.Parametros.imu_pitch_offset_deg + mediaPitch;
|
|
||||||
|
|
||||||
var parametros = VariaveisEquipamento.Parametros;
|
|
||||||
DefinirParametroGlobal(parametros, novoRoll, "imu_roll_offset_deg");
|
|
||||||
DefinirParametroGlobal(parametros, novoPitch, "imu_pitch_offset_deg");
|
|
||||||
|
|
||||||
if (!parametros.SalvarParametros())
|
|
||||||
throw new InvalidOperationException("Não foi possível salvar os novos offsets do IMU.");
|
|
||||||
|
|
||||||
parametros.AtualizarParametros();
|
|
||||||
HealthWorkerService.AtualizarDadosOperacao();
|
|
||||||
AtualizarReferenciaImuTela();
|
|
||||||
|
|
||||||
FuncoesIHM.MostrarAlerta(
|
|
||||||
"IMU referenciado",
|
|
||||||
$"Referência atualizada com sucesso.\r\n\r\n" +
|
|
||||||
$"Roll: {novoRoll:+0.00;-0.00;0.00}°\r\n" +
|
|
||||||
$"Pitch: {novoPitch:+0.00;-0.00;0.00}°",
|
|
||||||
MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
btnReferenciarImu.Text = "ZERAR";
|
|
||||||
btnReferenciarImu.Enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Câmeras
|
#region Câmeras
|
||||||
|
|
||||||
private async Task AtualizarCameras()
|
private async Task AtualizarCameras()
|
||||||
|
|
|
||||||
|
|
@ -3197,55 +3197,15 @@ namespace AgroBase.Models
|
||||||
|
|
||||||
private void ExecutarComandoMovDirGenerico(OperacaoComandoBaseModel controleBase, OperacaoModel op)
|
private void ExecutarComandoMovDirGenerico(OperacaoComandoBaseModel controleBase, OperacaoModel op)
|
||||||
{
|
{
|
||||||
if (op == null)
|
op.DefinirEmergencia(controleBase.Emergencia);
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ============================================================
|
|
||||||
* COMANDO OPERACIONAL DE PARADA
|
|
||||||
* ============================================================
|
|
||||||
*
|
|
||||||
* Pausa/Emergência só podem ser alteradas por um comando
|
|
||||||
* explicitamente destinado a isso.
|
|
||||||
*
|
|
||||||
* MOV/DIR nunca devem limpar esses estados.
|
|
||||||
*/
|
|
||||||
if (controleBase.Dispositivo == T_Code.Vzo)
|
|
||||||
{
|
|
||||||
op.DefinirEmergencia(controleBase.Emergencia);
|
|
||||||
|
|
||||||
if (op.Sensoriamento.Operacao.Emergencia)
|
|
||||||
return;
|
|
||||||
|
|
||||||
op.DefinirPausa(controleBase.Pausa);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Emergência sempre possui autoridade máxima.
|
|
||||||
*/
|
|
||||||
if (op.Sensoriamento.Operacao.Emergencia)
|
if (op.Sensoriamento.Operacao.Emergencia)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool controleManualAcionado =
|
op.DefinirPausa(controleBase.Pausa);
|
||||||
op.Parametros?.Controle?.ControleManualAcionado == true;
|
|
||||||
|
|
||||||
/*
|
if (op.Sensoriamento.Operacao.Pausa)
|
||||||
* ============================================================
|
|
||||||
* PAUSA OPERACIONAL
|
|
||||||
* ============================================================
|
|
||||||
*
|
|
||||||
* Pausa impede o AUTOMÁTICO, mas não impede uma intervenção
|
|
||||||
* manual explicitamente assumida pelo operador.
|
|
||||||
*
|
|
||||||
* Também permitimos comandos de soltura/neutro mesmo após
|
|
||||||
* retirar o controle manual, para nunca deixar comando preso.
|
|
||||||
*/
|
|
||||||
if (op.Sensoriamento.Operacao.Pausa && !controleManualAcionado && !controleBase.Solto)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (controleBase.Controle == null)
|
if (controleBase.Controle == null)
|
||||||
return;
|
return;
|
||||||
|
|
@ -3255,20 +3215,12 @@ namespace AgroBase.Models
|
||||||
if (cmdRover == null)
|
if (cmdRover == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (
|
if (cmdRover.Dispositivo == T_Code.Mov && (op.Parametros?.Controle?.MovimentoAutomatico ?? false) && op.Sensoriamento.Operacao.OperacaoIniciada)
|
||||||
cmdRover.Dispositivo == T_Code.Mov &&
|
|
||||||
(op.Parametros?.Controle?.MovimentoAutomatico ?? false) &&
|
|
||||||
op.Sensoriamento.Operacao.OperacaoIniciada
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (cmdRover.Dispositivo == T_Code.Dir && (op.Parametros?.Controle?.DirecionalAutomatico ?? false) && op.Sensoriamento.Operacao.OperacaoIniciada)
|
||||||
cmdRover.Dispositivo == T_Code.Dir &&
|
|
||||||
(op.Parametros?.Controle?.DirecionalAutomatico ?? false) &&
|
|
||||||
op.Sensoriamento.Operacao.OperacaoIniciada
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -3279,24 +3231,16 @@ namespace AgroBase.Models
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (controleBase.Controle.PercentualVelocidadeSP != null)
|
if (controleBase.Controle.PercentualVelocidadeSP != null)
|
||||||
controle.PercentualVelocidadeSP =
|
controle.PercentualVelocidadeSP = (double)controleBase .Controle.PercentualVelocidadeSP;
|
||||||
(double)controleBase.Controle.PercentualVelocidadeSP;
|
|
||||||
|
|
||||||
if (controleBase.Controle.AnguloSP != null)
|
if (controleBase.Controle.AnguloSP != null)
|
||||||
controle.Angulo =
|
controle.Angulo = (double)controleBase.Controle.AnguloSP;
|
||||||
(double)controleBase.Controle.AnguloSP;
|
|
||||||
|
|
||||||
if (controleBase.Controle.TipoMovimentoDirecional != null)
|
if (controleBase.Controle.TipoMovimentoDirecional != null)
|
||||||
{
|
op.DefinirTipoMovimentoControle((TipoMovimentoDirecional)controleBase.Controle.TipoMovimentoDirecional);
|
||||||
op.DefinirTipoMovimentoControle(
|
|
||||||
(TipoMovimentoDirecional)
|
|
||||||
controleBase.Controle.TipoMovimentoDirecional
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controleBase.Controle.EmFreio != null)
|
if (controleBase.Controle.EmFreio != null)
|
||||||
controle.EmFreio =
|
controle.EmFreio = (bool)controleBase.Controle.EmFreio;
|
||||||
(bool)controleBase.Controle.EmFreio;
|
|
||||||
|
|
||||||
switch (cmdRover.Dispositivo)
|
switch (cmdRover.Dispositivo)
|
||||||
{
|
{
|
||||||
|
|
@ -3304,8 +3248,7 @@ namespace AgroBase.Models
|
||||||
GeneralJoystick.ProcessarDadosControle(
|
GeneralJoystick.ProcessarDadosControle(
|
||||||
cmdRover.botaoJoy,
|
cmdRover.botaoJoy,
|
||||||
controleBase.Solto,
|
controleBase.Solto,
|
||||||
valorDesejado:
|
valorDesejado: controle.PercentualVelocidadeSP,
|
||||||
controle.PercentualVelocidadeSP,
|
|
||||||
ForcarComando: true
|
ForcarComando: true
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
@ -3314,8 +3257,7 @@ namespace AgroBase.Models
|
||||||
GeneralJoystick.ProcessarDadosControle(
|
GeneralJoystick.ProcessarDadosControle(
|
||||||
cmdRover.botaoJoy,
|
cmdRover.botaoJoy,
|
||||||
controleBase.Solto,
|
controleBase.Solto,
|
||||||
valorDesejado:
|
valorDesejado: controle.Angulo,
|
||||||
controle.Angulo,
|
|
||||||
ForcarComando: true
|
ForcarComando: true
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1123,7 +1123,7 @@ namespace AgroBase.Models
|
||||||
{ TipoMovimentoDirecional.Diagnostico, 25 },
|
{ TipoMovimentoDirecional.Diagnostico, 25 },
|
||||||
};
|
};
|
||||||
public static double AnguloInclinacaoRollMax { get; set; } = 22.0; // Lateral
|
public static double AnguloInclinacaoRollMax { get; set; } = 22.0; // Lateral
|
||||||
public static double AnguloInclinacaoPitchMax { get; set; } = 30.0; // Frontal
|
public static double AnguloInclinacaoPitchMax { get; set; } = 30.0; // Frontal 40 graus max
|
||||||
public static string VozAlerta { get; set; } = "Microsoft Maria Desktop";
|
public static string VozAlerta { get; set; } = "Microsoft Maria Desktop";
|
||||||
public static bool Pronto => Variaveis.OperacaoEmAndamento?.Parametros?.Controle != null;
|
public static bool Pronto => Variaveis.OperacaoEmAndamento?.Parametros?.Controle != null;
|
||||||
|
|
||||||
|
|
@ -1527,9 +1527,6 @@ namespace AgroBase.Models
|
||||||
public string can_gateway { get; set; }
|
public string can_gateway { get; set; }
|
||||||
public string can_submask { get; set; }
|
public string can_submask { get; set; }
|
||||||
|
|
||||||
public double imu_roll_offset_deg { get; set; } = 0.0; // Lateral
|
|
||||||
public double imu_pitch_offset_deg { get; set; } = 0.0; // Frontal
|
|
||||||
|
|
||||||
public void AtualizarParametros()
|
public void AtualizarParametros()
|
||||||
{
|
{
|
||||||
string config_path = Path.Combine(Variaveis.CaminhoSistema, Variaveis.CaminhoParametros, "config.json");
|
string config_path = Path.Combine(Variaveis.CaminhoSistema, Variaveis.CaminhoParametros, "config.json");
|
||||||
|
|
@ -1561,9 +1558,6 @@ namespace AgroBase.Models
|
||||||
camera_caminhho_id = par.camera_caminhho_id;
|
camera_caminhho_id = par.camera_caminhho_id;
|
||||||
camera_ervas_id = par.camera_ervas_id;
|
camera_ervas_id = par.camera_ervas_id;
|
||||||
|
|
||||||
imu_pitch_offset_deg = par.imu_pitch_offset_deg;
|
|
||||||
imu_roll_offset_deg = par.imu_roll_offset_deg;
|
|
||||||
|
|
||||||
Carregado = true;
|
Carregado = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -429,9 +429,7 @@ namespace AgroBase.Services.Operadores
|
||||||
("dir_angulo_direita_sinal", 1),
|
("dir_angulo_direita_sinal", 1),
|
||||||
("imu_dir_roll_min_aux", 6.0),
|
("imu_dir_roll_min_aux", 6.0),
|
||||||
("imu_dir_bias_attention_deg", 4.0),
|
("imu_dir_bias_attention_deg", 4.0),
|
||||||
("imu_dir_bias_risk_deg", 9.0),
|
("imu_dir_bias_risk_deg", 9.0)
|
||||||
("imu_roll_offset_deg", VariaveisEquipamento.Parametros.imu_roll_offset_deg),
|
|
||||||
("imu_pitch_offset_deg", VariaveisEquipamento.Parametros.imu_pitch_offset_deg)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"Carregado":true,"serial_number":"01","base_ip":"20.1.0.2","base_porta_caminho":5000,"base_porta_ervas":5002,"comunicacao_interface":"AG_Hallow","rover_ip":"20.1.0.10","rover_gateway":"20.1.0.1","rover_submask":"255.255.255.0","camera_caminhho_id":"14442C10C143E2D600","camera_ervas_id":["194430108133AC2F00"],"can_interface":"AG_Can","can_ip_pc":"192.168.0.5","can_ip_modulo":"192.168.0.7","can_porta":8235,"can_gateway":"192.168.0.1","can_submask":"255.255.255.0","imu_roll_offset_deg":0.0,"imu_pitch_offset_deg":0.0}
|
{"Carregado":true,"serial_number":"01","base_ip":"20.1.0.2","base_porta_caminho":5000,"base_porta_ervas":5002,"comunicacao_interface":"AG_Hallow","rover_ip":"20.1.0.10","rover_gateway":"20.1.0.1","rover_submask":"255.255.255.0","camera_caminhho_id":"14442C10C143E2D600","camera_ervas_id":["194430108133AC2F00"],"can_interface":"AG_Can","can_ip_pc":"192.168.0.5","can_ip_modulo":"192.168.0.7","can_porta":8235,"can_gateway":"192.168.0.1","can_submask":"255.255.255.0"}
|
||||||
|
|
@ -159,27 +159,14 @@ class ModuloDirecional(ModuloDiagnosticoBase):
|
||||||
condicoes = []
|
condicoes = []
|
||||||
|
|
||||||
if not conectado:
|
if not conectado:
|
||||||
condicoes = []
|
|
||||||
|
|
||||||
if comandar:
|
|
||||||
condicoes.append({
|
|
||||||
"valor": 0,
|
|
||||||
"severidade": 100,
|
|
||||||
"descricao": (
|
|
||||||
f"Driver direcional {endereco_str} desconectado "
|
|
||||||
"enquanto está em uso"
|
|
||||||
),
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"id": endereco_str,
|
"id": endereco_str,
|
||||||
"label": mod_id,
|
"label": mod_id,
|
||||||
"status": StatusModulo.DESCONECTADO.value,
|
"status": StatusModulo.DESCONECTADO.value,
|
||||||
"saude": 0,
|
"saude": 0,
|
||||||
"motivos": ["Desconectado"],
|
"motivos": ["Desconectado"],
|
||||||
"condicoes_operacionais": condicoes,
|
"condicoes_operacionais": [],
|
||||||
"em_uso": comandar,
|
"em_uso": comandar,
|
||||||
"referenciando": referenciando,
|
|
||||||
"componentes": {
|
"componentes": {
|
||||||
"conectividade": 0,
|
"conectividade": 0,
|
||||||
"feedback": 0,
|
"feedback": 0,
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
angulo_risk_factor=0.75,
|
angulo_risk_factor=0.75,
|
||||||
angulo_emergency_factor=1.20,
|
angulo_emergency_factor=1.20,
|
||||||
limites_refresh_s=1.0,
|
limites_refresh_s=1.0,
|
||||||
offsets_refresh_s=1.0,
|
|
||||||
|
|
||||||
# Taxas continuam independentes do ângulo máximo.
|
# Taxas continuam independentes do ângulo máximo.
|
||||||
roll_rate_attention_dps=25.0,
|
roll_rate_attention_dps=25.0,
|
||||||
|
|
@ -88,13 +87,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
self.limites_refresh_s = max(float(limites_refresh_s), 0.25)
|
self.limites_refresh_s = max(float(limites_refresh_s), 0.25)
|
||||||
self._ultimo_refresh_limites = 0.0
|
self._ultimo_refresh_limites = 0.0
|
||||||
|
|
||||||
# Offsets persistentes de atitude, definidos no equipamento.
|
|
||||||
# Convenção: valor corrigido = valor medido - offset.
|
|
||||||
self.offsets_refresh_s = max(float(offsets_refresh_s), 0.25)
|
|
||||||
self._ultimo_refresh_offsets = 0.0
|
|
||||||
self.roll_offset_deg = 0.0
|
|
||||||
self.pitch_offset_deg = 0.0
|
|
||||||
|
|
||||||
# Valores iniciais seguros. Serão substituídos pelos dados do Redis.
|
# Valores iniciais seguros. Serão substituídos pelos dados do Redis.
|
||||||
self.roll_max_deg = self.roll_max_default_deg
|
self.roll_max_deg = self.roll_max_default_deg
|
||||||
self.pitch_max_deg = self.pitch_max_default_deg
|
self.pitch_max_deg = self.pitch_max_default_deg
|
||||||
|
|
@ -162,10 +154,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
|
|
||||||
self.max_skew_imu_s = float(max_skew_imu_s)
|
self.max_skew_imu_s = float(max_skew_imu_s)
|
||||||
|
|
||||||
# Carrega configuração persistente antes da primeira atitude publicada.
|
|
||||||
self._atualizar_limites_equipamento(forcar=True)
|
|
||||||
self._atualizar_offsets_equipamento(forcar=True)
|
|
||||||
|
|
||||||
self.thread = threading.Thread(
|
self.thread = threading.Thread(
|
||||||
target=self.imu_task_loop,
|
target=self.imu_task_loop,
|
||||||
name="CameraIMUFinalWorker",
|
name="CameraIMUFinalWorker",
|
||||||
|
|
@ -801,77 +789,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
f"{self.pitch_emergency_deg:.1f}°)"
|
f"{self.pitch_emergency_deg:.1f}°)"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _validar_offset_angulo(self, valor, valor_atual):
|
|
||||||
"""Valida offset persistente de roll/pitch vindo do equipamento."""
|
|
||||||
try:
|
|
||||||
valor = float(valor)
|
|
||||||
if not math.isfinite(valor):
|
|
||||||
return float(valor_atual)
|
|
||||||
# Guard rail: offset mecânico maior que isso indica configuração errada.
|
|
||||||
if valor < -45.0 or valor > 45.0:
|
|
||||||
return float(valor_atual)
|
|
||||||
return valor
|
|
||||||
except Exception:
|
|
||||||
return float(valor_atual)
|
|
||||||
|
|
||||||
def _atualizar_offsets_equipamento(self, forcar=False):
|
|
||||||
"""
|
|
||||||
Atualiza os offsets persistentes da referência mecânica do rover.
|
|
||||||
|
|
||||||
Campos esperados em equipamento:
|
|
||||||
imu_roll_offset_deg
|
|
||||||
imu_pitch_offset_deg
|
|
||||||
|
|
||||||
Convenção:
|
|
||||||
roll_corrigido = roll_fundido - imu_roll_offset_deg
|
|
||||||
pitch_corrigido = pitch_fundido - imu_pitch_offset_deg
|
|
||||||
"""
|
|
||||||
agora = time.perf_counter()
|
|
||||||
if (
|
|
||||||
not forcar
|
|
||||||
and (agora - self._ultimo_refresh_offsets) < self.offsets_refresh_s
|
|
||||||
):
|
|
||||||
return
|
|
||||||
|
|
||||||
self._ultimo_refresh_offsets = agora
|
|
||||||
equipamento = ContextoGlobalRedis.get_equipamento() or {}
|
|
||||||
|
|
||||||
roll_anterior = self.roll_offset_deg
|
|
||||||
pitch_anterior = self.pitch_offset_deg
|
|
||||||
|
|
||||||
self.roll_offset_deg = self._validar_offset_angulo(
|
|
||||||
equipamento.get("imu_roll_offset_deg", 0.0),
|
|
||||||
self.roll_offset_deg,
|
|
||||||
)
|
|
||||||
self.pitch_offset_deg = self._validar_offset_angulo(
|
|
||||||
equipamento.get("imu_pitch_offset_deg", 0.0),
|
|
||||||
self.pitch_offset_deg,
|
|
||||||
)
|
|
||||||
|
|
||||||
mudou = (
|
|
||||||
abs(self.roll_offset_deg - roll_anterior) > 1e-6
|
|
||||||
or abs(self.pitch_offset_deg - pitch_anterior) > 1e-6
|
|
||||||
)
|
|
||||||
if mudou:
|
|
||||||
# Não deixa o EMA carregar a referência antiga depois de recalibrar.
|
|
||||||
self._resetar_filtro_fusao()
|
|
||||||
self.mostrar_log(
|
|
||||||
"Offsets IMU atualizados | "
|
|
||||||
f"roll={roll_anterior:.3f}°→{self.roll_offset_deg:.3f}° | "
|
|
||||||
f"pitch={pitch_anterior:.3f}°→{self.pitch_offset_deg:.3f}°"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _aplicar_offsets_fusao(self, fusao):
|
|
||||||
"""Aplica a referência mecânica depois da fusão e antes do filtro/risco."""
|
|
||||||
if fusao is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
corrigida = dict(fusao)
|
|
||||||
corrigida["roll"] = float(fusao.get("roll", 0.0)) - self.roll_offset_deg
|
|
||||||
corrigida["pitch"] = float(fusao.get("pitch", 0.0)) - self.pitch_offset_deg
|
|
||||||
# Offset constante não altera taxas angulares nem yaw.
|
|
||||||
return corrigida
|
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Fusão
|
# Fusão
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
@ -1467,16 +1384,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
"roll_max_configurado_deg": round(self.roll_max_deg, 3),
|
"roll_max_configurado_deg": round(self.roll_max_deg, 3),
|
||||||
"pitch_max_configurado_deg": round(self.pitch_max_deg, 3),
|
"pitch_max_configurado_deg": round(self.pitch_max_deg, 3),
|
||||||
|
|
||||||
# Referência mecânica persistente aplicada à atitude final.
|
|
||||||
"offsets_imu": {
|
|
||||||
"roll_deg": round(self.roll_offset_deg, 4),
|
|
||||||
"pitch_deg": round(self.pitch_offset_deg, 4),
|
|
||||||
"convencao": "corrigido=medido-offset",
|
|
||||||
"origem": "equipamento",
|
|
||||||
},
|
|
||||||
"roll_offset_deg": round(self.roll_offset_deg, 4),
|
|
||||||
"pitch_offset_deg": round(self.pitch_offset_deg, 4),
|
|
||||||
|
|
||||||
"roll_attention_deg": round(self.roll_attention_deg, 3),
|
"roll_attention_deg": round(self.roll_attention_deg, 3),
|
||||||
"roll_risk_deg": round(self.roll_risk_deg, 3),
|
"roll_risk_deg": round(self.roll_risk_deg, 3),
|
||||||
"roll_critical_deg": round(self.roll_critical_deg, 3),
|
"roll_critical_deg": round(self.roll_critical_deg, 3),
|
||||||
|
|
@ -1580,7 +1487,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
agora = time.time()
|
agora = time.time()
|
||||||
|
|
||||||
self._atualizar_limites_equipamento()
|
self._atualizar_limites_equipamento()
|
||||||
self._atualizar_offsets_equipamento()
|
|
||||||
|
|
||||||
fontes, ignoradas, desabilitadas = self._ler_fontes_imu()
|
fontes, ignoradas, desabilitadas = self._ler_fontes_imu()
|
||||||
|
|
||||||
|
|
@ -1614,11 +1520,6 @@ class CameraIMU(ModuloDiagnosticoBase):
|
||||||
|
|
||||||
fusao = self._fundir_fontes(fontes, sensores_agree=divergencia["sensors_agree"])
|
fusao = self._fundir_fontes(fontes, sensores_agree=divergencia["sensors_agree"])
|
||||||
|
|
||||||
# Corrige a atitude final pela referência mecânica persistente do rover.
|
|
||||||
# A divergência entre sensores continua sendo avaliada antes do offset,
|
|
||||||
# pois um offset global não deve mascarar desacordo entre IMUs.
|
|
||||||
fusao = self._aplicar_offsets_fusao(fusao)
|
|
||||||
|
|
||||||
# Atualiza o filtro antes de avaliar o risco.
|
# Atualiza o filtro antes de avaliar o risco.
|
||||||
atitude_filtrada = self._atualizar_filtro_fusao(fusao)
|
atitude_filtrada = self._atualizar_filtro_fusao(fusao)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -318,31 +318,13 @@ class ModuloMovimentacao(ModuloDiagnosticoBase):
|
||||||
)
|
)
|
||||||
|
|
||||||
if not conectado and estado_desconectado["nivel"] == "confirmado":
|
if not conectado and estado_desconectado["nivel"] == "confirmado":
|
||||||
condicoes_desconectado = []
|
|
||||||
|
|
||||||
if comandar:
|
|
||||||
condicoes_desconectado.append({
|
|
||||||
"label": "Conexão OID",
|
|
||||||
"valor": estado_desconectado["duracao_s"],
|
|
||||||
"severidade": 100,
|
|
||||||
"descricao": (
|
|
||||||
f"Driver de movimentação {mod_id} desconectado "
|
|
||||||
"enquanto está em uso"
|
|
||||||
),
|
|
||||||
"acoes": [
|
|
||||||
"Verificar comunicação CAN com o OID.",
|
|
||||||
"Verificar alimentação do driver.",
|
|
||||||
"Inspecionar conectores e cabeamento do motor.",
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"id": endereco_str,
|
"id": endereco_str,
|
||||||
"label": mod_id,
|
"label": mod_id,
|
||||||
"status": StatusModulo.DESCONECTADO.value,
|
"status": StatusModulo.DESCONECTADO.value,
|
||||||
"saude": 0,
|
"saude": 0,
|
||||||
"motivos": ["Desconectado"],
|
"motivos": ["Desconectado"],
|
||||||
"condicoes_operacionais": condicoes_desconectado,
|
"condicoes_operacionais": [],
|
||||||
"em_uso": comandar,
|
"em_uso": comandar,
|
||||||
"conectado_efetivo": False,
|
"conectado_efetivo": False,
|
||||||
"componentes": self._componentes_zero(),
|
"componentes": self._componentes_zero(),
|
||||||
|
|
|
||||||
|
|
@ -713,62 +713,36 @@ class ContextoGlobalRedis:
|
||||||
ultimo_publicado == cls._int(ultimo_esperado, -999999)
|
ultimo_publicado == cls._int(ultimo_esperado, -999999)
|
||||||
)
|
)
|
||||||
|
|
||||||
ack_mapa_exato = (
|
|
||||||
status_mapa == "aplicado"
|
|
||||||
and revisao_solicitada > 0
|
|
||||||
and health_rev == revisao_solicitada
|
|
||||||
and manager_rev == revisao_solicitada
|
|
||||||
and command_solicitado != ""
|
|
||||||
and health_cmd == command_solicitado
|
|
||||||
and manager_cmd == command_solicitado
|
|
||||||
and health_status == "aplicado"
|
|
||||||
and manager_status == "aplicado"
|
|
||||||
and qtd_esperada > 0
|
|
||||||
and qtd_publicada == qtd_esperada
|
|
||||||
and manager_qtd == qtd_esperada
|
|
||||||
and indices_extremos_ok
|
|
||||||
)
|
|
||||||
|
|
||||||
mapa_mpc_ok = (
|
mapa_mpc_ok = (
|
||||||
not requer_confirmacao_mapa_mpc
|
not requer_confirmacao_mapa_mpc
|
||||||
or (
|
or (
|
||||||
ack_mapa_exato
|
not mapa_barreira_critica
|
||||||
and mapa_confirmado_flag
|
and mapa_confirmado_flag
|
||||||
and not mapa_barreira_critica
|
and status_mapa == "aplicado"
|
||||||
|
and revisao_solicitada > 0
|
||||||
|
and health_rev == revisao_solicitada
|
||||||
|
and manager_rev == revisao_solicitada
|
||||||
|
and command_solicitado != ""
|
||||||
|
and health_cmd == command_solicitado
|
||||||
|
and manager_cmd == command_solicitado
|
||||||
|
and health_status == "aplicado"
|
||||||
|
and manager_status == "aplicado"
|
||||||
|
and qtd_esperada > 0
|
||||||
|
and qtd_publicada == qtd_esperada
|
||||||
|
and manager_qtd == qtd_esperada
|
||||||
|
and indices_extremos_ok
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if not mapa_mpc_ok:
|
if not mapa_mpc_ok:
|
||||||
motivos.append(
|
motivos.append(
|
||||||
"Mapa/MPC ainda não confirmado: "
|
"Mapa/MPC ainda não confirmado: "
|
||||||
f"confirmado={mapa_confirmado_flag}; "
|
f"rev solicitada/health/manager={revisao_solicitada}/{health_rev}/{manager_rev}; "
|
||||||
f"barreira={mapa_barreira_critica}; "
|
f"cmd solicitado/health/manager={command_solicitado}/{health_cmd}/{manager_cmd}; "
|
||||||
f"rev solicitada/health/manager="
|
f"pontos publicados/esperados/manager={qtd_publicada}/{qtd_esperada}/{manager_qtd}; "
|
||||||
f"{revisao_solicitada}/{health_rev}/{manager_rev}; "
|
|
||||||
f"cmd solicitado/health/manager="
|
|
||||||
f"{command_solicitado}/{health_cmd}/{manager_cmd}; "
|
|
||||||
f"pontos publicados/esperados/manager="
|
|
||||||
f"{qtd_publicada}/{qtd_esperada}/{manager_qtd}; "
|
|
||||||
f"indices publicado={primeiro_publicado}->{ultimo_publicado}, "
|
|
||||||
f"esperado={primeiro_esperado}->{ultimo_esperado}, "
|
|
||||||
f"ok={indices_extremos_ok}; "
|
|
||||||
f"status={status_mapa}/{health_status}/{manager_status}"
|
f"status={status_mapa}/{health_status}/{manager_status}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if ack_mapa_exato and not mapa_confirmado_flag:
|
|
||||||
mostrar_log(
|
|
||||||
"[MAPSYNC/INCONSISTENCIA] "
|
|
||||||
f"ACK exato confirmado, mas mapa_confirmado=false. "
|
|
||||||
f"rev={revisao_solicitada}; cmd={command_solicitado}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if ack_mapa_exato and mapa_barreira_critica:
|
|
||||||
mostrar_log(
|
|
||||||
"[MAPSYNC/INCONSISTENCIA] "
|
|
||||||
f"ACK exato confirmado, mas mapa_barreira_critica permanece ativa. "
|
|
||||||
f"rev={revisao_solicitada}; cmd={command_solicitado}"
|
|
||||||
)
|
|
||||||
|
|
||||||
detalhes_regras["mapa_mpc"] = {
|
detalhes_regras["mapa_mpc"] = {
|
||||||
"requer_confirmacao": requer_confirmacao_mapa_mpc,
|
"requer_confirmacao": requer_confirmacao_mapa_mpc,
|
||||||
"ok": mapa_mpc_ok,
|
"ok": mapa_mpc_ok,
|
||||||
|
|
|
||||||
|
|
@ -32,60 +32,34 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
|
||||||
get => _habilitado;
|
get => _habilitado;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_habilitado == value)
|
if (_habilitado != value)
|
||||||
return;
|
|
||||||
|
|
||||||
var r =
|
|
||||||
VariaveisControleOperacao.RoverEmFoco;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ao abandonar o manual, primeiro neutralizamos tudo
|
|
||||||
* enquanto o rover ainda reconhece autoridade manual.
|
|
||||||
*/
|
|
||||||
if (!value)
|
|
||||||
{
|
{
|
||||||
LimparTeclas();
|
_habilitado = value;
|
||||||
EnviarNeutros();
|
OnPropertyChanged(nameof(StatusTexto));
|
||||||
}
|
OnPropertyChanged(nameof(TextoAjuda));
|
||||||
|
OnPropertyChanged(nameof(StatusBrush));
|
||||||
|
|
||||||
_habilitado = value;
|
var r = VariaveisControleOperacao.RoverEmFoco;
|
||||||
|
if (r != null)
|
||||||
|
{
|
||||||
|
r.Controle.ControleManualAcionado = value;
|
||||||
|
r.Controle.MovimentoAutomatico = value ? false : r.ControleAutomatico;
|
||||||
|
r.Controle.DirecionalAutomatico = value ? false : r.ControleAutomatico;
|
||||||
|
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
|
||||||
|
{
|
||||||
|
Controle = VariaveisControleOperacao.RoverEmFoco?.Controle
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
OnPropertyChanged(nameof(StatusTexto));
|
if (!value)
|
||||||
OnPropertyChanged(nameof(TextoAjuda));
|
{
|
||||||
OnPropertyChanged(nameof(StatusBrush));
|
LimparTeclas();
|
||||||
|
EnviarNeutros();
|
||||||
if (r != null)
|
}
|
||||||
{
|
else
|
||||||
r.Controle.ControleManualAcionado =
|
{
|
||||||
value;
|
VariaveisControleOperacao.EnviarComandoIniciarUDP(VariaveisControleOperacao.RoverEmFoco.IP, true);
|
||||||
|
}
|
||||||
r.Controle.MovimentoAutomatico =
|
|
||||||
value
|
|
||||||
? false
|
|
||||||
: r.ControleAutomatico;
|
|
||||||
|
|
||||||
r.Controle.DirecionalAutomatico =
|
|
||||||
value
|
|
||||||
? false
|
|
||||||
: r.ControleAutomatico;
|
|
||||||
|
|
||||||
VariaveisControleOperacao
|
|
||||||
.EnviarParametrosOperacao(
|
|
||||||
new AgroBase.Models.Operacoes
|
|
||||||
.OperacaoParametrosModel()
|
|
||||||
{
|
|
||||||
Controle = r.Controle
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value && r != null)
|
|
||||||
{
|
|
||||||
VariaveisControleOperacao
|
|
||||||
.EnviarComandoIniciarUDP(
|
|
||||||
r.IP,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -653,27 +653,6 @@ namespace OperationControl.ViewModels
|
||||||
return "A operação não foi liberada pelo rover.";
|
return "A operação não foi liberada pelo rover.";
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdicionarEventoTrajetoria(
|
|
||||||
string descricao,
|
|
||||||
int prioridade = 700,
|
|
||||||
StatusModulo status = StatusModulo.Alerta)
|
|
||||||
{
|
|
||||||
descricao = NormalizarTexto(descricao);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(descricao))
|
|
||||||
return;
|
|
||||||
|
|
||||||
eventos.Add(new MotivoTopBarModel
|
|
||||||
{
|
|
||||||
Prioridade = prioridade,
|
|
||||||
Fonte = "Trajetoria",
|
|
||||||
Titulo = "TRAJETÓRIA BLOQUEADA",
|
|
||||||
Descricao = descricao,
|
|
||||||
StatusVisual = status,
|
|
||||||
Modulo = T_Code.Trj
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 0) Comunicação
|
// 0) Comunicação
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -773,22 +752,22 @@ namespace OperationControl.ViewModels
|
||||||
// Parâmetro obrigatório ausente
|
// Parâmetro obrigatório ausente
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
//if (
|
if (
|
||||||
// obj.Operacao != null &&
|
obj.Operacao != null &&
|
||||||
// !obj.Operacao.Liberada &&
|
!obj.Operacao.Liberada &&
|
||||||
// obj.Operacao.Pausa != true &&
|
obj.Operacao.Pausa != true &&
|
||||||
// obj.Operacao.Emergencia != true
|
obj.Operacao.Emergencia != true
|
||||||
//)
|
)
|
||||||
//{
|
{
|
||||||
// eventos.Add(new MotivoTopBarModel
|
eventos.Add(new MotivoTopBarModel
|
||||||
// {
|
{
|
||||||
// Prioridade = 850,
|
Prioridade = 850,
|
||||||
// Fonte = "Operacao",
|
Fonte = "Operacao",
|
||||||
// Titulo = "OPERAÇÃO BLOQUEADA",
|
Titulo = "OPERAÇÃO BLOQUEADA",
|
||||||
// Descricao = MotivoOperacaoAtual(),
|
Descricao = MotivoOperacaoAtual(),
|
||||||
// StatusVisual = StatusModulo.Falha
|
StatusVisual = StatusModulo.Falha
|
||||||
// });
|
});
|
||||||
//}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 5) Controle
|
// 5) Controle
|
||||||
|
|
@ -830,42 +809,14 @@ namespace OperationControl.ViewModels
|
||||||
|
|
||||||
foreach (var motivo in motivosTrajetoria)
|
foreach (var motivo in motivosTrajetoria)
|
||||||
{
|
{
|
||||||
AdicionarEventoTrajetoria(motivo);
|
eventos.Add(new MotivoTopBarModel
|
||||||
}
|
|
||||||
|
|
||||||
var impedimentoOperacao = obj.Operacao?.ImpedimentoErro ?? "";
|
|
||||||
|
|
||||||
var linhasImpedimento =
|
|
||||||
impedimentoOperacao
|
|
||||||
.Split(
|
|
||||||
new[] { "\r\n", "\n", "\r" },
|
|
||||||
StringSplitOptions.RemoveEmptyEntries)
|
|
||||||
.Select(x => x.Trim())
|
|
||||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
|
||||||
.Distinct()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var linha in linhasImpedimento)
|
|
||||||
{
|
|
||||||
bool relacionadoTrajetoria =
|
|
||||||
linha.Contains(
|
|
||||||
"Mapa/MPC",
|
|
||||||
StringComparison.OrdinalIgnoreCase)
|
|
||||||
||
|
|
||||||
linha.Contains(
|
|
||||||
"trajetória",
|
|
||||||
StringComparison.OrdinalIgnoreCase)
|
|
||||||
||
|
|
||||||
linha.Contains(
|
|
||||||
"trajetoria",
|
|
||||||
StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
if (relacionadoTrajetoria)
|
|
||||||
{
|
{
|
||||||
AdicionarEventoTrajetoria(
|
Prioridade = 700,
|
||||||
linha,
|
Fonte = "Trajetoria",
|
||||||
prioridade: 710);
|
Titulo = "TRAJETÓRIA BLOQUEADA",
|
||||||
}
|
Descricao = motivo,
|
||||||
|
StatusVisual = StatusModulo.Alerta
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue