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 CameraFrames { get; set; } = new Dictionary(); 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(CameraFrames ?? new Dictionary()), 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(); 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 _direcoesInterromperMovimento = new List { 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 Obstaculos { get; set; } public VisualWorkerDadosModel Clone() { return new VisualWorkerDadosModel() { DesvioNecessario = DesvioNecessario, DirecaoDesvio = DirecaoDesvio, ObstaculoCritico = ObstaculoCritico?.Clone(), Obstaculos = new List(Obstaculos ?? new List()), }; } } 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 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(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 anomalias { get; set; } //public List sombras { get; set; } //public VisualWorkerMessageAnaliseSoloModel solo { get; set; } //public List corredor_prof { get; set; } //public List corredor_seg { get; set; } public VisualWorkerMessageSegmentacaoSemanticaModel segmentacao { get; set; } public VisualWorkerMessageMatrizConfiancaModel matriz_confianca { get; set; } public List deteccao { get; set; } public VisualWorkerMessageAnaliseModel Clone() { return new VisualWorkerMessageAnaliseModel() { timestamp = timestamp, //anomalias = new List(anomalias ?? new List()), //sombras = new List(sombras ?? new List()), //solo = solo?.Clone(), //corredor_prof = new List(corredor_prof ?? new List()), //corredor_seg = new List(corredor_seg ?? new List()), segmentacao = segmentacao?.Clone() ?? new VisualWorkerMessageSegmentacaoSemanticaModel(), matriz_confianca = matriz_confianca?.Clone() ?? new VisualWorkerMessageMatrizConfiancaModel(), deteccao = deteccao?.Select(x => x.Clone()).ToList() ?? new List() }; } 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 bboxes = new List(); 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 perfil { get; set; } public double percent_y { get; set; } public double inclinacao { get; set; } //public List 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(perfil), percent_y = percent_y, inclinacao = inclinacao, //bbox_list = new List(bbox_list), //y_inicio = y_inicio, //altura_regiao = altura_regiao, //n_setores = n_setores, }; } } public class VisualWorkerMessageAnaliseBBoxModel { public string tipo { get; set; } public List bbox { get; set; } // [x, y, w, h] public List 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 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 bboxes_sombra { get; set; } public List corredor_perfil { get; set; } public VisualWorkerMessageRadar2DGridInfoModel grid_info { get; set; } public VisualWorkerMessageRadar2DAnaliseModel Clone() { return new VisualWorkerMessageRadar2DAnaliseModel() { bboxes_sombra = new List(bboxes_sombra), corredor_perfil = new List(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 centros_corredor { get; set; } public List 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(centros_corredor ?? new List()), larguras_px = new List(larguras_px ?? new List()), }; } } 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 y_range_m { get; set; } public List row_dist_m { get; set; } public List 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(row_dist_m ?? new List()), row_scale_x_m = new List(row_scale_x_m ?? new List()), 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 bbox_norm { get; set; } public List 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 } }