ajustes no alarme de comando leitura do mov, inversao do heading no operation contro, ajuste de lever arm direto na camera frontal

This commit is contained in:
Diego Freitas 2026-08-11 18:53:34 -03:00
parent 2406d4c6fe
commit a7f04f4016
6 changed files with 235 additions and 38 deletions

View File

@ -22,19 +22,12 @@ namespace AgroBase.Models.Modules
return Variaveis.OperacaoEmAndamento.DispMvd?.Dados?.Modulos?.FirstOrDefault(x => x.MovMotor._EnderecoCAN_Tx == _EnderecoCAN_Tx)?.Modulo_ID ?? "";
}
}
public bool LeituraLigado
{
get
{
return Leitura?.CorrenteMotor?.valor != 0;
}
}
public double LeituraRPM { get; set; } = 0;
public bool ComandoLigado
{
get
{
return RPM_SP > 0;
return Math.Abs(RPM_SP) > 0;
}
}
//public bool Freio { get; set; } = false;
@ -67,32 +60,144 @@ namespace AgroBase.Models.Modules
public int CorrenteTorqueMaximo { get; set; } = 40;
public int CorrenteFreio { get; set; } = 5;
public double OffsetLeitura { get; set; } = 1.0;
private const double IDADE_MAX_TELEMETRIA_S = 3.0;
// Valores iniciais conservadores.
// Ajustar depois conforme o ruído real observado nos logs.
private const double CORRENTE_MOTOR_ATIVA_A = 0.15;
private const double CORRENTE_BARRAMENTO_ATIVA_A = 0.10;
private const double POTENCIA_ATIVA_W = 3.0;
private const double CICLO_ATIVO = 1.0;
private static bool DadoFresco(CanCommandFreqModel<double> dado, DateTime agora)
{
return dado != null
&& dado.lidoEm != DateTime.MinValue
&& (agora - dado.lidoEm).TotalSeconds >= 0
&& (agora - dado.lidoEm).TotalSeconds <= IDADE_MAX_TELEMETRIA_S;
}
private bool HaEvidenciaAtuacao(DateTime agora)
{
var leitura = Leitura;
if (leitura == null)
return false;
return
(DadoFresco(leitura.CorrenteMotor, agora) &&
Math.Abs(leitura.CorrenteMotor.valor) >= CORRENTE_MOTOR_ATIVA_A)
||
(DadoFresco(leitura.CorrenteBarramento, agora) &&
Math.Abs(leitura.CorrenteBarramento.valor) >= CORRENTE_BARRAMENTO_ATIVA_A)
||
(DadoFresco(leitura.Potencia, agora) &&
Math.Abs(leitura.Potencia.valor) >= POTENCIA_ATIVA_W)
||
(DadoFresco(leitura.CicloTrabalho, agora) &&
Math.Abs(leitura.CicloTrabalho.valor) >= CICLO_ATIVO);
}
private bool HaEvidenciaSuficienteDeAusencia(DateTime agora)
{
var leitura = Leitura;
if (leitura == null)
return false;
int sinaisFrescos = 0;
bool algumIndicaAtuacao = false;
if (DadoFresco(leitura.CorrenteMotor, agora))
{
sinaisFrescos++;
if (Math.Abs(leitura.CorrenteMotor.valor) >= CORRENTE_MOTOR_ATIVA_A)
algumIndicaAtuacao = true;
}
if (DadoFresco(leitura.CorrenteBarramento, agora))
{
sinaisFrescos++;
if (Math.Abs(leitura.CorrenteBarramento.valor) >= CORRENTE_BARRAMENTO_ATIVA_A)
algumIndicaAtuacao = true;
}
if (DadoFresco(leitura.Potencia, agora))
{
sinaisFrescos++;
if (Math.Abs(leitura.Potencia.valor) >= POTENCIA_ATIVA_W)
algumIndicaAtuacao = true;
}
if (DadoFresco(leitura.CicloTrabalho, agora))
{
sinaisFrescos++;
if (Math.Abs(leitura.CicloTrabalho.valor) >= CICLO_ATIVO)
algumIndicaAtuacao = true;
}
// Só afirma ausência quando pelo menos dois sinais atuais
// concordam que não existe atuação.
return sinaisFrescos >= 2 && !algumIndicaAtuacao;
}
public bool LeituraLigado
{
get
{
return HaEvidenciaAtuacao(DateTime.Now);
}
}
private DateTime UltimoAlarmeComando { get; set; } = DateTime.MinValue;
public bool AlarmeComando
{
get
{
bool _alarme = ComandoLigado && !LeituraLigado;
DateTime agora = DateTime.Now;
if (_alarme)
{
if (UltimoAlarmeComando == DateTime.MinValue)
{
UltimoAlarmeComando = DateTime.Now;
}
if (UltimoAlarmeComando.AddSeconds(5) < DateTime.Now)
{
return true;
}
}
else
if (!ComandoLigado)
{
UltimoAlarmeComando = DateTime.MinValue;
return false;
}
if (HaEvidenciaAtuacao(agora))
{
UltimoAlarmeComando = DateTime.MinValue;
return false;
}
bool ausenciaConfirmada = HaEvidenciaSuficienteDeAusencia(agora);
if (!ausenciaConfirmada)
{
// Telemetria insuficiente ou velha:
// situação inconclusiva, tratada pela saúde de comunicação.
UltimoAlarmeComando = DateTime.MinValue;
return false;
}
if (UltimoAlarmeComando == DateTime.MinValue)
{
UltimoAlarmeComando = agora;
return false;
}
return (agora - UltimoAlarmeComando).TotalSeconds >= 5.0;
}
}

