diff --git a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs index b8e6c50b5..ef04cc29a 100644 --- a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs @@ -185,7 +185,11 @@ namespace AgroBase.Services.Operadores motivo_bat = _t.AutonomiaCooredor?.Motivos?.FirstOrDefault(x => x.Contains("Bateria")) ?? "", bateria_ok = _t.AutonomiaCooredor?.BateriaSuficiente ?? false, motivo_hrb = _t.AutonomiaCooredor?.Motivos?.FirstOrDefault(x => x.Contains("Herbicida")) ?? "", - herbicida_ok = _t.AutonomiaCooredor?.HerbicidaSuficiente ?? false + herbicida_ok = _t.AutonomiaCooredor?.HerbicidaSuficiente ?? false, + autonomia_liberada = _t.AutonomiaCooredor?.Liberado ?? false, + autonomia_status = (int)(_t.AutonomiaCooredor?.Status ?? AutonomiaCorredorStatus.Desconhecido), + autonomia_motivo = _t.AutonomiaCooredor?.Motivo ?? "", + autonomia_ok_supervisionado = _t.AutonomiaCooredor?.Status == AutonomiaCorredorStatus.OkSupervisionado, }, } : null ), @@ -308,6 +312,8 @@ namespace AgroBase.Services.Operadores { percent_vel_max = pControle.MovVelocidadeSErvasPercent, percent_vel_min = pControle.MovVelocidadeCErvasPercent, + percent_vel_curva = 20.0, + rampa_partida_pct = VariaveisEquipamento.PercentualVelMin, rampa_aceleracao_pct_s = 12.0, rampa_desaceleracao_pct_s = 18.0, rampa_desaceleracao_seguranca_pct_s = 35.0, diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py index be2b9a93b..45891c0f1 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py @@ -325,6 +325,16 @@ class ModuloAtuador(ModuloDiagnosticoBase): self._float(self._get(b["dados"], "potencia", self._campo_atual(b["dados"], "Potencia", 0)), 0) > self.POTENCIA_MIN_BOMBA_LIGADA ] + corredor_liberado = self._bool(corredor.get("liberado", False)) + autonomia_ok_supervisionado = self._bool( + corredor.get("autonomia_ok_supervisionado", False) + ) + autonomia_motivo = self._texto_ou_padrao( + corredor.get("autonomia_motivo"), + corredor.get("motivo_hrb"), + padrao="Herbicida insuficiente para pulverizar o corredor completo." + ) + return { "pulverizador_automatico": pulverizador_automatico, "calibrando": calibrando, @@ -347,6 +357,9 @@ class ModuloAtuador(ModuloDiagnosticoBase): "bicos_ligados": bicos_ligados, "bombas_comandadas": bombas_comandadas, "bombas_ligadas": bombas_ligadas, + "corredor_liberado": corredor_liberado, + "autonomia_ok_supervisionado": autonomia_ok_supervisionado, + "autonomia_motivo": autonomia_motivo, "debug": { "pulverizador_automatico": pulverizador_automatico, "calibrando": calibrando, @@ -1061,13 +1074,19 @@ class ModuloAtuador(ModuloDiagnosticoBase): if not ctx["herbicida_ok_corredor"]: motivo = self._texto_ou_padrao( + ctx.get("autonomia_motivo"), ctx.get("motivo_herbicida_corredor"), padrao="Herbicida insuficiente para pulverizar o corredor completo." ) motivos.append(motivo) - if herbicida_pode_bloquear: + autonomia_liberada_supervisionada = bool( + ctx.get("corredor_liberado", False) or + ctx.get("autonomia_ok_supervisionado", False) + ) + + if herbicida_pode_bloquear and not autonomia_liberada_supervisionada: condicoes.append({ "label": "Autonomia de herbicida", "valor": ctx["percent_reservatorio"], @@ -1076,6 +1095,7 @@ class ModuloAtuador(ModuloDiagnosticoBase): "descricao": motivo, "acoes": [ "Reabastecer ou reduzir distância do corredor planejado.", + "Liberar manualmente pela base se o operador assumir a supervisão.", ], }) score = min(score, 80) @@ -1085,9 +1105,10 @@ class ModuloAtuador(ModuloDiagnosticoBase): "valor": ctx["percent_reservatorio"], "severidade": 35, "classe": "recurso_operacional", - "descricao": f"{motivo} Pulverização automática desligada; condição informativa, sem bloqueio de deslocamento.", + "descricao": f"{motivo} Corredor liberado supervisionado; condição informativa, sem bloqueio estrutural.", "acoes": [ - "Reabastecer antes de habilitar a pulverização automática.", + "Monitorar consumo durante o corredor.", + "Reabastecer antes da próxima operação de pulverização.", ], }) score = min(score, 90) diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py index a9c28fabb..577dab335 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py @@ -187,24 +187,26 @@ def definir_comando(filtro_vel: FiltroVelocidade, erro_orientacao: float = None) debug["weed"] = info_ervas + velocidade_livre = calcular_velocidade_relativa( + vel_min=vel_com_ervas, + vel_max=vel_sem_ervas, + ang_max=ang_max, + erro_orientacao=erro_angular, + k=1.0, + curva=0.70, + dead=5.0 + ) + if reduzir_para_pulverizar: - velocidade_sp = min(velocidade_sp, vel_com_ervas) + velocidade_sp = min(velocidade_livre, vel_com_ervas) debug["motivos"].append("ervas no radar: reduzindo para pulverizar") elif reduzir_para_fim_corredor: - velocidade_sp = min(velocidade_sp, vel_com_ervas) + velocidade_sp = min(velocidade_livre, vel_com_ervas) debug["motivos"].append("fim de corredor próximo: reduzindo") else: - velocidade_sp = calcular_velocidade_relativa( - vel_min=vel_com_ervas, - vel_max=vel_sem_ervas, - ang_max=ang_max, - erro_orientacao=erro_angular, - k=1.0, - curva=0.70, - dead=5.0 - ) + velocidade_sp = velocidade_livre debug["motivos"].append("caminhando rua livre") else: @@ -328,7 +330,8 @@ def definir_comando(filtro_vel: FiltroVelocidade, erro_orientacao: float = None) # Aceleração normal é filtrada para não dar tranco. reducao_seguranca = bool( - reduzir_para_fim_corredor + reduzir_para_pulverizar + or reduzir_para_fim_corredor or reduzir_por_curva or reduzir_por_ipb or debug.get("visual", {}).get("mode") in ["caution", "slowdown"] @@ -782,18 +785,32 @@ def _aplicar_rampa_velocidade( ultimo_ts = 0.0 if ultimo_ts <= 0.0: - ultimo = 0.0 - ultimo_ts = agora + partida_pct = _float( + mov_cfg.get( + "rampa_partida_pct", + mov_cfg.get("percent_vel_min", 15.0) + ), + 15.0 + ) + + partida_pct = max(1.0, partida_pct) + saida = min(float(velocidade_alvo), partida_pct) + try: - filtro_vel._ultimo_sp_campo = ultimo - filtro_vel._ultimo_ts_campo = ultimo_ts + filtro_vel._ultimo_sp_campo = saida + filtro_vel._ultimo_ts_campo = agora except Exception: pass if debug is not None: - debug["rampa_velocidade_init"] = "inicializada_em_zero" + debug["rampa_velocidade_init"] = { + "modo": "partida_nao_zero", + "alvo": round(float(velocidade_alvo), 2), + "saida": round(float(saida), 2), + "partida_pct": round(float(partida_pct), 2), + } - return 0.0 + return saida dt = _clamp(agora - ultimo_ts, 0.02, 0.5) diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py index ace9d6d5c..2fbced1a3 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py @@ -216,11 +216,12 @@ class RegrasTaticas: ) parar = self._bool(decision.get("parar", False)) - mode = str(decision.get("mode", "") or "").lower() + mode = str(decision.get("mode", "") or "").strip().lower() + parar_hard = bool(parar and mode == "stop") obstaculo_persistente = self._avaliar_persistencia( nome="oak_obstaculo", - estado_bruto=parar, + estado_bruto=parar_hard, tempo_acionar=0.15, tempo_liberar=0.80 )