ajuste regras do IMU, fps da camera, desligamento dos bicos ao desligar pulverizador automatico, atualizado autonomia de herbicida
This commit is contained in:
parent
632f672ce1
commit
809c0412e3
|
|
@ -763,6 +763,11 @@ namespace AgroBase.Forms.Operacoes
|
|||
private void chbPulverizador_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico = ((CheckBox)sender).Checked;
|
||||
|
||||
if (!Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico && Variaveis.OperacaoEmAndamento.Controle.Bicos.Any(x => x.ComandoAtuar))
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Controle.Bicos.ForEach(b => b.ComandoAtuar = false);
|
||||
}
|
||||
}
|
||||
|
||||
private void chbSonarAtivado_CheckedChanged(object sender, EventArgs e)
|
||||
|
|
|
|||
|
|
@ -593,6 +593,7 @@ namespace AgroBase.Models.Modules
|
|||
Sensor_ID_Num = 11,
|
||||
ComandoAtuar = false,
|
||||
PressaoSP = 100,
|
||||
PotenciaSP = 100,
|
||||
Componente = S_Code.sBMB,
|
||||
Comandar = true,
|
||||
Mandatorio = true,
|
||||
|
|
|
|||
|
|
@ -200,6 +200,12 @@ namespace AgroBase.Models
|
|||
{
|
||||
CorredorAtual?.AtualizarDados();
|
||||
|
||||
//AtualizarDadosAutonomiaCorredor(idxCorredor: idxNovoCorredor);
|
||||
}
|
||||
|
||||
bool mudouCorredor = (CorredorAtual?.Idx ?? -1) != idxNovoCorredor;
|
||||
if (mudouCorredor || !AutonomiaCorredor.Liberado)
|
||||
{
|
||||
AtualizarDadosAutonomiaCorredor(idxCorredor: idxNovoCorredor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ namespace AgroBase.Services
|
|||
public static async Task ConfigurarModulo()
|
||||
{
|
||||
Variaveis.MostrarLog($"[GPSService.ConfigurarModulo] Iniciando configuração do módulo GPS...");
|
||||
await ConfigurarModuloRover(comprimento_antena: 130);
|
||||
await ConfigurarModuloRover(comprimento_antena: 100);
|
||||
}
|
||||
|
||||
private static async Task ConfigurarModuloRover(string porta_usb = "com3", string porta_entrada = "com2", int comprimento_antena = 100, int tolerancia_antena = 5)
|
||||
|
|
|
|||
|
|
@ -377,18 +377,40 @@ namespace AgroBase.Services
|
|||
|
||||
private double CalcularLPorMetroReferencia(double velocidadeAtual_m_s)
|
||||
{
|
||||
// 1. Histórico real já consolidado
|
||||
if (LPorMetroHistorico > 0)
|
||||
return LPorMetroHistorico;
|
||||
|
||||
// 2. Janela atual real
|
||||
if (LPorMetro > 0)
|
||||
return LPorMetro;
|
||||
|
||||
double velocidade_m_min = velocidadeAtual_m_s * 60.0;
|
||||
// 3. Pré-cálculo enquanto o robô ainda está parado
|
||||
double velocidadeReferencia_m_s = velocidadeAtual_m_s;
|
||||
|
||||
if (velocidade_m_min > 0.1 && LPorMinutoEstimadoBicos > 0)
|
||||
return LPorMinutoEstimadoBicos / velocidade_m_min;
|
||||
if (velocidadeReferencia_m_s < 0.10)
|
||||
{
|
||||
velocidadeReferencia_m_s =
|
||||
FuncoesMatematicas.CalculaVelocidadeMsPercentual(
|
||||
Variaveis.OperacaoEmAndamento
|
||||
.Parametros
|
||||
.Controle
|
||||
.MovVelocidadeCErvasPercent
|
||||
);
|
||||
}
|
||||
|
||||
return LPorMetroBase;
|
||||
// Para a verificação pré-corredor, usar o pior caso:
|
||||
// todos os bicos pulverizando.
|
||||
double vazaoReferencia_LMin = VazaoTotalTodosBicos_LMin;
|
||||
|
||||
if (velocidadeReferencia_m_s > 0.01 &&
|
||||
vazaoReferencia_LMin > 0)
|
||||
{
|
||||
double velocidade_m_min = velocidadeReferencia_m_s * 60.0;
|
||||
return vazaoReferencia_LMin / velocidade_m_min;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool ConseguePulverizarRua(double comprimentoRua_m)
|
||||
|
|
|
|||
|
|
@ -65,75 +65,187 @@ class RegrasTaticas:
|
|||
_imu = ContextoGlobalRedis.get_modulo(T_Code.Imu) or {}
|
||||
|
||||
_imu_saude = StatusModulo(
|
||||
_imu.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)
|
||||
_imu.get("saude", {}).get(
|
||||
"status",
|
||||
StatusModulo.DESCONECTADO.value
|
||||
)
|
||||
)
|
||||
|
||||
imu_operante = _imu_saude in [StatusModulo.OPERANTE, StatusModulo.ALERTA]
|
||||
imu_operante = _imu_saude in [
|
||||
StatusModulo.OPERANTE,
|
||||
StatusModulo.ALERTA,
|
||||
]
|
||||
|
||||
imu_ts = float(_imu.get("timestamp", 0.0) or 0.0)
|
||||
imu_ts_s = imu_ts / 1000.0 if imu_ts > 100000000000.0 else imu_ts
|
||||
imu_atualizada = (time.time() - imu_ts_s) <= 1.0 if imu_ts_s > 0 else False
|
||||
# ============================================================
|
||||
# Atualidade do dado
|
||||
# ============================================================
|
||||
|
||||
try:
|
||||
imu_ts = float(_imu.get("timestamp", 0.0) or 0.0)
|
||||
except (TypeError, ValueError):
|
||||
imu_ts = 0.0
|
||||
|
||||
imu_ts_s = (
|
||||
imu_ts / 1000.0
|
||||
if imu_ts > 100000000000.0
|
||||
else imu_ts
|
||||
)
|
||||
|
||||
imu_atualizada = (
|
||||
(time.time() - imu_ts_s) <= 1.0
|
||||
if imu_ts_s > 0
|
||||
else False
|
||||
)
|
||||
|
||||
imu_valido = bool(_imu.get("valido", False))
|
||||
|
||||
risk_level = str(_imu.get("risk_level", "unknown") or "unknown")
|
||||
risk_level_num = int(_imu.get("risk_level_num", 4) or 4)
|
||||
# ============================================================
|
||||
# Estado de risco
|
||||
# ============================================================
|
||||
|
||||
risk_level = str(
|
||||
_imu.get("risk_level", "unknown") or "unknown"
|
||||
).strip().lower()
|
||||
|
||||
risk_level_num_raw = _imu.get("risk_level_num", None)
|
||||
|
||||
if risk_level_num_raw is None:
|
||||
# Fallback pelo campo textual caso o número não tenha sido publicado.
|
||||
mapa_niveis = {
|
||||
"normal": 0,
|
||||
"attention": 1,
|
||||
"risk": 2,
|
||||
"critical": 3,
|
||||
"emergency": 4,
|
||||
}
|
||||
|
||||
risk_level_num = mapa_niveis.get(risk_level, 4)
|
||||
else:
|
||||
try:
|
||||
risk_level_num = int(risk_level_num_raw)
|
||||
except (TypeError, ValueError):
|
||||
risk_level_num = 4
|
||||
|
||||
# Impede valores fora do contrato.
|
||||
risk_level_num = max(0, min(4, risk_level_num))
|
||||
|
||||
stop = bool(_imu.get("stop", False))
|
||||
emergency_stop = bool(_imu.get("emergency_stop", False))
|
||||
bloquear_avanco = bool(_imu.get("bloquear_avanco", False))
|
||||
|
||||
roll = float(_imu.get("roll_filtrado", _imu.get("roll_seg", _imu.get("roll", 0.0))) or 0.0)
|
||||
pitch = float(_imu.get("pitch_filtrado", _imu.get("pitch_seg", _imu.get("pitch", 0.0))) or 0.0)
|
||||
try:
|
||||
roll = float(
|
||||
_imu.get(
|
||||
"roll_filtrado",
|
||||
_imu.get("roll_seg", _imu.get("roll", 0.0))
|
||||
) or 0.0
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
roll = 0.0
|
||||
|
||||
roll_rate = float(_imu.get("roll_rate_dps", 0.0) or 0.0)
|
||||
pitch_rate = float(_imu.get("pitch_rate_dps", 0.0) or 0.0)
|
||||
try:
|
||||
pitch = float(
|
||||
_imu.get(
|
||||
"pitch_filtrado",
|
||||
_imu.get("pitch_seg", _imu.get("pitch", 0.0))
|
||||
) or 0.0
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
pitch = 0.0
|
||||
|
||||
try:
|
||||
roll_rate = float(
|
||||
_imu.get("roll_rate_dps", 0.0) or 0.0
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
roll_rate = 0.0
|
||||
|
||||
try:
|
||||
pitch_rate = float(
|
||||
_imu.get("pitch_rate_dps", 0.0) or 0.0
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
pitch_rate = 0.0
|
||||
|
||||
motivos_risco = _imu.get("motivos_risco", []) or []
|
||||
acao_sugerida = str(_imu.get("acao_sugerida", "") or "")
|
||||
|
||||
imu_bloqueio_bruto = (
|
||||
not imu_operante
|
||||
or not imu_atualizada
|
||||
or not imu_valido
|
||||
or emergency_stop
|
||||
or stop
|
||||
or bloquear_avanco
|
||||
or risk_level_num >= 3
|
||||
acao_sugerida = str(
|
||||
_imu.get("acao_sugerida", "") or ""
|
||||
)
|
||||
|
||||
inclinacao_persistente = self._avaliar_persistencia(
|
||||
nome="inclinacao_perigosa",
|
||||
estado_bruto=imu_bloqueio_bruto,
|
||||
tempo_acionar=0.10 if emergency_stop else 0.20,
|
||||
tempo_liberar=1.2
|
||||
)
|
||||
# ============================================================
|
||||
# Primeiro valida a disponibilidade da IMU
|
||||
# ============================================================
|
||||
|
||||
if not imu_operante:
|
||||
self._resetar_persistencia("inclinacao_perigosa")
|
||||
|
||||
motivos.append(
|
||||
f"IMU mandatória por [ Parada por Inclinação ] não operante: {_imu_saude.name}"
|
||||
"IMU mandatória por [ Parada por Inclinação ] "
|
||||
f"não operante: {_imu_saude.name}"
|
||||
)
|
||||
|
||||
freio_necessario = True
|
||||
|
||||
elif not imu_atualizada:
|
||||
motivos.append("IMU mandatória por [ Parada por Inclinação ] desatualizada")
|
||||
self._resetar_persistencia("inclinacao_perigosa")
|
||||
|
||||
motivos.append(
|
||||
"IMU mandatória por [ Parada por Inclinação ] "
|
||||
"desatualizada"
|
||||
)
|
||||
|
||||
freio_necessario = True
|
||||
|
||||
elif not imu_valido:
|
||||
motivos.append("IMU mandatória por [ Parada por Inclinação ] sem leitura válida")
|
||||
freio_necessario = True
|
||||
self._resetar_persistencia("inclinacao_perigosa")
|
||||
|
||||
elif inclinacao_persistente:
|
||||
motivos.append(
|
||||
f"IMU bloqueou movimento: {risk_level} | ação={acao_sugerida} | "
|
||||
f"roll={roll:.2f}°, pitch={pitch:.2f}°, "
|
||||
f"roll_rate={roll_rate:.1f}°/s, pitch_rate={pitch_rate:.1f}°/s"
|
||||
"IMU mandatória por [ Parada por Inclinação ] "
|
||||
"sem leitura válida"
|
||||
)
|
||||
|
||||
if motivos_risco:
|
||||
motivos.append(f"Motivos IMU: {', '.join(map(str, motivos_risco))}")
|
||||
freio_necessario = True
|
||||
|
||||
freio_necessario = bool(emergency_stop or stop or risk_level_num >= 3)
|
||||
else:
|
||||
# A persistência passa a tratar somente perigo de inclinação,
|
||||
# e não falhas de comunicação ou saúde.
|
||||
perigo_inclinacao_bruto = bool(
|
||||
emergency_stop
|
||||
or stop
|
||||
or bloquear_avanco
|
||||
or risk_level_num >= 3
|
||||
)
|
||||
|
||||
inclinacao_persistente = self._avaliar_persistencia(
|
||||
nome="inclinacao_perigosa",
|
||||
estado_bruto=perigo_inclinacao_bruto,
|
||||
tempo_acionar=0.10 if emergency_stop else 0.20,
|
||||
tempo_liberar=1.2,
|
||||
)
|
||||
|
||||
if inclinacao_persistente:
|
||||
motivos.append(
|
||||
f"IMU bloqueou movimento: {risk_level} | "
|
||||
f"nível={risk_level_num} | "
|
||||
f"ação={acao_sugerida} | "
|
||||
f"roll={roll:.2f}°, pitch={pitch:.2f}°, "
|
||||
f"roll_rate={roll_rate:.1f}°/s, "
|
||||
f"pitch_rate={pitch_rate:.1f}°/s"
|
||||
)
|
||||
|
||||
if motivos_risco:
|
||||
motivos.append(
|
||||
f"Motivos IMU: "
|
||||
f"{', '.join(map(str, motivos_risco))}"
|
||||
)
|
||||
|
||||
# Se a persistência está ativa, o bloqueio também deve estar.
|
||||
# Não devemos recalcular usando somente o estado instantâneo.
|
||||
freio_necessario = True
|
||||
else:
|
||||
# Evita que um bloqueio antigo sobreviva ao recurso ser desligado
|
||||
# e ligado novamente.
|
||||
self._resetar_persistencia("inclinacao_perigosa")
|
||||
|
||||
pulverizador_automatico = _controle.get("pulverizador_automatico", False)
|
||||
if pulverizador_automatico:
|
||||
|
|
@ -159,7 +271,6 @@ class RegrasTaticas:
|
|||
f"Cavitação na bomba pressurizadora da linha! "
|
||||
f"Pressão: {pressao_sp}/{pressao_atual} psi"
|
||||
)
|
||||
freio_necessario = False
|
||||
|
||||
mov_assistido_sonar = _controle.get("mov_auxilio_sonar", False)
|
||||
dir_assistido_sonar = _controle.get("dir_auxilio_sonar", False)
|
||||
|
|
@ -205,3 +316,14 @@ class RegrasTaticas:
|
|||
|
||||
p["ultimo_estado_bruto"] = estado_bruto
|
||||
return p["ativo"]
|
||||
|
||||
def _resetar_persistencia(self, nome):
|
||||
p = self.persistencias.get(nome)
|
||||
|
||||
if p is None:
|
||||
return
|
||||
|
||||
p["ativo"] = False
|
||||
p["ts_inicio_true"] = None
|
||||
p["ts_inicio_false"] = None
|
||||
p["ultimo_estado_bruto"] = False
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ WEED_DEFAULT_CONFIG = {
|
|||
"camera_height": 800,
|
||||
|
||||
# FPS solicitado na câmera/OAK. Pode ser maior que o pipeline.
|
||||
"camera_fps": 25,
|
||||
"camera_fps": 40,
|
||||
|
||||
# Tamanho final do tensor entregue ao modelo: [W, H].
|
||||
"ia_resolution": [640, 400],
|
||||
|
|
|
|||
Loading…
Reference in New Issue