ajustes fps camera, imu redundante e snapshot operacao

This commit is contained in:
Diego Freitas 2026-08-11 07:22:22 -03:00
parent f5645ce227
commit 2406d4c6fe
5 changed files with 71 additions and 29 deletions

View File

@ -4061,7 +4061,7 @@ namespace AgroBase.Models
saude_geral < 80.0 ? StatusModulo.Alerta :
StatusModulo.Operante;
op.SubstituirOperacaoSnapshot(this, operacaoAtualizada);
op.SubstituirOperacaoSnapshot(op.Sensoriamento, operacaoAtualizada);
if (statusMudou)
{
@ -5308,7 +5308,8 @@ namespace AgroBase.Models
Finalizando = origem.Finalizando;
DataInicio = origem.DataInicio;
DataFim = origem.DataFim;
StatusOperacaoAnterior = origem.StatusOperacaoAnterior;
//StatusOperacaoAtual = origem.StatusOperacaoAtual;
//StatusOperacaoAnterior = origem.StatusOperacaoAnterior;
ModsCalibragem =
origem.ModsCalibragem?
@ -5350,7 +5351,7 @@ namespace AgroBase.Models
ParametrosMandatorios = new List<OperacaoParametrosMandatoriosModel>(ParametrosMandatorios ?? new List<OperacaoParametrosMandatoriosModel>()),
DispositivosMapeados = new List<DispositivoDetalhesModel>(DispositivosMapeados ?? new List<DispositivoDetalhesModel>()),
ModsCalibragem = new Dictionary<T_Code, Dictionary<string, bool>>(ModsCalibragem ?? new Dictionary<T_Code, Dictionary<string, bool>>()),
ModsCalibragemView = new Dictionary<string, Dictionary<string, bool>>(ModsCalibragemView),
ModsCalibragemView = new Dictionary<string, Dictionary<string, bool>>(ModsCalibragemView ?? new Dictionary<string, Dictionary<string, bool>>()),
};
}

View File

@ -2269,8 +2269,8 @@ namespace AgroBase.Models
{
return numbers.GroupBy(n => n)
.OrderByDescending(g => g.Count())
.First()
.Key;
.FirstOrDefault()?
.Key ?? double.NaN;
}
public static double CalcularTemperatura(double leitura, double offset = 0.0)

View File

@ -30,7 +30,7 @@ def main():
T_Code.Sen: ModuloSensoriamento(),
T_Code.Atu: ModuloAtuador(),
#T_Code.Lra: ModuloLoRa(),
T_Code.Imu: CameraIMU(modulos_imu=[T_Code.Snr]),
T_Code.Imu: CameraIMU(modulos_imu=[T_Code.Snr, T_Code.Cam], max_disagreement_deg=4.0, max_skew_imu_s=0.12),
T_Code.Npc: ModuloPC(),
T_Code.Lvx: ModuloLivox(),
T_Code.Ipb: ModuloIPBribge(),

View File

@ -61,6 +61,8 @@ class CameraIMU(ModuloDiagnosticoBase):
filtro_alpha=0.35,
historico_len=100,
modulos_imu=None,
max_skew_imu_s=0.12
):
self.freq = float(freq)
self.publish_hz = float(publish_hz)
@ -150,6 +152,8 @@ class CameraIMU(ModuloDiagnosticoBase):
self._assinatura_fontes_anterior = None
self.max_skew_imu_s = float(max_skew_imu_s)
self.thread = threading.Thread(
target=self.imu_task_loop,
name="CameraIMUFinalWorker",
@ -904,6 +908,7 @@ class CameraIMU(ModuloDiagnosticoBase):
1.0,
),
"fonte_principal": fonte_principal["mx_id"],
"fonte_principal_t_code": fonte_principal.get("t_code"),
"single_source": False,
"estrategia_fusao": "weighted_agreement",
}
@ -917,11 +922,9 @@ class CameraIMU(ModuloDiagnosticoBase):
"roll_rate_dps": fonte_principal["roll_rate_dps"],
"pitch_rate_dps": fonte_principal["pitch_rate_dps"],
"yaw_rate_dps": fonte_principal["yaw_rate_dps"],
"confidence": min(
float(fonte_principal["confidence"]),
1.0,
),
"confidence": min(float(fonte_principal["confidence"]), 1.0),
"fonte_principal": fonte_principal["mx_id"],
"fonte_principal_t_code": fonte_principal.get("t_code"),
"fonte_roll": fonte_principal["mx_id"],
"fonte_pitch": fonte_principal["mx_id"],
"fonte_roll_rate": fonte_principal["mx_id"],
@ -1011,6 +1014,39 @@ class CameraIMU(ModuloDiagnosticoBase):
"""
self._filtro_fusao_inicializado = False
def _filtrar_fontes_dessincronizadas(self, fontes):
if len(fontes) < 2:
return fontes, []
mais_recente = min(
fontes,
key=lambda f: f.get("idade_s", 999.0)
)
idade_referencia = mais_recente.get("idade_s", 999.0)
sincronizadas = []
dessincronizadas = []
for fonte in fontes:
skew_s = abs(
fonte.get("idade_s", 999.0) - idade_referencia
)
if skew_s <= self.max_skew_imu_s:
sincronizadas.append(fonte)
else:
fonte = dict(fonte)
fonte["confiavel"] = False
fonte["confidence"] = 0.0
fonte["motivos"] = list(fonte.get("motivos", []))
fonte["motivos"].append(
f"imu_dessincronizada_{skew_s:.3f}s"
)
dessincronizadas.append(fonte)
return sincronizadas, dessincronizadas
# ============================================================
# Risco e ação sugerida
# ============================================================
@ -1454,6 +1490,9 @@ class CameraIMU(ModuloDiagnosticoBase):
fontes, ignoradas, desabilitadas = self._ler_fontes_imu()
fontes, dessincronizadas = (self._filtrar_fontes_dessincronizadas(fontes))
ignoradas.extend(dessincronizadas)
modulos_validos = {
f.get("t_code")
for f in fontes

View File

@ -861,28 +861,30 @@ class CameraManager:
self._ultima_saude_ts = time.time()
try:
# Mantém a referência estável durante leitura/publicação da saúde.
# fechar_camera_manager aguarda esta seção curta terminar.
# O lock protege somente a identidade da sessão da câmera.
with self._vida_lock:
camera_atual = self.camera
generation = self._camera_generation
if camera_atual is not None:
if pipeline_ia is None:
pipeline_ia = self._avaliar_saude_pipeline_ia()
camera_atual.atualizar_saude(pipeline_ia=pipeline_ia)
if camera_atual is not None:
if pipeline_ia is None:
pipeline_ia = self._avaliar_saude_pipeline_ia()
elif self.mx_id is not None:
from camera_worker.manager import definir_saude_camera
definir_saude_camera(
self.mx_id,
StatusModulo.DESCONECTADO,
0,
["desconectado"],
False,
{},
disp=T_Code.Cam,
conectado=False,
)
camera_atual.atualizar_saude(pipeline_ia=pipeline_ia)
elif self.mx_id is not None:
from camera_worker.manager import definir_saude_camera
definir_saude_camera(
self.mx_id,
StatusModulo.DESCONECTADO,
0,
["desconectado"],
False,
{},
disp=T_Code.Cam,
conectado=False,
)
except Exception as e:
self.mostrar_log(f"[saude] erro: {e}")