Salvando logs do visual e weed worker durante operacao
This commit is contained in:
parent
386520716e
commit
3aae33cc50
|
|
@ -48,6 +48,7 @@
|
|||
this.nudTemposalvarlog = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblTemposalvarlog = new System.Windows.Forms.Label();
|
||||
this.gpbP_Atu = new System.Windows.Forms.GroupBox();
|
||||
this.cmbAgitadorModo = new System.Windows.Forms.ComboBox();
|
||||
this.chbPulverizadorAutomatico = new System.Windows.Forms.CheckBox();
|
||||
this.nudAtuarem = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblAtuarem = new System.Windows.Forms.Label();
|
||||
|
|
@ -93,7 +94,7 @@
|
|||
this.nudCapacidadereservatorio = new System.Windows.Forms.NumericUpDown();
|
||||
this.lblUnCapcaidadereservatorio = new System.Windows.Forms.Label();
|
||||
this.lblCapacidadereservatorio = new System.Windows.Forms.Label();
|
||||
this.cmbAgitadorModo = new System.Windows.Forms.ComboBox();
|
||||
this.chbGravarDadosPosProcessamento = new System.Windows.Forms.CheckBox();
|
||||
this.gpbModulos.SuspendLayout();
|
||||
this.gpbP_Knt.SuspendLayout();
|
||||
this.gpbP_Sen.SuspendLayout();
|
||||
|
|
@ -363,6 +364,17 @@
|
|||
this.gpbP_Atu.TabStop = false;
|
||||
this.gpbP_Atu.Text = "Ajustes";
|
||||
//
|
||||
// cmbAgitadorModo
|
||||
//
|
||||
this.cmbAgitadorModo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cmbAgitadorModo.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.cmbAgitadorModo.FormattingEnabled = true;
|
||||
this.cmbAgitadorModo.Location = new System.Drawing.Point(9, 132);
|
||||
this.cmbAgitadorModo.Margin = new System.Windows.Forms.Padding(6);
|
||||
this.cmbAgitadorModo.Name = "cmbAgitadorModo";
|
||||
this.cmbAgitadorModo.Size = new System.Drawing.Size(175, 32);
|
||||
this.cmbAgitadorModo.TabIndex = 9;
|
||||
//
|
||||
// chbPulverizadorAutomatico
|
||||
//
|
||||
this.chbPulverizadorAutomatico.AutoSize = true;
|
||||
|
|
@ -802,6 +814,7 @@
|
|||
//
|
||||
// gpbConfiguracoesgerais
|
||||
//
|
||||
this.gpbConfiguracoesgerais.Controls.Add(this.chbGravarDadosPosProcessamento);
|
||||
this.gpbConfiguracoesgerais.Controls.Add(this.txtDensidadeherbicida);
|
||||
this.gpbConfiguracoesgerais.Controls.Add(this.lblUnDensidadeherbicida);
|
||||
this.gpbConfiguracoesgerais.Controls.Add(this.label2);
|
||||
|
|
@ -872,16 +885,16 @@
|
|||
this.lblCapacidadereservatorio.TabIndex = 9;
|
||||
this.lblCapacidadereservatorio.Text = "Capacidade reservatório";
|
||||
//
|
||||
// cmbAgitadorModo
|
||||
// chbGravarDadosPosProcessamento
|
||||
//
|
||||
this.cmbAgitadorModo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cmbAgitadorModo.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.cmbAgitadorModo.FormattingEnabled = true;
|
||||
this.cmbAgitadorModo.Location = new System.Drawing.Point(9, 132);
|
||||
this.cmbAgitadorModo.Margin = new System.Windows.Forms.Padding(6);
|
||||
this.cmbAgitadorModo.Name = "cmbAgitadorModo";
|
||||
this.cmbAgitadorModo.Size = new System.Drawing.Size(175, 32);
|
||||
this.cmbAgitadorModo.TabIndex = 9;
|
||||
this.chbGravarDadosPosProcessamento.AutoSize = true;
|
||||
this.chbGravarDadosPosProcessamento.Location = new System.Drawing.Point(14, 219);
|
||||
this.chbGravarDadosPosProcessamento.Margin = new System.Windows.Forms.Padding(6);
|
||||
this.chbGravarDadosPosProcessamento.Name = "chbGravarDadosPosProcessamento";
|
||||
this.chbGravarDadosPosProcessamento.Size = new System.Drawing.Size(354, 28);
|
||||
this.chbGravarDadosPosProcessamento.TabIndex = 15;
|
||||
this.chbGravarDadosPosProcessamento.Text = "Gravar dados para pós processamento";
|
||||
this.chbGravarDadosPosProcessamento.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// frmParametrizacaoOperacao
|
||||
//
|
||||
|
|
@ -998,5 +1011,6 @@
|
|||
private System.Windows.Forms.CheckBox chbFrenagem;
|
||||
private System.Windows.Forms.CheckBox chbMovAuxilioSonar;
|
||||
private System.Windows.Forms.ComboBox cmbAgitadorModo;
|
||||
private System.Windows.Forms.CheckBox chbGravarDadosPosProcessamento;
|
||||
}
|
||||
}
|
||||
|
|
@ -88,6 +88,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
txtAnteciparManobraM.Text = _Parametros.Controle.AnteciparManobraCorredorM.ToString();
|
||||
|
||||
cmbAgitadorModo.SelectedIndex = (int)_Parametros.Controle.AtuAgitadorModo;
|
||||
|
||||
chbGravarDadosPosProcessamento.Checked = _Parametros.Controle.RegistrarDadosPosProcessamento;
|
||||
}
|
||||
|
||||
private void chbD_CheckedChanged(object sender, EventArgs e)
|
||||
|
|
@ -148,6 +150,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
Variaveis.OperacaoEmAndamento.Parametros.Controle.MovAuxilioSonar = chbMovAuxilioSonar.Checked;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.FrenagemAutomaticaAoParar = chbFrenagem.Checked;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuAgitadorModo = (ModoAgitadorCalda)cmbAgitadorModo.SelectedIndex;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.RegistrarDadosPosProcessamento = chbGravarDadosPosProcessamento.Checked;
|
||||
|
||||
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios = ModulosMandatorios.Where(x => x.Utilizar).ToList();
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico = chbPulverizadorAutomatico.Checked;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
List<AtuSensoriamentoLogModel> LogsAtuador = new List<AtuSensoriamentoLogModel>();
|
||||
List<SensoriamentoMensagemJsonModel> LogsSensoriamento = new List<SensoriamentoMensagemJsonModel>();
|
||||
List<List<CameraWorkerItemModel>> LogsCam_Solo = new List<List<CameraWorkerItemModel>>();
|
||||
List<VisualWorkerModel> LogsVisualWorker = new List<VisualWorkerModel>();
|
||||
List<WeedWorkerModel> LogsWeedWorker = new List<WeedWorkerModel>();
|
||||
List<string> pathImagensSolo = new List<string>();
|
||||
List<PictureBox> picsCamSolo = new List<PictureBox>();
|
||||
List<PictureBox> picsCamSoloSeg = new List<PictureBox>();
|
||||
|
|
@ -160,6 +162,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
LogsSensoriamento = JsonConvert.DeserializeObject<SensoriamentoMensagemJsonModel[]>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, data.sen ?? Enums.T_Code.Sen.ToString())).ToList();
|
||||
pathImagensCaminho = ofd.FileName.Replace("data.lgop", data.cam_caminho + "\\");
|
||||
LogsCam_Caminho = JsonConvert.DeserializeObject<List<CameraWorkerItemModel>>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, data.cam_caminho ?? Enums.T_Code.Snr.ToString())).ToList();
|
||||
LogsVisualWorker = JsonConvert.DeserializeObject<List<VisualWorkerModel>>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, "VisualWorker")).ToList();
|
||||
LogsWeedWorker = JsonConvert.DeserializeObject<List<WeedWorkerModel>>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, "WeedWorker")).ToList();
|
||||
|
||||
pathImagensSolo = new List<string>();
|
||||
picsCamSolo = new List<PictureBox>();
|
||||
|
|
@ -843,7 +847,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
{
|
||||
new GraficoInterativoSerieModel()
|
||||
{
|
||||
Titulo = $"{camNome} RAM %",
|
||||
Titulo = $"{camNome} RAM Mb",
|
||||
Valores = camSolo.Select(x => (double)(x?.performance?.memoria_usada ?? 0)).ToList(),
|
||||
Visivel = true,
|
||||
MostrarValor = true
|
||||
|
|
@ -865,7 +869,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
{
|
||||
new GraficoInterativoSerieModel()
|
||||
{
|
||||
Titulo = $"{camNome} RAM %",
|
||||
Titulo = $"{camNome} RAM Mb",
|
||||
Valores = camCaminho.Select(x => (double)(x?.performance?.memoria_usada ?? 0)).ToList(),
|
||||
Visivel = true,
|
||||
MostrarValor = true
|
||||
|
|
@ -895,10 +899,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
dtComandosDir.Columns.Add("clTipoMovimento", "Tipo Movimento");
|
||||
|
||||
dtComandosAtu.Columns.Clear();
|
||||
dtComandosAtu.Columns.Add("clB0", "B0");
|
||||
dtComandosAtu.Columns.Add("clB1", "B1");
|
||||
dtComandosAtu.Columns.Add("clB2", "B2");
|
||||
dtComandosAtu.Columns.Add("clB3", "B3");
|
||||
for (int i = 1; i <= VariaveisEquipamento.QuantidadeBicosPulverizadores; i++)
|
||||
dtComandosAtu.Columns.Add($"clB{i}", $"B{i}");
|
||||
}
|
||||
|
||||
private void InicializarCombosBusca()
|
||||
|
|
@ -1029,10 +1031,10 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
private Bitmap CarregarImagemCamera(string Caminho, string complemento = "")
|
||||
{
|
||||
string caminhoCompleto = Caminho + trbMomento.Value + ".jpeg";
|
||||
string caminhoCompleto = Caminho + trbMomento.Value + ".jpg";
|
||||
if (!string.IsNullOrEmpty(complemento))
|
||||
{
|
||||
caminhoCompleto = caminhoCompleto.Replace(".jpeg", $"{complemento}.jpeg");
|
||||
caminhoCompleto = caminhoCompleto.Replace(".jpg", $"{complemento}.jpg");
|
||||
}
|
||||
Bitmap frame = new Bitmap(1, 1);
|
||||
using (Graphics g = Graphics.FromImage(frame))
|
||||
|
|
@ -1126,6 +1128,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
{
|
||||
var Log = LogsOperacao[idxMomentoAtual];
|
||||
var LogAtu = LogsAtuador[idxMomentoAtual];
|
||||
var LogWw = LogsWeedWorker[idxMomentoAtual];
|
||||
|
||||
lblPercentualBateria.Text = $"Bateria {Log.Bateria.PercentualBateria.ToString("0.00")}%";
|
||||
FuncoesGlobais.PreencheValorProgressBar(pgbPercentualBateria, Log.Bateria.PercentualBateria);
|
||||
|
|
@ -1145,7 +1148,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
txtHerbicidaPorErva.Text = LogAtu.HerbicidaPorAtuacao.ToString("0.00") + " ml";
|
||||
txtDentroRua.Text = Log.Trajetoria.CorredorAtual.Dentro ? "Sim" : "Não";
|
||||
txtDirecaoCarro.Text = Log.Trajetoria.DirecaoCaminho.ToString() + " (" + Log.Trajetoria.CorredorAtual.Idx + " - " + Log.Trajetoria.ProximoPonto.idxPonto + " - " + Log.Trajetoria.ProximoPonto.idxPontoCorredor + ")";
|
||||
txtErvasNoRadar.Text = Log.Atuador.ErvasNoRadar.ToString() + " (" + (Log.Atuador.PercentualErvasNoRadar * 100).ToString("0.00") + "%)";
|
||||
txtErvasNoRadar.Text = LogWw.Analise.ervas_no_radar + " (" + (LogWw.Analise.percentual_ervas_no_radar).ToString("0.00") + "%)";
|
||||
txtErvasTerreno.Text = Log.Atuador.PercentualErvasTerreno.ToString("0.00");
|
||||
txtTipoMovimento.Text = Log.Controle.TipoMovimento.ToString();
|
||||
txtVelocidade.Text = (Log.Movimentacao.VelocidadeMedia * 3.6).ToString("0.00") + " km/h (" + Log.Movimentacao.VelocidadeMedia.ToString("0.00") + " m/s)";
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ namespace AgroBase.Forms
|
|||
lblLeituraDebug.Text = $"Leitura em: " + (analise?.timestamp ?? DateTime.MinValue).ToString("dd/MM/yyyy HH:mm:ss");
|
||||
OAKCameraFrameModel frame = VisualWorkerService.DadosLeitura.CameraFrames[TipoFrameCamera.Heatmap];
|
||||
picDebug.Image?.Dispose();
|
||||
picDebug.Image = analise.PlotarAnalise(frame);
|
||||
//picDebug.Image = analise.PlotarAnalise(frame);
|
||||
|
||||
//PreencherGridAnomalias(analise.anomalias ?? new List<VisualWorkerMessageAnaliseBBoxModel>());
|
||||
//PreencherGridSolo(analise.solo?.bbox_list ?? new List<VisualWorkerMessageAnaliseBBoxModel>());
|
||||
|
|
@ -254,7 +254,7 @@ namespace AgroBase.Forms
|
|||
chartPerfilSolo.Legends[0].Docking = Docking.Bottom;
|
||||
}
|
||||
|
||||
void PlotarGraficoPerfilCorredor(List<VisualWorkerMessageRadar2DPerfilModel> perfilCorredor)
|
||||
/*void PlotarGraficoPerfilCorredor(List<VisualWorkerMessageRadar2DPerfilModel> perfilCorredor)
|
||||
{
|
||||
chartCorredor.Series.Clear();
|
||||
|
||||
|
|
@ -303,7 +303,7 @@ namespace AgroBase.Forms
|
|||
|
||||
chartCorredor.ChartAreas[0].AxisX.Crossing = 0; // 🔥 Eixo X cruza no centro (0 lateral)
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
private void pnlInclinacao_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -405,6 +405,7 @@ namespace AgroBase.Models
|
|||
AtuPercentualInicioPulverizacao = 70,
|
||||
AtuPressaoLinha = 85,
|
||||
AtuAgitadorModo = ModoAgitadorCalda.SemAgitacao,
|
||||
AtuModoControle = ModoControleBomba.OnOff
|
||||
};
|
||||
p.ModulosMandatorios = new List<OperacaoModulosMandatoriosModel>()
|
||||
{
|
||||
|
|
@ -515,7 +516,7 @@ namespace AgroBase.Models
|
|||
AtuPercentualInicioPulverizacao = 70,
|
||||
AtuPressaoLinha = 85,
|
||||
AtuAgitadorModo = ModoAgitadorCalda.Continuo,
|
||||
AtuModoControle = ModoControleBomba.PID,
|
||||
AtuModoControle = ModoControleBomba.OnOff,
|
||||
};
|
||||
p.ModulosMandatorios = new List<OperacaoModulosMandatoriosModel>()
|
||||
{
|
||||
|
|
@ -2087,7 +2088,9 @@ namespace AgroBase.Models
|
|||
SalvarLogLine(T_Code.Sen.ToString(), logSen);
|
||||
|
||||
SalvarLogCameraSolo();
|
||||
SalvarLogLine("WeedWorker", Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorErvas);
|
||||
SalvarLogCameraCaminho();
|
||||
SalvarLogLine("VisualWorker", Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual);
|
||||
|
||||
string ArquivoOp = Variaveis.CaminhoOperacoes + Variaveis.OperacaoEmAndamento.ID + "/data.lgop";
|
||||
if (!File.Exists(ArquivoOp))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using static AgroBase.Models.Enums;
|
||||
|
||||
namespace AgroBase.Models.Operadores
|
||||
|
|
@ -13,12 +14,15 @@ namespace AgroBase.Models.Operadores
|
|||
public bool Pronto { get; set; }
|
||||
public DateTime ProntoEm { get; set; }
|
||||
public DateTime UltimaMensagem { get; set; }
|
||||
[JsonIgnore]
|
||||
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 bool StatusValido => new List<StatusModulo>() { StatusModulo.Operante, StatusModulo.Alerta }.Contains(Status);
|
||||
public VisualWorkerResumoModel Resumo { get; set; }
|
||||
public VisualWorkerPerformanceModel Performance { get; set; } = new VisualWorkerPerformanceModel();
|
||||
public VisualWorkerRedisTimestampsModel Timestamps { get; set; } = new VisualWorkerRedisTimestampsModel();
|
||||
|
||||
public VisualWorkerModel Clone()
|
||||
{
|
||||
|
|
@ -33,7 +37,9 @@ namespace AgroBase.Models.Operadores
|
|||
Imu = Imu?.Clone(),
|
||||
UltimaMensagem = UltimaMensagem,
|
||||
Status = Status,
|
||||
Resumo = Resumo?.Clone()
|
||||
Resumo = Resumo?.Clone(),
|
||||
Performance = Performance?.Clone() ?? new VisualWorkerPerformanceModel(),
|
||||
Timestamps = Timestamps?.Clone() ?? new VisualWorkerRedisTimestampsModel(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +54,22 @@ namespace AgroBase.Models.Operadores
|
|||
Imu = new VisualWorkerMessageIMUModel();
|
||||
Resumo = new VisualWorkerResumoModel();
|
||||
Status = StatusModulo.Desconectado;
|
||||
Performance = new VisualWorkerPerformanceModel();
|
||||
Timestamps = new VisualWorkerRedisTimestampsModel();
|
||||
}
|
||||
}
|
||||
|
||||
public class VisualWorkerRedisTimestampsModel
|
||||
{
|
||||
public double analise { get; set; }
|
||||
public double segmentacao { get; set; }
|
||||
public double deteccao { get; set; }
|
||||
public double matriz_confianca { get; set; }
|
||||
public double performance_visual { get; set; }
|
||||
|
||||
public VisualWorkerRedisTimestampsModel Clone()
|
||||
{
|
||||
return (VisualWorkerRedisTimestampsModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,130 +146,48 @@ namespace AgroBase.Models.Operadores
|
|||
}
|
||||
}
|
||||
|
||||
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 bool valido { get; set; }
|
||||
public double 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 double frequencia_hz { get; set; }
|
||||
public double latencia_ms { get; set; }
|
||||
|
||||
public double rugosidade { get; set; }
|
||||
public double impacto { get; set; }
|
||||
public double estabilidade { get; set; }
|
||||
|
||||
public bool movimento_detectado { get; set; }
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; } = new Dictionary<string, JToken>();
|
||||
|
||||
public VisualWorkerMessageIMUModel Clone()
|
||||
{
|
||||
return new VisualWorkerMessageIMUModel()
|
||||
return new VisualWorkerMessageIMUModel
|
||||
{
|
||||
valido = valido,
|
||||
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
|
||||
yaw_fixed = yaw_fixed,
|
||||
frequencia_hz = frequencia_hz,
|
||||
latencia_ms = latencia_ms,
|
||||
rugosidade = rugosidade,
|
||||
impacto = impacto,
|
||||
estabilidade = estabilidade,
|
||||
movimento_detectado = movimento_detectado,
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -255,160 +195,20 @@ namespace AgroBase.Models.Operadores
|
|||
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 VisualWorkerMessageSegmentacaoSemanticaModel segmentacao { get; set; } = new VisualWorkerMessageSegmentacaoSemanticaModel();
|
||||
public VisualWorkerMessageMatrizConfiancaModel matriz_confianca { get; set; } = new VisualWorkerMessageMatrizConfiancaModel();
|
||||
public List<VisualWorkerMessageDeteccaoModel> deteccao { get; set; } = new List<VisualWorkerMessageDeteccaoModel>();
|
||||
|
||||
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
|
||||
|
|
@ -423,142 +223,6 @@ namespace AgroBase.Models.Operadores
|
|||
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; }
|
||||
|
|
@ -569,8 +233,8 @@ namespace AgroBase.Models.Operadores
|
|||
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 List<double?[]> centros_corredor { get; set; } = new List<double?[]>();
|
||||
public List<int> larguras_px { get; set; } = new List<int>();
|
||||
|
||||
public VisualWorkerMessageSegmentacaoSemanticaModel Clone()
|
||||
{
|
||||
|
|
@ -583,8 +247,11 @@ namespace AgroBase.Models.Operadores
|
|||
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?[]>()),
|
||||
status_corredor_debug = status_corredor_debug?.Clone(),
|
||||
centros_corredor = centros_corredor?
|
||||
.Select(x => x?.ToArray())
|
||||
.ToList()
|
||||
?? new List<double?[]>(),
|
||||
larguras_px = new List<int>(larguras_px ?? new List<int>()),
|
||||
};
|
||||
}
|
||||
|
|
@ -601,6 +268,30 @@ namespace AgroBase.Models.Operadores
|
|||
public StatusCarroMapa status_heuristico { get; set; }
|
||||
public string status_heuristico_nome { get; set; }
|
||||
public dynamic heuristica_debug { get; set; }
|
||||
|
||||
public VisualWorkerMessageSegmentacaoSemanticaDebugCorredorModel Clone()
|
||||
{
|
||||
return new VisualWorkerMessageSegmentacaoSemanticaDebugCorredorModel
|
||||
{
|
||||
origem_status = origem_status,
|
||||
status_modelo = status_modelo,
|
||||
status_modelo_nome = status_modelo_nome,
|
||||
status_modelo_label_name = status_modelo_label_name,
|
||||
status_modelo_conf = status_modelo_conf,
|
||||
status_modelo_probs = CloneDynamic(status_modelo_probs),
|
||||
status_heuristico = status_heuristico,
|
||||
status_heuristico_nome = status_heuristico_nome,
|
||||
heuristica_debug = CloneDynamic(heuristica_debug)
|
||||
};
|
||||
}
|
||||
|
||||
private static object CloneDynamic(object valor)
|
||||
{
|
||||
if (valor is JToken token)
|
||||
return token.DeepClone();
|
||||
|
||||
return valor;
|
||||
}
|
||||
}
|
||||
|
||||
public class VisualWorkerMessageMatrizConfiancaModel
|
||||
|
|
@ -609,10 +300,10 @@ namespace AgroBase.Models.Operadores
|
|||
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 List<float> y_range_m { get; set; } = new List<float>();
|
||||
public List<float> row_dist_m { get; set; } = new List<float>();
|
||||
public List<float> row_scale_x_m { get; set; } = new List<float>();
|
||||
public VisualWorkerMessageMatrizConfiancaBlockModel block { get; set; } = new VisualWorkerMessageMatrizConfiancaBlockModel();
|
||||
|
||||
public VisualWorkerMessageMatrizConfiancaModel Clone()
|
||||
{
|
||||
|
|
@ -622,10 +313,10 @@ namespace AgroBase.Models.Operadores
|
|||
seq = seq,
|
||||
grid_w = grid_w,
|
||||
grid_h = grid_h,
|
||||
y_range_m = y_range_m,
|
||||
y_range_m = new List<float>(y_range_m ?? new List<float>()),
|
||||
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()
|
||||
block = block?.Clone() ?? new VisualWorkerMessageMatrizConfiancaBlockModel(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -728,9 +419,9 @@ namespace AgroBase.Models.Operadores
|
|||
public string track_status { get; set; }
|
||||
public bool tem_tracker { get; set; }
|
||||
public List<double> xyz_m { get; set; }
|
||||
public double distancia_m { get; set; }
|
||||
public double lateral_m { get; set; }
|
||||
public double altura_relativa_m { get; set; }
|
||||
public double? distancia_m { get; set; }
|
||||
public double? lateral_m { get; set; }
|
||||
public double? altura_relativa_m { get; set; }
|
||||
public List<double> bbox_full { get; set; }
|
||||
|
||||
public VisualWorkerMessageDeteccaoModel Clone()
|
||||
|
|
@ -739,22 +430,158 @@ namespace AgroBase.Models.Operadores
|
|||
{
|
||||
label_id = label_id,
|
||||
label = label,
|
||||
bbox_norm = bbox_norm,
|
||||
bbox_px = bbox_px,
|
||||
bbox_norm = bbox_norm != null
|
||||
? new List<double>(bbox_norm)
|
||||
: new List<double>(),
|
||||
bbox_px = bbox_px != null
|
||||
? new List<double>(bbox_px)
|
||||
: new List<double>(),
|
||||
conf = conf,
|
||||
track_id = track_id,
|
||||
track_status = track_status,
|
||||
tem_tracker = tem_tracker,
|
||||
xyz_m = xyz_m,
|
||||
xyz_m = xyz_m != null
|
||||
? new List<double>(xyz_m)
|
||||
: new List<double>(),
|
||||
distancia_m = distancia_m,
|
||||
lateral_m = lateral_m,
|
||||
altura_relativa_m = altura_relativa_m,
|
||||
bbox_full = bbox_full,
|
||||
bbox_full = bbox_full != null
|
||||
? new List<double>(bbox_full)
|
||||
: new List<double>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class VisualWorkerPerformanceModel
|
||||
{
|
||||
public double timestamp { get; set; }
|
||||
|
||||
public Dictionary<string, VisualWorkerPerformanceLoopModel> loops { get; set; }
|
||||
= new Dictionary<string, VisualWorkerPerformanceLoopModel>();
|
||||
|
||||
public JObject sync { get; set; } = new JObject();
|
||||
|
||||
public JObject camera_cache { get; set; } = new JObject();
|
||||
|
||||
public VisualWorkerPerformanceCacheModel visual_cache { get; set; }
|
||||
= new VisualWorkerPerformanceCacheModel();
|
||||
|
||||
public VisualWorkerPerformancePublicacaoModel pub_debug { get; set; }
|
||||
= new VisualWorkerPerformancePublicacaoModel();
|
||||
|
||||
public JObject contadores { get; set; } = new JObject();
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; }
|
||||
= new Dictionary<string, JToken>();
|
||||
|
||||
public VisualWorkerPerformanceModel Clone()
|
||||
{
|
||||
return new VisualWorkerPerformanceModel
|
||||
{
|
||||
timestamp = timestamp,
|
||||
loops = loops?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.Clone()
|
||||
) ?? new Dictionary<string, VisualWorkerPerformanceLoopModel>(),
|
||||
|
||||
sync = sync != null ? (JObject)sync.DeepClone() : new JObject(),
|
||||
camera_cache = camera_cache != null
|
||||
? (JObject)camera_cache.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
visual_cache = visual_cache?.Clone()
|
||||
?? new VisualWorkerPerformanceCacheModel(),
|
||||
|
||||
pub_debug = pub_debug?.Clone()
|
||||
?? new VisualWorkerPerformancePublicacaoModel(),
|
||||
|
||||
contadores = contadores != null
|
||||
? (JObject)contadores.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class VisualWorkerPerformanceLoopModel
|
||||
{
|
||||
public double fps_real { get; set; }
|
||||
|
||||
public JObject periodo_ms { get; set; } = new JObject();
|
||||
public JObject latencia_ms { get; set; } = new JObject();
|
||||
|
||||
public Dictionary<string, JObject> metrics_ms { get; set; }
|
||||
= new Dictionary<string, JObject>();
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; }
|
||||
= new Dictionary<string, JToken>();
|
||||
|
||||
public VisualWorkerPerformanceLoopModel Clone()
|
||||
{
|
||||
return new VisualWorkerPerformanceLoopModel
|
||||
{
|
||||
fps_real = fps_real,
|
||||
periodo_ms = periodo_ms != null
|
||||
? (JObject)periodo_ms.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
latencia_ms = latencia_ms != null
|
||||
? (JObject)latencia_ms.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
metrics_ms = metrics_ms?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value != null
|
||||
? (JObject)x.Value.DeepClone()
|
||||
: new JObject()
|
||||
) ?? new Dictionary<string, JObject>(),
|
||||
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class VisualWorkerPerformanceCacheModel
|
||||
{
|
||||
public double seg_ts { get; set; }
|
||||
public double det_ts { get; set; }
|
||||
public double grid_ts { get; set; }
|
||||
|
||||
public bool tem_seg { get; set; }
|
||||
public bool tem_grid { get; set; }
|
||||
|
||||
public VisualWorkerPerformanceCacheModel Clone()
|
||||
{
|
||||
return (VisualWorkerPerformanceCacheModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class VisualWorkerPerformancePublicacaoModel
|
||||
{
|
||||
public double ts { get; set; }
|
||||
public int publicou { get; set; }
|
||||
public int campos { get; set; }
|
||||
public double redis_ms { get; set; }
|
||||
|
||||
public VisualWorkerPerformancePublicacaoModel Clone()
|
||||
{
|
||||
return (VisualWorkerPerformancePublicacaoModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum VisualWorkerCommandType
|
||||
{
|
||||
ScriptCarregado = 1,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static AgroBase.Models.Enums;
|
||||
|
||||
namespace AgroBase.Models.Operadores
|
||||
|
|
@ -11,21 +14,35 @@ namespace AgroBase.Models.Operadores
|
|||
public bool Pronto { get; set; }
|
||||
public DateTime ProntoEm { get; set; }
|
||||
public DateTime UltimaMensagem { get; set; }
|
||||
[JsonIgnore]
|
||||
public Dictionary<TipoFrameCamera, OAKCameraFrameModel> CameraFrames { get; set; } = new Dictionary<TipoFrameCamera, OAKCameraFrameModel>();
|
||||
public WeedWorkerAnaliseModel Analise { get; set; } = new WeedWorkerAnaliseModel();
|
||||
public WeedWorkerPerformanceModel Performance { get; set; } = new WeedWorkerPerformanceModel();
|
||||
public WeedWorkerAnaliseMetricasModel MetricasAnalise { get; set; } = new WeedWorkerAnaliseMetricasModel();
|
||||
public WeedWorkerRedisTimestampsModel Timestamps { get; set; } = new WeedWorkerRedisTimestampsModel();
|
||||
|
||||
|
||||
public WeedWorkerModel Clone()
|
||||
{
|
||||
return new WeedWorkerModel()
|
||||
return new WeedWorkerModel
|
||||
{
|
||||
Iniciado = Iniciado,
|
||||
IniciadoEm = IniciadoEm,
|
||||
Pronto = Pronto,
|
||||
ProntoEm = ProntoEm,
|
||||
CameraFrames = new Dictionary<TipoFrameCamera, OAKCameraFrameModel>(CameraFrames ?? new Dictionary<TipoFrameCamera, OAKCameraFrameModel>()),
|
||||
Analise = Analise.Clone(),
|
||||
UltimaMensagem = UltimaMensagem,
|
||||
|
||||
Analise = Analise?.Clone()
|
||||
?? new WeedWorkerAnaliseModel(),
|
||||
|
||||
MetricasAnalise = MetricasAnalise?.Clone()
|
||||
?? new WeedWorkerAnaliseMetricasModel(),
|
||||
|
||||
Performance = Performance?.Clone()
|
||||
?? new WeedWorkerPerformanceModel(),
|
||||
|
||||
Timestamps = Timestamps?.Clone()
|
||||
?? new WeedWorkerRedisTimestampsModel()
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -33,9 +50,73 @@ namespace AgroBase.Models.Operadores
|
|||
{
|
||||
Iniciado = false;
|
||||
IniciadoEm = DateTime.MinValue;
|
||||
|
||||
Pronto = false;
|
||||
ProntoEm = DateTime.MinValue;
|
||||
CameraFrames = new Dictionary<TipoFrameCamera, OAKCameraFrameModel>();
|
||||
|
||||
UltimaMensagem = DateTime.MinValue;
|
||||
|
||||
CameraFrames =
|
||||
new Dictionary<TipoFrameCamera, OAKCameraFrameModel>();
|
||||
|
||||
Analise = new WeedWorkerAnaliseModel();
|
||||
MetricasAnalise = new WeedWorkerAnaliseMetricasModel();
|
||||
Performance = new WeedWorkerPerformanceModel();
|
||||
Timestamps = new WeedWorkerRedisTimestampsModel();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerAnaliseMetricasModel
|
||||
{
|
||||
public double ts_analise { get; set; }
|
||||
|
||||
public double fps_model { get; set; }
|
||||
public double fps_inferencia { get; set; }
|
||||
|
||||
public double infer_ms { get; set; }
|
||||
public double infer_gpu_ms { get; set; }
|
||||
|
||||
public WeedWorkerAnaliseMetricasModel Clone()
|
||||
{
|
||||
return (WeedWorkerAnaliseMetricasModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerAnaliseEnvelopeModel
|
||||
{
|
||||
public double ts_analise { get; set; }
|
||||
|
||||
public double fps_model { get; set; }
|
||||
public double fps_inferencia { get; set; }
|
||||
|
||||
public double infer_ms { get; set; }
|
||||
public double infer_gpu_ms { get; set; }
|
||||
|
||||
public WeedWorkerAnaliseModel analise { get; set; }
|
||||
= new WeedWorkerAnaliseModel();
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; }
|
||||
= new Dictionary<string, JToken>();
|
||||
|
||||
public WeedWorkerAnaliseEnvelopeModel Clone()
|
||||
{
|
||||
return new WeedWorkerAnaliseEnvelopeModel
|
||||
{
|
||||
ts_analise = ts_analise,
|
||||
fps_model = fps_model,
|
||||
fps_inferencia = fps_inferencia,
|
||||
infer_ms = infer_ms,
|
||||
infer_gpu_ms = infer_gpu_ms,
|
||||
|
||||
analise = analise?.Clone()
|
||||
?? new WeedWorkerAnaliseModel(),
|
||||
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,9 +132,11 @@ namespace AgroBase.Models.Operadores
|
|||
public double timestamp { get; set; }
|
||||
public int height { get; set; }
|
||||
public int width { get; set; }
|
||||
public Dictionary<int, bool> controle { get; set; }
|
||||
public Dictionary<int, bool> controle { get; set; } = new Dictionary<int, bool>();
|
||||
public bool ervas_no_radar { get; set; }
|
||||
public WeedWorkerAnaliseEstatisticasModel estatisticas { get; set; }
|
||||
public double fracao_ervas_no_radar { get; set; }
|
||||
public double percentual_ervas_no_radar { get; set; }
|
||||
public WeedWorkerAnaliseEstatisticasModel estatisticas { get; set; } = new WeedWorkerAnaliseEstatisticasModel();
|
||||
|
||||
public WeedWorkerAnaliseModel Clone()
|
||||
{
|
||||
|
|
@ -64,28 +147,17 @@ namespace AgroBase.Models.Operadores
|
|||
height = height,
|
||||
width = width,
|
||||
ervas_no_radar = ervas_no_radar,
|
||||
fracao_ervas_no_radar = fracao_ervas_no_radar,
|
||||
percentual_ervas_no_radar = percentual_ervas_no_radar,
|
||||
estatisticas = estatisticas?.Clone()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerAnaliseDeteccaoModel
|
||||
{
|
||||
public int id { get; set; }
|
||||
public double[] centro { get; set; }
|
||||
public double[] bbox { get; set; }
|
||||
public int class_id { get; set; }
|
||||
public int ultimo_frame { get; set; }
|
||||
public int frames_detectada { get; set; }
|
||||
public string status { get; set; }
|
||||
public string descricao { get; set; }
|
||||
public double confianca { get; set; }
|
||||
}
|
||||
|
||||
public class WeedWorkerAnaliseEstatisticasModel
|
||||
{
|
||||
public WeedWorkerAnaliseEstatisticasErvasModel erva { get; set; }
|
||||
public WeedWorkerAnaliseEstatisticasBicosModel bicos { get; set; }
|
||||
public WeedWorkerAnaliseEstatisticasErvasModel erva { get; set; } = new WeedWorkerAnaliseEstatisticasErvasModel();
|
||||
public WeedWorkerAnaliseEstatisticasBicosModel bicos { get; set; } = new WeedWorkerAnaliseEstatisticasBicosModel();
|
||||
|
||||
public WeedWorkerAnaliseEstatisticasModel Clone()
|
||||
{
|
||||
|
|
@ -120,19 +192,62 @@ namespace AgroBase.Models.Operadores
|
|||
|
||||
public class WeedWorkerAnaliseEstatisticasBicosModel
|
||||
{
|
||||
public List<double> larguras { get; set; }
|
||||
public List<double> contagem_cana_px_por_bico { get; set; }
|
||||
public List<double> contagem_cana_frac_por_bico { get; set; }
|
||||
public string motivo { get; set; }
|
||||
|
||||
public List<double> frac_erva_por_bico { get; set; }
|
||||
= new List<double>();
|
||||
|
||||
public List<double> ema_frac_por_bico { get; set; }
|
||||
= new List<double>();
|
||||
|
||||
public WeedWorkerAnaliseEstatisticasBicosFaixaModel faixa { get; set; }
|
||||
= new WeedWorkerAnaliseEstatisticasBicosFaixaModel();
|
||||
|
||||
public List<double> larguras { get; set; }
|
||||
= new List<double>();
|
||||
|
||||
public int shift_px { get; set; }
|
||||
|
||||
public double thr_on_eff { get; set; }
|
||||
public double thr_off_eff { get; set; }
|
||||
|
||||
public List<int> on_cnt { get; set; }
|
||||
= new List<int>();
|
||||
|
||||
public List<int> off_cnt { get; set; }
|
||||
= new List<int>();
|
||||
|
||||
public List<bool> estado_bico { get; set; }
|
||||
= new List<bool>();
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; }
|
||||
= new Dictionary<string, JToken>();
|
||||
|
||||
public WeedWorkerAnaliseEstatisticasBicosModel Clone()
|
||||
{
|
||||
return new WeedWorkerAnaliseEstatisticasBicosModel()
|
||||
return new WeedWorkerAnaliseEstatisticasBicosModel
|
||||
{
|
||||
larguras = new List<double>(larguras),
|
||||
contagem_cana_frac_por_bico = new List<double>(contagem_cana_frac_por_bico ?? new List<double>()),
|
||||
contagem_cana_px_por_bico = new List<double>(contagem_cana_px_por_bico ?? new List<double>()),
|
||||
motivo = motivo,
|
||||
frac_erva_por_bico =
|
||||
new List<double>(frac_erva_por_bico ?? new List<double>()),
|
||||
ema_frac_por_bico =
|
||||
new List<double>(ema_frac_por_bico ?? new List<double>()),
|
||||
faixa = faixa?.Clone()
|
||||
?? new WeedWorkerAnaliseEstatisticasBicosFaixaModel(),
|
||||
larguras =
|
||||
new List<double>(larguras ?? new List<double>()),
|
||||
shift_px = shift_px,
|
||||
thr_on_eff = thr_on_eff,
|
||||
thr_off_eff = thr_off_eff,
|
||||
on_cnt = new List<int>(on_cnt ?? new List<int>()),
|
||||
off_cnt = new List<int>(off_cnt ?? new List<int>()),
|
||||
estado_bico =
|
||||
new List<bool>(estado_bico ?? new List<bool>()),
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -152,6 +267,144 @@ namespace AgroBase.Models.Operadores
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public class WeedWorkerPerformanceModel
|
||||
{
|
||||
public double timestamp { get; set; }
|
||||
|
||||
public Dictionary<string, WeedWorkerPerformanceLoopModel> loops { get; set; }
|
||||
= new Dictionary<string, WeedWorkerPerformanceLoopModel>();
|
||||
|
||||
public JObject sync { get; set; } = new JObject();
|
||||
|
||||
public WeedWorkerPerformanceCacheModel weed_cache { get; set; }
|
||||
= new WeedWorkerPerformanceCacheModel();
|
||||
|
||||
public WeedWorkerPerformancePublicacaoModel pub_debug { get; set; }
|
||||
= new WeedWorkerPerformancePublicacaoModel();
|
||||
|
||||
public JObject contadores { get; set; } = new JObject();
|
||||
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; }
|
||||
= new Dictionary<string, JToken>();
|
||||
|
||||
public WeedWorkerPerformanceModel Clone()
|
||||
{
|
||||
return new WeedWorkerPerformanceModel
|
||||
{
|
||||
timestamp = timestamp,
|
||||
|
||||
loops = loops?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.Clone()
|
||||
) ?? new Dictionary<string, WeedWorkerPerformanceLoopModel>(),
|
||||
|
||||
sync = sync != null
|
||||
? (JObject)sync.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
weed_cache = weed_cache?.Clone()
|
||||
?? new WeedWorkerPerformanceCacheModel(),
|
||||
|
||||
pub_debug = pub_debug?.Clone()
|
||||
?? new WeedWorkerPerformancePublicacaoModel(),
|
||||
|
||||
contadores = contadores != null
|
||||
? (JObject)contadores.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerPerformanceLoopModel
|
||||
{
|
||||
public double fps_real { get; set; }
|
||||
|
||||
public JObject periodo_ms { get; set; } = new JObject();
|
||||
public JObject latencia_ms { get; set; } = new JObject();
|
||||
|
||||
public Dictionary<string, JObject> metrics_ms { get; set; }
|
||||
= new Dictionary<string, JObject>();
|
||||
|
||||
[Newtonsoft.Json.JsonExtensionData]
|
||||
public IDictionary<string, JToken> Extra { get; set; }
|
||||
= new Dictionary<string, JToken>();
|
||||
|
||||
public WeedWorkerPerformanceLoopModel Clone()
|
||||
{
|
||||
return new WeedWorkerPerformanceLoopModel
|
||||
{
|
||||
fps_real = fps_real,
|
||||
|
||||
periodo_ms = periodo_ms != null
|
||||
? (JObject)periodo_ms.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
latencia_ms = latencia_ms != null
|
||||
? (JObject)latencia_ms.DeepClone()
|
||||
: new JObject(),
|
||||
|
||||
metrics_ms = metrics_ms?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value != null
|
||||
? (JObject)x.Value.DeepClone()
|
||||
: new JObject()
|
||||
) ?? new Dictionary<string, JObject>(),
|
||||
|
||||
Extra = Extra?.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value?.DeepClone()
|
||||
) ?? new Dictionary<string, JToken>()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerPerformanceCacheModel
|
||||
{
|
||||
public double tensor_ts { get; set; }
|
||||
public double? tensor_age_ms { get; set; }
|
||||
public double tensor_consumido_ts { get; set; }
|
||||
public bool tem_tensor { get; set; }
|
||||
|
||||
public WeedWorkerPerformanceCacheModel Clone()
|
||||
{
|
||||
return (WeedWorkerPerformanceCacheModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerPerformancePublicacaoModel
|
||||
{
|
||||
public double ts { get; set; }
|
||||
public int publicou { get; set; }
|
||||
public int campos { get; set; }
|
||||
public double redis_ms { get; set; }
|
||||
|
||||
public WeedWorkerPerformancePublicacaoModel Clone()
|
||||
{
|
||||
return (WeedWorkerPerformancePublicacaoModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeedWorkerRedisTimestampsModel
|
||||
{
|
||||
public double analise { get; set; }
|
||||
public double analise_weed { get; set; }
|
||||
public double performance_weed { get; set; }
|
||||
|
||||
public WeedWorkerRedisTimestampsModel Clone()
|
||||
{
|
||||
return (WeedWorkerRedisTimestampsModel)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum WeedWorkerCommandType
|
||||
{
|
||||
ScriptCarregado = 1,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ namespace AgroBase.Services.Operadores
|
|||
|
||||
private bool DebugMode = true;
|
||||
|
||||
static long _lastTsVW = -1;
|
||||
private static double _lastTsSegmentacao = -1;
|
||||
private static double _lastTsDeteccao = -1;
|
||||
private static double _lastTsMatrizConfianca = -1;
|
||||
private static double _lastTsPerformanceVisual = -1;
|
||||
|
||||
public void MostrarLog(string message, int limite = 500)
|
||||
{
|
||||
|
|
@ -143,92 +146,211 @@ namespace AgroBase.Services.Operadores
|
|||
|
||||
public static void AtualizarAnalise()
|
||||
{
|
||||
// IMU (simples e direto)
|
||||
string imuJson = RedisService.Get(RedisService.ModKey(Enums.T_Code.Imu));
|
||||
if (!string.IsNullOrWhiteSpace(imuJson))
|
||||
{
|
||||
try
|
||||
{
|
||||
DadosLeitura.Imu = JsonConvert.DeserializeObject<VisualWorkerMessageIMUModel>(imuJson);
|
||||
}
|
||||
catch { /* opcional: logar erro */ }
|
||||
}
|
||||
AtualizarImu();
|
||||
|
||||
DadosLeitura.Status = HealthWorkerService.ModulosSaude.FirstOrDefault(x => x.modulo == Enums.T_Code.Snr)?.status ?? Enums.StatusModulo.Desconectado;
|
||||
DadosLeitura.Status =
|
||||
HealthWorkerService.ModulosSaude
|
||||
.FirstOrDefault(x => x.modulo == Enums.T_Code.Snr)?.status
|
||||
?? Enums.StatusModulo.Desconectado;
|
||||
|
||||
// VisualWorker
|
||||
var json = RedisService.Get(CtxKey.DadosVisualWorker);
|
||||
if (string.IsNullOrWhiteSpace(json)) return;
|
||||
string json = RedisService.Get(CtxKey.DadosVisualWorker);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
return;
|
||||
|
||||
JObject root;
|
||||
|
||||
try
|
||||
{
|
||||
root = JObject.Parse(json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Opcional: registrar payload inválido
|
||||
return;
|
||||
}
|
||||
|
||||
double tsAnalise =
|
||||
root["ts_analise"]?.Value<double>() ?? 0.0;
|
||||
|
||||
double tsSegmentacao =
|
||||
root["ts_segmentacao"]?.Value<double>() ?? 0.0;
|
||||
|
||||
double tsDeteccao =
|
||||
root["ts_deteccao"]?.Value<double>() ?? 0.0;
|
||||
|
||||
double tsMatriz =
|
||||
root["ts_matriz_confianca"]?.Value<double>() ?? 0.0;
|
||||
|
||||
double tsPerformance =
|
||||
root["ts_performance_visual"]?.Value<double>() ?? 0.0;
|
||||
|
||||
DadosLeitura.Timestamps.analise = tsAnalise;
|
||||
DadosLeitura.Timestamps.segmentacao = tsSegmentacao;
|
||||
DadosLeitura.Timestamps.deteccao = tsDeteccao;
|
||||
DadosLeitura.Timestamps.matriz_confianca = tsMatriz;
|
||||
DadosLeitura.Timestamps.performance_visual = tsPerformance;
|
||||
|
||||
if (tsAnalise > 0)
|
||||
{
|
||||
DadosLeitura.Analises.timestamp =
|
||||
FuncoesGlobais.UnixToDateTime(tsAnalise.ToString(
|
||||
System.Globalization.CultureInfo.InvariantCulture
|
||||
));
|
||||
}
|
||||
|
||||
if (tsSegmentacao > 0 &&
|
||||
tsSegmentacao != _lastTsSegmentacao)
|
||||
{
|
||||
var token = root["segmentacao"];
|
||||
|
||||
if (token != null &&
|
||||
token.Type != JTokenType.Null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var model =
|
||||
token.ToObject<VisualWorkerMessageSegmentacaoSemanticaModel>();
|
||||
|
||||
if (model != null)
|
||||
DadosLeitura.Analises.segmentacao = model;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return; // payload inválido
|
||||
// Opcional: registrar erro de contrato
|
||||
}
|
||||
}
|
||||
|
||||
// ts_analise (Unix)
|
||||
long tsUnix = root["ts_analise"]?.Value<long>() ?? 0;
|
||||
if (tsUnix != 0)
|
||||
_lastTsSegmentacao = tsSegmentacao;
|
||||
}
|
||||
|
||||
if (tsDeteccao > 0 &&
|
||||
tsDeteccao != _lastTsDeteccao)
|
||||
{
|
||||
// atualiza o DateTime sempre que vier um ts válido
|
||||
DadosLeitura.Analises.timestamp = FuncoesGlobais.UnixToDateTime(tsUnix.ToString());
|
||||
var token = root["deteccao"];
|
||||
|
||||
if (token != null &&
|
||||
token.Type != JTokenType.Null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var model =
|
||||
token.ToObject<List<VisualWorkerMessageDeteccaoModel>>();
|
||||
|
||||
DadosLeitura.Analises.deteccao =
|
||||
model ?? new List<VisualWorkerMessageDeteccaoModel>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Opcional: registrar erro de contrato
|
||||
}
|
||||
}
|
||||
|
||||
// Se o timestamp não mudou, evita desserializar objetos grandes
|
||||
if (tsUnix != 0 && tsUnix == _lastTsVW)
|
||||
_lastTsDeteccao = tsDeteccao;
|
||||
}
|
||||
|
||||
if (tsMatriz > 0 &&
|
||||
tsMatriz != _lastTsMatrizConfianca)
|
||||
{
|
||||
var token = root["matriz_confianca"];
|
||||
|
||||
if (token != null &&
|
||||
token.Type != JTokenType.Null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var model =
|
||||
token.ToObject<VisualWorkerMessageMatrizConfiancaModel>();
|
||||
|
||||
if (model != null)
|
||||
DadosLeitura.Analises.matriz_confianca = model;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Opcional: registrar erro de contrato
|
||||
}
|
||||
}
|
||||
|
||||
_lastTsMatrizConfianca = tsMatriz;
|
||||
}
|
||||
|
||||
if (tsPerformance > 0 &&
|
||||
tsPerformance != _lastTsPerformanceVisual)
|
||||
{
|
||||
var token = root["performance_visual"];
|
||||
|
||||
if (token != null &&
|
||||
token.Type != JTokenType.Null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var model =
|
||||
token.ToObject<VisualWorkerPerformanceModel>();
|
||||
|
||||
if (model != null)
|
||||
{
|
||||
model.timestamp = tsPerformance;
|
||||
DadosLeitura.Performance = model;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Opcional: registrar erro de contrato
|
||||
}
|
||||
}
|
||||
|
||||
_lastTsPerformanceVisual = tsPerformance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AtualizarImu()
|
||||
{
|
||||
try
|
||||
{
|
||||
string mxId = Variaveis.OperacaoEmAndamento?.DispSen?.Dados?.CameraCaminho?.Id;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(mxId))
|
||||
return;
|
||||
|
||||
_lastTsVW = tsUnix;
|
||||
string cameraJson = RedisService.Get(RedisService.CamKey(mxId));
|
||||
|
||||
// segmentação (sem re-serializar o token)
|
||||
var segTok = root["segmentacao"];
|
||||
if (segTok != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var seg = segTok.ToObject<VisualWorkerMessageSegmentacaoSemanticaModel>();
|
||||
if (seg != null) DadosLeitura.Analises.segmentacao = seg;
|
||||
}
|
||||
catch { /* opcional: log */ }
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(cameraJson))
|
||||
return;
|
||||
|
||||
// matriz de confiança
|
||||
var mcTok = root["matriz_confianca"];
|
||||
if (mcTok != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var mc = mcTok.ToObject<VisualWorkerMessageMatrizConfiancaModel>();
|
||||
if (mc != null) DadosLeitura.Analises.matriz_confianca = mc;
|
||||
}
|
||||
catch { /* opcional: log */ }
|
||||
}
|
||||
JObject root = JObject.Parse(cameraJson);
|
||||
|
||||
// deteccao (sem re-serializar o token)
|
||||
var detTok = root["deteccao"];
|
||||
if (detTok != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var det = detTok.ToObject<List<VisualWorkerMessageDeteccaoModel>>();
|
||||
if (det != null) DadosLeitura.Analises.deteccao = det;
|
||||
JToken imuToken = root["imu"];
|
||||
|
||||
if (imuToken == null ||
|
||||
imuToken.Type == JTokenType.Null)
|
||||
return;
|
||||
|
||||
var imu = imuToken.ToObject<VisualWorkerMessageIMUModel>();
|
||||
|
||||
if (imu != null)
|
||||
DadosLeitura.Imu = imu;
|
||||
}
|
||||
catch { /* opcional: log */ }
|
||||
catch
|
||||
{
|
||||
// Mantém a última leitura válida.
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReiniciarLeituraAnalise()
|
||||
{
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosWeedWorker,
|
||||
("analise.segmentacao", new VisualWorkerMessageSegmentacaoSemanticaModel()),
|
||||
("analise.matriz_confianca", new VisualWorkerMessageMatrizConfiancaModel()),
|
||||
("analise.deteccao", new List<VisualWorkerMessageDeteccaoModel>())
|
||||
CtxKey.DadosVisualWorker,
|
||||
("segmentacao", new VisualWorkerMessageSegmentacaoSemanticaModel()),
|
||||
("matriz_confianca", new VisualWorkerMessageMatrizConfiancaModel()),
|
||||
("deteccao", new List<VisualWorkerMessageDeteccaoModel>()),
|
||||
("ts_segmentacao", 0.0),
|
||||
("ts_matriz_confianca", 0.0),
|
||||
("ts_deteccao", 0.0)
|
||||
);
|
||||
|
||||
_lastTsSegmentacao = -1;
|
||||
_lastTsMatrizConfianca = -1;
|
||||
_lastTsDeteccao = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ namespace AgroBase.Services.Operadores
|
|||
|
||||
private bool DebugMode = true;
|
||||
|
||||
private static double _lastTsAnaliseWeed = -1;
|
||||
private static double _lastTsPerformanceWeed = -1;
|
||||
|
||||
public void MostrarLog(string message, int limite = 500)
|
||||
{
|
||||
if (DebugMode)
|
||||
|
|
@ -171,20 +174,106 @@ namespace AgroBase.Services.Operadores
|
|||
|
||||
public static void AtualizarAnalise()
|
||||
{
|
||||
var json = RedisService.Get(CtxKey.DadosWeedWorker);
|
||||
if (string.IsNullOrWhiteSpace(json)) return;
|
||||
string json = RedisService.Get(CtxKey.DadosWeedWorker);
|
||||
|
||||
var root = JObject.Parse(json);
|
||||
var analise = root["analise"] as JObject;
|
||||
if (analise == null) return;
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
return;
|
||||
|
||||
JObject root;
|
||||
|
||||
try
|
||||
{
|
||||
DadosLeitura.Analise = JsonConvert.DeserializeObject<WeedWorkerAnaliseModel>(root["analise"].ToString());
|
||||
root = JObject.Parse(json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Erro ao deserializar analise de ervas: {ex.Message}");
|
||||
Console.WriteLine(
|
||||
$"Erro ao interpretar DadosWeedWorker: {ex.Message}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
double tsAnalise =
|
||||
root["ts_analise"]?.Value<double>() ?? 0.0;
|
||||
|
||||
double tsAnaliseWeed =
|
||||
root["ts_analise_weed"]?.Value<double>() ?? 0.0;
|
||||
|
||||
double tsPerformance =
|
||||
root["ts_performance_weed"]?.Value<double>() ?? 0.0;
|
||||
|
||||
DadosLeitura.Timestamps.analise = tsAnalise;
|
||||
DadosLeitura.Timestamps.analise_weed = tsAnaliseWeed;
|
||||
DadosLeitura.Timestamps.performance_weed = tsPerformance;
|
||||
|
||||
if (tsAnaliseWeed > 0 &&
|
||||
tsAnaliseWeed != _lastTsAnaliseWeed)
|
||||
{
|
||||
JToken envelopeToken = root["analise"];
|
||||
|
||||
if (envelopeToken != null &&
|
||||
envelopeToken.Type != JTokenType.Null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var envelope =
|
||||
envelopeToken.ToObject<WeedWorkerAnaliseEnvelopeModel>();
|
||||
|
||||
if (envelope != null)
|
||||
{
|
||||
DadosLeitura.MetricasAnalise =
|
||||
new WeedWorkerAnaliseMetricasModel
|
||||
{
|
||||
ts_analise = envelope.ts_analise,
|
||||
fps_model = envelope.fps_model,
|
||||
fps_inferencia = envelope.fps_inferencia,
|
||||
infer_ms = envelope.infer_ms,
|
||||
infer_gpu_ms = envelope.infer_gpu_ms
|
||||
};
|
||||
|
||||
DadosLeitura.Analise =
|
||||
envelope.analise ?? new WeedWorkerAnaliseModel();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"Erro ao desserializar análise de ervas: {ex.Message}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_lastTsAnaliseWeed = tsAnaliseWeed;
|
||||
}
|
||||
|
||||
if (tsPerformance > 0 &&
|
||||
tsPerformance != _lastTsPerformanceWeed)
|
||||
{
|
||||
JToken performanceToken = root["performance_weed"];
|
||||
|
||||
if (performanceToken != null &&
|
||||
performanceToken.Type != JTokenType.Null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var performance =
|
||||
performanceToken.ToObject<WeedWorkerPerformanceModel>();
|
||||
|
||||
if (performance != null)
|
||||
{
|
||||
performance.timestamp = tsPerformance;
|
||||
DadosLeitura.Performance = performance;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"Erro ao desserializar performance weed: {ex.Message}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_lastTsPerformanceWeed = tsPerformance;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,11 +281,36 @@ namespace AgroBase.Services.Operadores
|
|||
{
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosWeedWorker,
|
||||
("analise.ervas_no_radar", false),
|
||||
("analise.percentual_ervas_no_radar", 0),
|
||||
("analise.controle", new Dictionary<string, bool>(Variaveis.OperacaoEmAndamento.DispAtu.Dados.BicosPulverizadores.ToDictionary(x => x.Posicao.ToString(), x => x.ComandoAtuar))),
|
||||
("analise.estatisticas", new WeedWorkerAnaliseEstatisticasModel())
|
||||
|
||||
("analise.analise.ervas_no_radar", false),
|
||||
|
||||
("analise.analise.controle",
|
||||
new Dictionary<string, bool>(
|
||||
Variaveis.OperacaoEmAndamento
|
||||
.DispAtu
|
||||
.Dados
|
||||
.BicosPulverizadores
|
||||
.ToDictionary(
|
||||
x => x.Posicao.ToString(),
|
||||
x => false
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
("analise.analise.estatisticas",
|
||||
new WeedWorkerAnaliseEstatisticasModel()
|
||||
),
|
||||
|
||||
("ts_analise_weed", 0.0)
|
||||
);
|
||||
|
||||
_lastTsAnaliseWeed = -1;
|
||||
|
||||
DadosLeitura.Analise =
|
||||
new WeedWorkerAnaliseModel();
|
||||
|
||||
DadosLeitura.MetricasAnalise =
|
||||
new WeedWorkerAnaliseMetricasModel();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,66 @@ class CameraManager:
|
|||
def __init__(self, mostrar_log):
|
||||
self.mostrar_log = mostrar_log
|
||||
self._ultimo_scan = 0
|
||||
self._resetar_estados_volateis_cameras()
|
||||
|
||||
def _resetar_estados_volateis_cameras(self):
|
||||
"""
|
||||
Limpa estados que pertencem à execução anterior dos workers.
|
||||
|
||||
Esses campos não podem ser confiados após o camera_worker reiniciar,
|
||||
pois podem ter permanecido como True no Redis mesmo com os pipelines
|
||||
já encerrados.
|
||||
"""
|
||||
try:
|
||||
agora = time.time()
|
||||
cameras_mapeadas = ContextoGlobalRedis.get_cameras() or {}
|
||||
|
||||
if not cameras_mapeadas:
|
||||
return
|
||||
|
||||
for mx_id, camera_resumo in list(cameras_mapeadas.items()):
|
||||
if not isinstance(camera_resumo, dict):
|
||||
camera_resumo = {}
|
||||
cameras_mapeadas[mx_id] = camera_resumo
|
||||
|
||||
# Estado resumido dentro de DadosCameras
|
||||
camera_resumo["iniciando"] = False
|
||||
camera_resumo["iniciado"] = False
|
||||
camera_resumo["rodando"] = False
|
||||
camera_resumo["presente_scan"] = False
|
||||
camera_resumo["status_scan"] = "aguardando_scan"
|
||||
|
||||
# Não atualizar o timestamp de heartbeat.
|
||||
# Se atualizarmos, uma câmera antiga parecerá recente.
|
||||
camera_resumo["manager_reset_ts"] = agora
|
||||
|
||||
# Estado detalhado da câmera em CamKey(mx_id)
|
||||
camera_detalhada = ContextoGlobalRedis.get_camera(mx_id) or {}
|
||||
|
||||
camera_detalhada["iniciando"] = False
|
||||
camera_detalhada["iniciado"] = False
|
||||
camera_detalhada["rodando"] = False
|
||||
camera_detalhada["manager_reset_ts"] = agora
|
||||
|
||||
ContextoGlobalRedis.set(
|
||||
ContextoGlobalRedis.CamKey(mx_id),
|
||||
camera_detalhada
|
||||
)
|
||||
|
||||
ContextoGlobalRedis.set(
|
||||
CtxKey.DadosCameras,
|
||||
cameras_mapeadas
|
||||
)
|
||||
|
||||
self.mostrar_log(
|
||||
f"[CameraManager] Estados voláteis resetados para "
|
||||
f"{len(cameras_mapeadas)} câmera(s)."
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.mostrar_log(
|
||||
f"[CameraManager] Erro ao resetar estados das câmeras: {e}"
|
||||
)
|
||||
|
||||
def atualizar_cameras(self):
|
||||
agora = time.time()
|
||||
|
|
@ -88,6 +148,9 @@ class CameraManager:
|
|||
cam = ContextoGlobalRedis.get_camera(cam_id) or val
|
||||
|
||||
timestamp = cam.get("timestamp", val.get("timestamp", 0))
|
||||
iniciando = cam.get("iniciando", val.get("iniciando", False))
|
||||
iniciado = cam.get("iniciado", val.get("iniciado", False))
|
||||
|
||||
idade = agora - timestamp
|
||||
#self.mostrar_log(f"mx_id: {cam_id}, ts: {timestamp}, idade: {idade}")
|
||||
|
||||
|
|
@ -114,7 +177,7 @@ class CameraManager:
|
|||
val["status_scan"] = "provavelmente_em_uso"
|
||||
|
||||
# Se passou muito tempo sem scan e sem saúde, remove
|
||||
elif not vista_no_scan and idade > TIMEOUT_CAMERA_SUMIR:
|
||||
elif not vista_no_scan and idade > TIMEOUT_CAMERA_SUMIR and not iniciando and not iniciado:
|
||||
ids_para_remover.append(cam_id)
|
||||
|
||||
# Se apareceu no scan, mantém
|
||||
|
|
@ -193,7 +256,7 @@ def definir_saude_camera(mx_id: str, status: StatusModulo, saude: int, motivos:
|
|||
"status": status.value,
|
||||
"saude": saude,
|
||||
"motivos": motivos,
|
||||
"saude_idividual": []
|
||||
"saude_individual": []
|
||||
}
|
||||
#if not conectado:
|
||||
# _cameras[mx_id] = {}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ VISUAL_DEFAULT_CONFIG = {
|
|||
"debug_visual": False,
|
||||
|
||||
# Publica logs de performance no console.
|
||||
"debug_perf": True,
|
||||
"debug_perf": False,
|
||||
|
||||
# Tamanho dos frames de preview/debug enviados ao C#.
|
||||
"preview_size": (1280, 720),
|
||||
|
|
|
|||
|
|
@ -77,6 +77,22 @@ def main():
|
|||
|
||||
def inicializar():
|
||||
mostrar_log("🚀 Iniciando Visual Worker...")
|
||||
ContextoGlobalRedis.set(
|
||||
CtxKey.DadosVisualWorker,
|
||||
{
|
||||
"ts_analise": time.time(),
|
||||
|
||||
"ts_segmentacao": 0.0,
|
||||
"ts_deteccao": 0.0,
|
||||
"ts_matriz_confianca": 0.0,
|
||||
"ts_performance_visual": 0.0,
|
||||
|
||||
"segmentacao": None,
|
||||
"deteccao": None,
|
||||
"matriz_confianca": None,
|
||||
"performance_visual": None,
|
||||
}
|
||||
)
|
||||
ContextoGlobalRedis.ouvir_comandos(CmdKey.VisualWorkerRx, redis_callback)
|
||||
ContextoGlobalRedis.publicar_comando(CmdKey.VisualWorkerTx, { "cmd": VisualWorkerCommandType.ScriptCarregado.value })
|
||||
loop_ativo()
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ WEED_DEFAULT_CONFIG = {
|
|||
"debug_visual": False,
|
||||
|
||||
# Publica logs de performance no console.
|
||||
"debug_perf": True,
|
||||
"debug_perf": False,
|
||||
|
||||
# Inclui tempos internos do WeedDetector no payload de análise.
|
||||
# Barato e útil nesta fase; pode desligar na versão final final.
|
||||
|
|
|
|||
|
|
@ -75,6 +75,16 @@ def main():
|
|||
|
||||
def inicializar():
|
||||
mostrar_log("🚀 Iniciando Weed Worker...")
|
||||
ContextoGlobalRedis.set(
|
||||
CtxKey.DadosWeedWorker,
|
||||
{
|
||||
"ts_analise": time.time(),
|
||||
"ts_analise_weed": 0.0,
|
||||
"ts_performance_weed": 0.0,
|
||||
"analise": None,
|
||||
"performance_weed": None,
|
||||
}
|
||||
)
|
||||
ContextoGlobalRedis.ouvir_comandos(CmdKey.WeedWorkerRx, redis_callback)
|
||||
ContextoGlobalRedis.publicar_comando(CmdKey.WeedWorkerTx, { "cmd": WeedWorkerCommandType.ScriptCarregado.value })
|
||||
loop_ativo()
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ class WeedDetector:
|
|||
# Mantém o nome antigo para não quebrar payload/C# agora.
|
||||
# Semântica atual: True se há alvo pulverizável no radar.
|
||||
"ervas_no_radar": bool(target_no_radar),
|
||||
"fracao_ervas_no_radar": float(estat_target.get("frac_global", 0.0)),
|
||||
"percentual_ervas_no_radar": float(estat_target.get("frac_global", 0.0) * 100.0),
|
||||
|
||||
"estatisticas": {
|
||||
# Mantém a chave "erva" para compatibilidade do payload.
|
||||
|
|
|
|||
Loading…
Reference in New Issue