View File

@ -91,6 +91,7 @@ namespace AgroBase.Services
private static readonly ConcurrentDictionary<string, SemaphoreSlim> _portIoLocks = new ConcurrentDictionary<string, SemaphoreSlim>(StringComparer.OrdinalIgnoreCase);
private static readonly ConcurrentDictionary<string, int> _missingPortConfirmations = new ConcurrentDictionary<string, int>(StringComparer.OrdinalIgnoreCase);
private static readonly ConcurrentDictionary<T_Code, int> _usbDisconnectedConfirmations = new ConcurrentDictionary<T_Code, int>();
public static int ConfirmacoesPortaAusente { get; set; } = 2;
private static CancellationTokenSource _lifetimeCts = new CancellationTokenSource();
@ -893,19 +894,35 @@ namespace AgroBase.Services
bool connected = health.status != StatusModulo.Desconectado;
if (mapped == null && connected)
if (connected)
{
_usbDisconnectedConfirmations.TryRemove(
camera.dispositivo,
out _
);
if (mapped == null)
{
AdicionarOuAtualizarDispositivoMapeado(
new DispositivoDetalhesModel
{
Dispositivo =
camera.dispositivo,
Dispositivo = camera.dispositivo,
Endereco = "USB",
Versao = camera.versao
}
);
}
else if (mapped != null && !connected)
continue;
}
int confirmacoes = _usbDisconnectedConfirmations.AddOrUpdate(
camera.dispositivo,
1,
(_, atual) => atual + 1
);
if (mapped != null && confirmacoes >= 2)
{
RemoverDispositivoMapeado(mapped);
}

View File

@ -131,8 +131,8 @@ namespace OperationControl.Controls
// Derivados
public double MaxAbsAngle => Math.Max(Math.Abs(RollDeg), Math.Abs(PitchDeg));
public string RollTexto => $"FRT {FormatSignedDeg(RollDeg)}";
public string PitchTexto => $"LAT {FormatSignedDeg(PitchDeg)}";
public string RollTexto => $"LAT {FormatSignedDeg(RollDeg)}";
public string PitchTexto => $"FRT {FormatSignedDeg(PitchDeg)}";
private static string FormatSignedDeg(double value)
{

View File

@ -1048,8 +1048,8 @@ namespace OperationControl.ViewModels
// ATTITUDE
var IMU = _viewOperacaoCenter.Monitoramento.Attitude;
if (obj?.Imu?.InclinacaoLateral != null) IMU.PitchDeg = (double)obj.Imu.InclinacaoLateral;
if (obj?.Imu?.InclinacaoFrontal != null) IMU.RollDeg = (double)obj.Imu.InclinacaoFrontal;
if (obj?.Imu?.InclinacaoLateral != null) IMU.RollDeg = (double)obj.Imu.InclinacaoLateral;
if (obj?.Imu?.InclinacaoFrontal != null) IMU.PitchDeg = (double)obj.Imu.InclinacaoFrontal;
IMU.LateralError = erroLateral;

View File

@ -47,6 +47,60 @@
<Border Background="Black" Visibility="{Binding CameraFrontalSemSinal, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock Text="SEM SINAL" Foreground="Gray" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<!-- Ajuste lateral positivo: desloca o rover para a esquerda -->
<Button x:Name="btnLeverArmEsquerda"
Panel.ZIndex="10"
Content="◀ +5 cm"
Width="90"
Height="30"
Margin="12"
Padding="10,4"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
FontSize="15"
FontWeight="SemiBold"
Foreground="White"
Background="#CC2E7D32"
BorderBrush="#8BC34A"
BorderThickness="2"
Cursor="Hand"
ToolTip="Aumentar o lever arm lateral em 5 cm"
Click="btnLeverArmEsquerda_Click"
/>
<TextBlock
x:Name="lblLeverArmLateral"
Text="Lever Arm Lateral: 00 cm"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Foreground="White"
Margin="12"
Padding="10,4"
/>
<!-- Ajuste lateral negativo: desloca o rover para a direita -->
<Button x:Name="btnLeverArmDireita"
Panel.ZIndex="10"
Content="-5 cm ▶"
Width="90"
Height="30"
Margin="12"
Padding="10,4"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
FontSize="15"
FontWeight="SemiBold"
Foreground="White"
Background="#CCB3261E"
BorderBrush="#EF5350"
BorderThickness="2"
Cursor="Hand"
ToolTip="Diminuir o lever arm lateral em 5 cm"
Click="btnLeverArmDireita_Click"
/>
</Grid>
</Grid>
</Border>

View File

@ -69,6 +69,26 @@ namespace OperationControl.Views.Operacao.Monitoramento
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, false, tipo);
}
private void AtualizarLeverArm(double valorCm)
{
double la_frontal = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Gnss?.LeverArmFrontal ?? 0;
double la_lateral = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Gnss?.LeverArmLateral ?? 0;
double novo = la_lateral + valorCm;
VariaveisControleOperacao.EnviarComandoLeverArm(lateral: novo, frontal: la_frontal);
lblLeverArmLateral.Text = $"Lever Arm Lateral: {novo} cm";
}
private void btnLeverArmEsquerda_Click(object sender, System.Windows.RoutedEventArgs e)
{
AtualizarLeverArm(+5);
}
private void btnLeverArmDireita_Click(object sender, System.Windows.RoutedEventArgs e)
{
AtualizarLeverArm(-5);
}
#endregion
#region CAMERA ERVAS
@ -98,5 +118,6 @@ namespace OperationControl.Views.Operacao.Monitoramento
#endregion
}
}