agrobot_base/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs

747 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using static AgroBase.Models.Enums;
namespace AgroBase.Models.Operadores
{
public class VisualWorkerModel
{
public bool Iniciado { get; set; }
public DateTime IniciadoEm { get; set; }
public bool Pronto { get; set; }
public DateTime ProntoEm { get; set; }
public DateTime UltimaMensagem { get; set; }
public Dictionary<TipoFrameCamera, OAKCameraFrameModel> CameraFrames { get; set; } = new Dictionary<TipoFrameCamera, OAKCameraFrameModel>();
public VisualWorkerMessageAnaliseModel Analises { get; set; } = new VisualWorkerMessageAnaliseModel();
public VisualWorkerMessageIMUModel Imu { get; set; } = new VisualWorkerMessageIMUModel();
public StatusModulo Status { get; set; }
public VisualWorkerResumoModel Resumo { get; set; }
public VisualWorkerModel Clone()
{
return new VisualWorkerModel()
{
Iniciado = Iniciado,
IniciadoEm = IniciadoEm,
Pronto = Pronto,
ProntoEm = ProntoEm,
CameraFrames = new Dictionary<TipoFrameCamera, OAKCameraFrameModel>(CameraFrames ?? new Dictionary<TipoFrameCamera, OAKCameraFrameModel>()),
Analises = Analises?.Clone(),
Imu = Imu?.Clone(),
UltimaMensagem = UltimaMensagem,
Status = Status,
Resumo = Resumo?.Clone()
};
}
public void ReiniciarEstado()
{
Iniciado = false;
IniciadoEm = DateTime.MinValue;
Pronto = false;
ProntoEm = DateTime.MinValue;
CameraFrames = new Dictionary<TipoFrameCamera, OAKCameraFrameModel>();
Analises = new VisualWorkerMessageAnaliseModel();
Imu = new VisualWorkerMessageIMUModel();
Resumo = new VisualWorkerResumoModel();
Status = StatusModulo.Desconectado;
}
}
public class VisualWorkerResumoModel
{
public StatusCarroMapa StatusCarro { get; set; }
public double ErroLateral { get; set; }
public double ErroAngular { get; set; }
public bool ObstaculoDetectado { get; set; } = false;
public bool DeveParar { get; set; } = false;
public bool EnviarComandoParada { get; set; } = false;
public bool EnviarComandoRetomada { get; set; } = false;
private bool _comandoParadaEnviado { get; set; } = false;
public void AtualizarStatusBloqueio(bool consideraEmMovimento)
{
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
ObstaculoDetectado = (Sonar?.Analises?.matriz_confianca?.block?.decision?.parar ?? false);
StatusCarro = Sonar?.Analises?.segmentacao?.status_corredor ?? StatusCarroMapa.Indefinido;
ErroLateral = Sonar?.Analises?.segmentacao?.erro_lateral_pct ?? 0;
ErroAngular = Sonar?.Analises?.segmentacao?.erro_angular ?? 0;
if (!(Variaveis.OperacaoEmAndamento.Parametros?.Controle?.OakParadaPorObstaculo ?? false))
{
_comandoParadaEnviado = false;
DeveParar = false;
EnviarComandoParada = false;
EnviarComandoRetomada = false;
}
else
{
List<Direcao> _direcoesInterromperMovimento = new List<Direcao> { Direcao.Frente }; //, Direcao.Tras
Direcao _ultimaDirecaoControle = Variaveis.OperacaoEmAndamento.Controle?.TiposControle?.FirstOrDefault(x => x?.Tipo == T_Code.Mov)?.UltimaDirecao ?? Direcao.Parado;
bool _carroEmMovimento = _direcoesInterromperMovimento.Contains(_ultimaDirecaoControle);
bool emMovimento = consideraEmMovimento ? _carroEmMovimento : true;
DeveParar = Sonar?.Status == StatusModulo.Operante && ObstaculoDetectado;
EnviarComandoParada = DeveParar && emMovimento;
if (EnviarComandoParada)
{
_comandoParadaEnviado = true;
}
EnviarComandoRetomada = !ObstaculoDetectado && _comandoParadaEnviado;
if (EnviarComandoRetomada)
{
_comandoParadaEnviado = false;
}
}
}
public VisualWorkerResumoModel Clone()
{
return new VisualWorkerResumoModel()
{
StatusCarro = StatusCarro,
ErroLateral = ErroLateral,
ErroAngular = ErroAngular,
ObstaculoDetectado = ObstaculoDetectado,
DeveParar = DeveParar,
EnviarComandoParada = EnviarComandoParada,
EnviarComandoRetomada = EnviarComandoRetomada,
_comandoParadaEnviado = _comandoParadaEnviado,
};
}
public VisualWorkerResumoModel UpdateClone()
{
AtualizarStatusBloqueio(false);
return Clone();
}
}
public class VisualWorkerDadosModel
{
public bool DesvioNecessario { get; set; }
public Enums.Direcao DirecaoDesvio { get; set; }
public Obstaculo ObstaculoCritico { get; set; }
public List<Obstaculo> Obstaculos { get; set; }
public VisualWorkerDadosModel Clone()
{
return new VisualWorkerDadosModel()
{
DesvioNecessario = DesvioNecessario,
DirecaoDesvio = DirecaoDesvio,
ObstaculoCritico = ObstaculoCritico?.Clone(),
Obstaculos = new List<Obstaculo>(Obstaculos ?? new List<Obstaculo>()),
};
}
}
public class VisualWorkerMessageResponseModel
{
public VisualWorkerCommandType cmd { get; set; }
public VisualWorkerMessageResponseSaveFramesModel save_frames { get; set; }
public VisualWorkerMessageResponseModel Clone()
{
return new VisualWorkerMessageResponseModel()
{
cmd = cmd,
save_frames = save_frames.Clone()
};
}
}
public class VisualWorkerMessageResponseSaveFramesModel
{
public long timestamp { get; set; }
public List<string> frames { get; set; }
private bool _newData = false;
public bool newData
{
get
{
if (_newData)
{
_newData = false;
return true;
}
else
{
return false;
}
}
set
{
_newData = value;
}
}
public VisualWorkerMessageResponseSaveFramesModel Clone()
{
return new VisualWorkerMessageResponseSaveFramesModel()
{
timestamp = timestamp,
frames = new List<string>(frames),
newData = true
};
}
}
public class VisualWorkerMessageIMUModel
{
public long timestamp { get; set; }
public double roll { get; set; }
public double pitch { get; set; }
public double yaw { get; set; }
public double yaw_fixed { get; set; }
public VisualWorkerMessageIMUModel Clone()
{
return new VisualWorkerMessageIMUModel()
{
timestamp = timestamp,
roll = roll,
pitch = pitch,
yaw = yaw,
};
}
}
public class VisualWorkerMessageSetupModel
{
public long timestamp { get; set; }
public bool status { get; set; }
private bool _newData = false;
public bool newData
{
get
{
if (_newData)
{
_newData = false;
return true;
}
else
{
return false;
}
}
set
{
_newData = value;
}
}
public VisualWorkerMessageSetupModel Clone()
{
return new VisualWorkerMessageSetupModel()
{
timestamp = timestamp,
status = status,
newData = true
};
}
}
public class VisualWorkerMessageAnaliseModel
{
public DateTime timestamp { get; set; }
//public List<VisualWorkerMessageAnaliseBBoxModel> anomalias { get; set; }
//public List<VisualWorkerMessageAnaliseBBoxModel> sombras { get; set; }
//public VisualWorkerMessageAnaliseSoloModel solo { get; set; }
//public List<VisualWorkerMessageRadar2DPerfilModel> corredor_prof { get; set; }
//public List<VisualWorkerMessageRadar2DPerfilModel> corredor_seg { get; set; }
public VisualWorkerMessageSegmentacaoSemanticaModel segmentacao { get; set; }
public VisualWorkerMessageMatrizConfiancaModel matriz_confianca { get; set; }
public List<VisualWorkerMessageDeteccaoModel> deteccao { get; set; }
public VisualWorkerMessageAnaliseModel Clone()
{
return new VisualWorkerMessageAnaliseModel()
{
timestamp = timestamp,
//anomalias = new List<VisualWorkerMessageAnaliseBBoxModel>(anomalias ?? new List<VisualWorkerMessageAnaliseBBoxModel>()),
//sombras = new List<VisualWorkerMessageAnaliseBBoxModel>(sombras ?? new List<VisualWorkerMessageAnaliseBBoxModel>()),
//solo = solo?.Clone(),
//corredor_prof = new List<VisualWorkerMessageRadar2DPerfilModel>(corredor_prof ?? new List<VisualWorkerMessageRadar2DPerfilModel>()),
//corredor_seg = new List<VisualWorkerMessageRadar2DPerfilModel>(corredor_seg ?? new List<VisualWorkerMessageRadar2DPerfilModel>()),
segmentacao = segmentacao?.Clone() ?? new VisualWorkerMessageSegmentacaoSemanticaModel(),
matriz_confianca = matriz_confianca?.Clone() ?? new VisualWorkerMessageMatrizConfiancaModel(),
deteccao = deteccao?.Select(x => x.Clone()).ToList() ?? new List<VisualWorkerMessageDeteccaoModel>()
};
}
public Bitmap PlotarAnalise(OAKCameraFrameModel frame)
{
return null;
/*Bitmap img = frame?.image();
if (img == null) return null;
using (Graphics g = Graphics.FromImage(img))
{
Pen penObstaculo = new Pen(Color.Red, 2);
Pen penErosao = new Pen(Color.Blue, 2);
Pen penLombada = new Pen(Color.Orange, 2);
Pen penFaixaSolo = new Pen(Color.Black, 2);
Pen penGrafico = new Pen(Color.DarkGreen, 2);
Font font = new Font("Arial", 8);
Brush brush = Brushes.Black;
// 🔸 Definir brushes semi-transparentes para preenchimento
Brush brushObstaculo = new SolidBrush(Color.FromArgb(60, Color.Red));
Brush brushErosao = new SolidBrush(Color.FromArgb(60, Color.Blue));
Brush brushLombada = new SolidBrush(Color.FromArgb(60, Color.Orange));
int imgWidth = img.Width;
int imgHeight = img.Height;
// 🔸 Desenhar Bounding Boxes (Anomalias + Solo)
List<VisualWorkerMessageAnaliseBBoxModel> bboxes = new List<VisualWorkerMessageAnaliseBBoxModel>();
if (anomalias != null) bboxes.AddRange(anomalias);
//if (solo?.bbox_list != null) bboxes.AddRange(solo.bbox_list);
foreach (var bbox in bboxes)
{
Pen pen = penObstaculo;
Brush fill = brushObstaculo;
if (bbox.tipo == "erosao")
{
pen = penErosao;
fill = brushErosao;
}
if (bbox.tipo == "lombada")
{
pen = penLombada;
fill = brushLombada;
}
int x = (int)(bbox.bbox[0] * imgWidth);
int y = (int)(bbox.bbox[1] * imgHeight);
int w = (int)(bbox.bbox[2] * imgWidth);
int h = (int)(bbox.bbox[3] * imgHeight);
var rect = new Rectangle(x, y, w, h);
// 🔸 Preencher com opacidade
g.FillRectangle(fill, rect);
// 🔸 Contorno
g.DrawRectangle(pen, rect);
// 🔸 Label
string label = $"{bbox.tipo} {bbox.distancia_m}m Δ{bbox.variacao}mm";
g.DrawString(label, font, brush, rect.X, rect.Y - 12);
}
// 🔸 Linha da faixa do solo
if (solo != null)
{
int yInicio = imgHeight - (int)(solo.percent_y * imgHeight);
g.DrawLine(penFaixaSolo, 0, yInicio, imgWidth, yInicio);
}
// 🔸 Gráfico do perfil de solo
if (solo?.perfil != null && solo.perfil.Count > 1)
{
var perfil = solo.perfil;
int setores = solo.perfil.Count;
int yInicio = imgHeight - (int)(solo.percent_y * imgHeight);
int alturaRegiao = imgHeight / solo.perfil.Count;
double maxZ = perfil.Max();
double minZ = perfil.Min();
if (maxZ == minZ) maxZ += 1; // evita divisão por zero
for (int i = 0; i < perfil.Count - 1; i++)
{
float x1 = (float)(i * imgWidth / setores + imgWidth / (2.0 * setores));
float x2 = (float)((i + 1) * imgWidth / setores + imgWidth / (2.0 * setores));
float y1 = (float)(yInicio + alturaRegiao - ((perfil[i] - minZ) / (maxZ - minZ)) * alturaRegiao);
float y2 = (float)(yInicio + alturaRegiao - ((perfil[i + 1] - minZ) / (maxZ - minZ)) * alturaRegiao);
g.DrawLine(penGrafico, x1, y1, x2, y2);
g.FillEllipse(Brushes.DarkGreen, x1 - 3, y1 - 3, 6, 6);
}
// Desenha o último ponto
float xLast = (float)((perfil.Count - 1) * imgWidth / setores + imgWidth / (2.0 * setores));
float yLast = (float)(yInicio + alturaRegiao - ((perfil.Last() - minZ) / (maxZ - minZ)) * alturaRegiao);
g.FillEllipse(Brushes.DarkGreen, xLast - 3, yLast - 3, 6, 6);
}
}
return img;*/
}
}
public class VisualWorkerMessageAnaliseSoloModel
{
public List<double> perfil { get; set; }
public double percent_y { get; set; }
public double inclinacao { get; set; }
//public List<VisualWorkerMessageAnaliseBBoxModel> bbox_list { get; set; }
//public int y_inicio { get; set; }
//public int altura_regiao { get; set; }
//public int n_setores { get; set; }
public VisualWorkerMessageAnaliseSoloModel Clone()
{
return new VisualWorkerMessageAnaliseSoloModel()
{
perfil = new List<double>(perfil),
percent_y = percent_y,
inclinacao = inclinacao,
//bbox_list = new List<VisualWorkerMessageAnaliseBBoxModel>(bbox_list),
//y_inicio = y_inicio,
//altura_regiao = altura_regiao,
//n_setores = n_setores,
};
}
}
public class VisualWorkerMessageAnaliseBBoxModel
{
public string tipo { get; set; }
public List<double> bbox { get; set; } // [x, y, w, h]
public List<double> centro_percentual { get; set; } // [x%, y%]
public double? distancia_m { get; set; }
public double? largura_m { get; set; }
public double? altura_m { get; set; }
public List<double> profundidades { get; set; } // [z1, z2] ou null
public double? variacao { get; set; } // delta Z ou null
}
public class VisualWorkerMessageRadar2DModel
{
public OAKCameraFrameModel frame { get; set; }
public VisualWorkerMessageRadar2DAnaliseModel analise { get; set; }
private bool _newData = false;
public bool newData
{
get
{
if (_newData)
{
_newData = false;
return true;
}
else
{
return false;
}
}
set
{
_newData = value;
}
}
public VisualWorkerMessageRadar2DModel Clone()
{
return new VisualWorkerMessageRadar2DModel()
{
frame = frame.Clone(),
analise = analise.Clone(),
newData = true
};
}
public Bitmap PlotarAnalsie(Bitmap img)
{
/*try
{
using (Graphics g = Graphics.FromImage(img))
{
var grid = analise.grid_info;
double cellSize = grid.cell_size;
double escala = grid.escala;
int imgSize = (int)grid.img_size;
int centerX = (int)grid.center_x;
int centerY = (int)grid.center_y;
int gridX = (int)(2 * grid.distancia_max / cellSize);
int gridZ = (int)(grid.distancia_max / cellSize);
foreach (var bbox in analise.bboxes_sombra)
{
int xGrid = bbox.bbox[0];
int zGrid = bbox.bbox[1];
int wGrid = bbox.bbox[2];
int hGrid = bbox.bbox[3];
// 🔸 Converte X (grid → metros → pixels com margem)
int pixelX = (int)(centerX + (xGrid - gridX / 2.0) * cellSize * escala);
// 🔸 Converte Z/Y (grid → metros → pixels com inversão vertical + margem)
int pixelY = (int)((centerY / 3) + zGrid * cellSize * escala);
// 🔸 Tamanho da bbox em pixels
int pixelW = (int)(wGrid * cellSize * escala);
int pixelH = (int)(hGrid * cellSize * escala);
// 🔸 Desenha a bbox
var rect = new Rectangle(pixelX, pixelY, pixelW, pixelH);
g.DrawRectangle(new Pen(Color.Red, 2), rect);
// 🔸 Desenha o centro da bbox
int centroX = pixelX + pixelW / 2;
int centroY = pixelY + pixelH / 2;
g.FillEllipse(Brushes.Red, centroX - 3, centroY - 3, 6, 6);
}
}
}
catch
{
}*/
return img;
}
}
public class VisualWorkerMessageRadar2DAnaliseModel
{
public List<VisualWorkerMessageAnaliseBBoxModel> bboxes_sombra { get; set; }
public List<VisualWorkerMessageRadar2DPerfilModel> corredor_perfil { get; set; }
public VisualWorkerMessageRadar2DGridInfoModel grid_info { get; set; }
public VisualWorkerMessageRadar2DAnaliseModel Clone()
{
return new VisualWorkerMessageRadar2DAnaliseModel()
{
bboxes_sombra = new List<VisualWorkerMessageAnaliseBBoxModel>(bboxes_sombra),
corredor_perfil = new List<VisualWorkerMessageRadar2DPerfilModel>(corredor_perfil),
grid_info = grid_info.Clone()
};
}
}
public class VisualWorkerMessageRadar2DPerfilModel
{
public double distancia_m { get; set; }
public double esquerda_m { get; set; }
public double direita_m { get; set; }
public double largura_m { get; set; }
}
public class VisualWorkerMessageRadar2DGridInfoModel
{
public double escala { get; set; }
public double img_size { get; set; }
public double center_x { get; set; }
public double center_y { get; set; }
public double cell_size { get; set; }
public double distancia_max { get; set; }
public double largura_max { get; set; }
public VisualWorkerMessageRadar2DGridInfoModel Clone()
{
return new VisualWorkerMessageRadar2DGridInfoModel()
{
escala = escala,
img_size = img_size,
center_x = center_x,
center_y = center_y,
cell_size = cell_size,
distancia_max = distancia_max,
largura_max = largura_max
};
}
}
public class VisualWorkerMessageSegmentacaoSemanticaModel
{
public double timestamp { get; set; }
public int height { get; set; }
public int width { get; set; }
public double? erro_angular { get; set; }
public double? erro_lateral_pct { get; set; }
public StatusCarroMapa status_corredor { get; set; }
public StatusCarroMapa status_corredor_anterior { get; set; }
public VisualWorkerMessageSegmentacaoSemanticaDebugCorredorModel status_corredor_debug { get; set; }
public List<double?[]> centros_corredor { get; set; }
public List<int> larguras_px { get; set; }
public VisualWorkerMessageSegmentacaoSemanticaModel Clone()
{
return new VisualWorkerMessageSegmentacaoSemanticaModel()
{
timestamp = timestamp,
height = height,
width = width,
erro_angular = erro_angular,
erro_lateral_pct = erro_lateral_pct,
status_corredor = status_corredor,
status_corredor_anterior = status_corredor_anterior,
status_corredor_debug = status_corredor_debug,
centros_corredor = new List<double?[]>(centros_corredor ?? new List<double?[]>()),
larguras_px = new List<int>(larguras_px ?? new List<int>()),
};
}
}
public class VisualWorkerMessageSegmentacaoSemanticaDebugCorredorModel
{
public double nav_global { get; set; }
public double nav_near { get; set; }
public double nav_mid { get; set; }
public double nav_far { get; set; }
}
public class VisualWorkerMessageMatrizConfiancaModel
{
public float ts { get; set; }
public int seq { get; set; }
public int grid_w { get; set; }
public int grid_h { get; set; }
public List<float> y_range_m { get; set; }
public List<float> row_dist_m { get; set; }
public List<float> row_scale_x_m { get; set; }
public VisualWorkerMessageMatrizConfiancaBlockModel block { get; set; }
public VisualWorkerMessageMatrizConfiancaModel Clone()
{
return new VisualWorkerMessageMatrizConfiancaModel()
{
ts = ts,
seq = seq,
grid_w = grid_w,
grid_h = grid_h,
y_range_m = y_range_m,
row_dist_m = new List<float>(row_dist_m ?? new List<float>()),
row_scale_x_m = new List<float>(row_scale_x_m ?? new List<float>()),
block = block?.Clone() ?? new VisualWorkerMessageMatrizConfiancaBlockModel()
};
}
}
public class VisualWorkerMessageMatrizConfiancaBlockModel
{
public float? d_block_line_m { get; set; }
public float d_obs_true_min_m { get; set; }
public bool blocked { get; set; }
public bool blocked_raw { get; set; }
public string reason { get; set; }
public string reason_detail { get; set; }
public VisualWorkerMessageMatrizConfiancaBlockDecisionModel decision { get; set; }
public VisualWorkerMessageMatrizConfiancaBlockDecisionTrendModel trend { get; set; }
public VisualWorkerMessageMatrizConfiancaBlockModel Clone()
{
return new VisualWorkerMessageMatrizConfiancaBlockModel()
{
d_block_line_m = d_block_line_m,
d_obs_true_min_m = d_obs_true_min_m,
blocked = blocked,
blocked_raw = blocked_raw,
reason = reason,
reason_detail = reason_detail,
decision = decision?.Clone(),
trend = trend?.Clone()
};
}
}
public class VisualWorkerMessageMatrizConfiancaBlockDecisionModel
{
public bool parar { get; set; }
public float dist_necessaria { get; set; }
public float? v_max_sugerida_mps { get; set; }
public int frames_on { get; set; }
public int frames_off { get; set; }
public int N_on { get; set; }
public int N_off { get; set; }
public string mode { get; set; }
public double risk_ema { get; set; }
public int frames_risk_on { get; set; }
public VisualWorkerMessageMatrizConfiancaBlockDecisionModel Clone()
{
return new VisualWorkerMessageMatrizConfiancaBlockDecisionModel()
{
parar = parar,
dist_necessaria = dist_necessaria,
v_max_sugerida_mps = v_max_sugerida_mps,
frames_on = frames_on,
frames_off = frames_off,
N_on = N_on,
N_off = N_off,
mode = mode,
frames_risk_on = frames_risk_on,
risk_ema = risk_ema
};
}
}
public class VisualWorkerMessageMatrizConfiancaBlockDecisionTrendModel
{
public double risk_raw { get; set; }
public double risk_ema { get; set; }
public string band { get; set; }
public double delta_central { get; set; }
public double delta_side_bias { get; set; }
public double approaching_obs_m { get; set; }
public double approaching_det_m { get; set; }
public int frames_risk_on { get; set; }
public int frames_risk_off { get; set; }
public VisualWorkerMessageMatrizConfiancaBlockDecisionTrendModel Clone()
{
return new VisualWorkerMessageMatrizConfiancaBlockDecisionTrendModel()
{
risk_raw = risk_raw,
risk_ema = risk_ema,
band = band,
delta_central = delta_central,
delta_side_bias = delta_side_bias,
approaching_obs_m = approaching_obs_m,
approaching_det_m = approaching_det_m,
frames_risk_on = frames_risk_on,
frames_risk_off = frames_risk_off
};
}
}
public class VisualWorkerMessageDeteccaoModel
{
public int label_id { get; set; }
public string label { get; set; }
public double conf { get; set; }
public List<double> bbox_norm { get; set; }
public List<double> bbox_px { get; set; }
public VisualWorkerMessageDeteccaoModel Clone()
{
return new VisualWorkerMessageDeteccaoModel()
{
label_id = label_id,
label = label,
bbox_norm = bbox_norm,
bbox_px = bbox_px,
conf = conf
};
}
}
public enum VisualWorkerCommandType
{
ScriptCarregado = 1,
CalibrarProfundidade = 2,
IniciarCameraManager = 3,
AtualizarSaudeCamera = 4,
GetCameraFrame = 5,
SaveCameraFrames = 6,
EnviarImagemMock = 7
}
}