ajuste na atuação do bico enquanto parado e antecipação da zona de atuação conforme velcodaide
This commit is contained in:
parent
bfed826136
commit
bb546da70f
|
|
@ -296,6 +296,8 @@ class WeedDetector:
|
||||||
|
|
||||||
cfg = self.config
|
cfg = self.config
|
||||||
vel_mps = float(cfg.get("velocidade_robo", 0.0) or 0.0)
|
vel_mps = float(cfg.get("velocidade_robo", 0.0) or 0.0)
|
||||||
|
# A geometria de atuação foi definida para o avanço. A ré não é
|
||||||
|
# reinterpretada como um percurso espacial inverso dos bicos.
|
||||||
if vel_mps < 0:
|
if vel_mps < 0:
|
||||||
vel_mps = 0.0
|
vel_mps = 0.0
|
||||||
|
|
||||||
|
|
@ -463,9 +465,14 @@ class WeedDetector:
|
||||||
self._frac_grid_last = frac_grid
|
self._frac_grid_last = frac_grid
|
||||||
|
|
||||||
# 3) Atualiza score espacial.
|
# 3) Atualiza score espacial.
|
||||||
|
# Em movimento, acumula evidência e desloca a esteira normalmente.
|
||||||
|
# Parado, acompanha a evidência do frame atual por EMA: o mesmo ruído
|
||||||
|
# não pode ser somado indefinidamente, mas uma erva persistente continua
|
||||||
|
# podendo manter/ligar o bico.
|
||||||
score_update_info = self._atualizar_score_memoria(
|
score_update_info = self._atualizar_score_memoria(
|
||||||
frac_grid=frac_grid,
|
frac_grid=frac_grid,
|
||||||
cfg=cfg,
|
cfg=cfg,
|
||||||
|
em_movimento=bool(shift_info["em_movimento"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 4) Decide bicos pela zona física de atuação, com compensação de latência.
|
# 4) Decide bicos pela zona física de atuação, com compensação de latência.
|
||||||
|
|
@ -533,6 +540,7 @@ class WeedDetector:
|
||||||
return {
|
return {
|
||||||
"dt_s": 0.0,
|
"dt_s": 0.0,
|
||||||
"vel_mps": float(vel_mps),
|
"vel_mps": float(vel_mps),
|
||||||
|
"em_movimento": False,
|
||||||
"delta_frac": 0.0,
|
"delta_frac": 0.0,
|
||||||
"shift_cells": 0.0,
|
"shift_cells": 0.0,
|
||||||
"distancia_deslocada_total_cm": float(self._distancia_deslocada_total_cm),
|
"distancia_deslocada_total_cm": float(self._distancia_deslocada_total_cm),
|
||||||
|
|
@ -545,10 +553,17 @@ class WeedDetector:
|
||||||
if max_dt > 0:
|
if max_dt > 0:
|
||||||
dt = min(dt, max_dt)
|
dt = min(dt, max_dt)
|
||||||
|
|
||||||
if dt <= 0 or vel_mps <= 0:
|
vel_min = max(
|
||||||
|
0.0,
|
||||||
|
float(cfg.get("vel_min_movimento_memoria_mps", 0.03) or 0.03),
|
||||||
|
)
|
||||||
|
em_movimento = bool(abs(vel_mps) >= vel_min)
|
||||||
|
|
||||||
|
if dt <= 0 or not em_movimento:
|
||||||
return {
|
return {
|
||||||
"dt_s": float(max(0.0, dt)),
|
"dt_s": float(max(0.0, dt)),
|
||||||
"vel_mps": float(vel_mps),
|
"vel_mps": float(vel_mps),
|
||||||
|
"em_movimento": False,
|
||||||
"delta_frac": 0.0,
|
"delta_frac": 0.0,
|
||||||
"shift_cells": 0.0,
|
"shift_cells": 0.0,
|
||||||
"distancia_deslocada_total_cm": float(self._distancia_deslocada_total_cm),
|
"distancia_deslocada_total_cm": float(self._distancia_deslocada_total_cm),
|
||||||
|
|
@ -582,6 +597,7 @@ class WeedDetector:
|
||||||
return {
|
return {
|
||||||
"dt_s": float(dt),
|
"dt_s": float(dt),
|
||||||
"vel_mps": float(vel_mps),
|
"vel_mps": float(vel_mps),
|
||||||
|
"em_movimento": True,
|
||||||
"delta_frac": float(delta_frac),
|
"delta_frac": float(delta_frac),
|
||||||
"shift_cells": float(shift_cells),
|
"shift_cells": float(shift_cells),
|
||||||
"k_shift_frame_por_mps": float(k_shift),
|
"k_shift_frame_por_mps": float(k_shift),
|
||||||
|
|
@ -723,6 +739,7 @@ class WeedDetector:
|
||||||
self,
|
self,
|
||||||
frac_grid: np.ndarray,
|
frac_grid: np.ndarray,
|
||||||
cfg: dict,
|
cfg: dict,
|
||||||
|
em_movimento: bool = True,
|
||||||
):
|
):
|
||||||
min_frac_pred = float(
|
min_frac_pred = float(
|
||||||
cfg.get(
|
cfg.get(
|
||||||
|
|
@ -748,14 +765,35 @@ class WeedDetector:
|
||||||
evidencia = np.clip(frac_grid / percent_ref, 0.0, 1.0).astype(np.float32)
|
evidencia = np.clip(frac_grid / percent_ref, 0.0, 1.0).astype(np.float32)
|
||||||
cond_pos = frac_grid >= min_frac_pred
|
cond_pos = frac_grid >= min_frac_pred
|
||||||
|
|
||||||
# Decaimento geral, depois reforço positivo.
|
if em_movimento:
|
||||||
score = np.maximum(0.0, self._score_grid - down_decay)
|
# Em movimento, cada frame traz evidência de uma nova faixa física
|
||||||
|
# do terreno; mantém a estratégia acumulativa original.
|
||||||
|
score = np.maximum(0.0, self._score_grid - down_decay)
|
||||||
|
|
||||||
score = np.where(
|
score = np.where(
|
||||||
cond_pos,
|
cond_pos,
|
||||||
np.minimum(1.0, score + up_gain * evidencia),
|
np.minimum(1.0, score + up_gain * evidencia),
|
||||||
score,
|
score,
|
||||||
).astype(np.float32)
|
).astype(np.float32)
|
||||||
|
modo_atualizacao = "acumulativo_movimento"
|
||||||
|
else:
|
||||||
|
# Parado, vários frames observam essencialmente o mesmo terreno.
|
||||||
|
# Uma EMA faz o score convergir para a evidência atual, em vez de
|
||||||
|
# transformar repetição temporal em confiança espacial infinita.
|
||||||
|
alpha_parado = float(cfg.get("score_alpha_parado", 0.70) or 0.70)
|
||||||
|
alpha_parado = float(np.clip(alpha_parado, 0.0, 0.99))
|
||||||
|
|
||||||
|
evidencia_atual = np.where(
|
||||||
|
cond_pos,
|
||||||
|
evidencia,
|
||||||
|
0.0,
|
||||||
|
).astype(np.float32)
|
||||||
|
|
||||||
|
score = (
|
||||||
|
alpha_parado * self._score_grid
|
||||||
|
+ (1.0 - alpha_parado) * evidencia_atual
|
||||||
|
).astype(np.float32)
|
||||||
|
modo_atualizacao = "ema_parado"
|
||||||
|
|
||||||
self._score_grid = score
|
self._score_grid = score
|
||||||
|
|
||||||
|
|
@ -764,6 +802,11 @@ class WeedDetector:
|
||||||
"percent_ref_evidencia": float(percent_ref),
|
"percent_ref_evidencia": float(percent_ref),
|
||||||
"score_up_gain": float(up_gain),
|
"score_up_gain": float(up_gain),
|
||||||
"score_down_decay": float(down_decay),
|
"score_down_decay": float(down_decay),
|
||||||
|
"em_movimento": bool(em_movimento),
|
||||||
|
"modo_atualizacao": modo_atualizacao,
|
||||||
|
"score_alpha_parado": float(
|
||||||
|
cfg.get("score_alpha_parado", 0.70) or 0.70
|
||||||
|
),
|
||||||
"frac_grid_max": float(frac_grid.max()) if frac_grid.size else 0.0,
|
"frac_grid_max": float(frac_grid.max()) if frac_grid.size else 0.0,
|
||||||
"evidencia_max": float(evidencia.max()) if evidencia.size else 0.0,
|
"evidencia_max": float(evidencia.max()) if evidencia.size else 0.0,
|
||||||
}
|
}
|
||||||
|
|
@ -788,20 +831,32 @@ class WeedDetector:
|
||||||
|
|
||||||
k_shift = max(0.0, k_shift)
|
k_shift = max(0.0, k_shift)
|
||||||
|
|
||||||
# Antecipação em fração da imagem:
|
# A zona configurada representa a posição física fixa dos bicos.
|
||||||
# Se demora para atuar, avalia células um pouco acima da zona real,
|
# Com faixa=0,85, área=0,10 e inversão vertical, 85%..95% da imagem
|
||||||
# porque elas chegarão na zona quando o bico abrir de fato.
|
# original vira 5%..15% na convenção interna. Essa zona NÃO muda de
|
||||||
antecipacao_frac = max(0.0, vel_mps * lat_s * k_shift)
|
# parado até a velocidade de referência. Somente a parcela de
|
||||||
|
# velocidade ACIMA da referência antecipa a avaliação para compensar
|
||||||
|
# o tempo de resposta do sistema.
|
||||||
|
vel_referencia = max(
|
||||||
|
0.0,
|
||||||
|
float(cfg.get("velocidade_referencia_atuacao_mps", 0.65) or 0.65),
|
||||||
|
)
|
||||||
|
velocidade_abs = abs(float(vel_mps))
|
||||||
|
velocidade_excedente = max(0.0, velocidade_abs - vel_referencia)
|
||||||
|
antecipacao_extra_frac = velocidade_excedente * lat_s * k_shift
|
||||||
|
|
||||||
if getattr(self, "inverter_sentido_vertical_bicos", False):
|
# A posição dos bicos é fixa. Não tentamos reinterpretar essa zona na
|
||||||
# Se a erva vem do pé para o topo, antecipar significa olhar
|
# marcha a ré; a antecipação só indica uma região anterior no sentido
|
||||||
# um pouco abaixo da zona real, pois ela ainda vai subir até o bico.
|
# visual configurado para a operação normal de avanço.
|
||||||
zona_eval_ini_frac = zona_ini_frac + antecipacao_frac
|
sentido_vertical = (
|
||||||
zona_eval_fim_frac = zona_fim_frac + antecipacao_frac
|
1.0
|
||||||
else:
|
if getattr(self, "inverter_sentido_vertical_bicos", False)
|
||||||
# Lógica atual: erva vem do topo para o pé.
|
else -1.0
|
||||||
zona_eval_ini_frac = zona_ini_frac - antecipacao_frac
|
)
|
||||||
zona_eval_fim_frac = zona_fim_frac - antecipacao_frac
|
offset_assinado = antecipacao_extra_frac * sentido_vertical
|
||||||
|
|
||||||
|
zona_eval_ini_frac = zona_ini_frac + offset_assinado
|
||||||
|
zona_eval_fim_frac = zona_fim_frac + offset_assinado
|
||||||
|
|
||||||
zona_eval_ini_frac = max(0.0, min(1.0, zona_eval_ini_frac))
|
zona_eval_ini_frac = max(0.0, min(1.0, zona_eval_ini_frac))
|
||||||
zona_eval_fim_frac = max(0.0, min(1.0, zona_eval_fim_frac))
|
zona_eval_fim_frac = max(0.0, min(1.0, zona_eval_fim_frac))
|
||||||
|
|
@ -872,7 +927,12 @@ class WeedDetector:
|
||||||
|
|
||||||
# Zona avaliada com compensação de latência.
|
# Zona avaliada com compensação de latência.
|
||||||
"latencia_total_atuacao_ms": float(lat_ms),
|
"latencia_total_atuacao_ms": float(lat_ms),
|
||||||
"antecipacao_frac": float(antecipacao_frac),
|
"antecipacao_frac": float(antecipacao_extra_frac),
|
||||||
|
"velocidade_referencia_atuacao_mps": float(vel_referencia),
|
||||||
|
"velocidade_excedente_atuacao_mps": float(velocidade_excedente),
|
||||||
|
"offset_base_referencia_frac": 0.0,
|
||||||
|
"antecipacao_extra_frac": float(antecipacao_extra_frac),
|
||||||
|
"offset_assinado_frac": float(offset_assinado),
|
||||||
"zona_eval_inicio_frac": float(zona_eval_ini_frac),
|
"zona_eval_inicio_frac": float(zona_eval_ini_frac),
|
||||||
"zona_eval_fim_frac": float(zona_eval_fim_frac),
|
"zona_eval_fim_frac": float(zona_eval_fim_frac),
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue