Ajustes de estrutura de dados
This commit is contained in:
parent
c5e90f7b44
commit
909b7261d6
|
|
@ -652,96 +652,6 @@
|
|||
<None Include="Imagens\salvar.png" />
|
||||
<Content Include="Imagens\transferidor.png" />
|
||||
<None Include="Imagens\voltar.png" />
|
||||
<Content Include="Python\Models\deeplabv3plus\backbone\hrnetv2.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\backbone\mobilenetv2.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\backbone\resnet.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\backbone\xception.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\backbone\__init__.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\modeling.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\utils.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\_deeplab.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\deeplabv3plus\__init__.py">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\models\common.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\models\experimental.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\models\yolo.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\models\__init__.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\activations.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\add_nms.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\autoanchor.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\aws\resume.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\aws\__init__.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\datasets.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\general.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\google_app_engine\additional_requirements.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\google_utils.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\loss.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\metrics.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\plots.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\torch_utils.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\wandb_logging\log_dataset.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\wandb_logging\wandb_utils.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\wandb_logging\__init__.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\__init__.py">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Output\folium\images\position_marker.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
@ -933,69 +843,6 @@
|
|||
</Compile>
|
||||
<None Include="Imagens\esp32-s3.jpg" />
|
||||
<None Include="Imagens\esp32-wrover.jpg" />
|
||||
<Content Include="Python\Models\yolo\coco.names">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\yolov3.cfg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\yolov3.weights">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\coco-tiny.names">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\yolov3-tiny.cfg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\yolov3-tiny.weights">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\yolov3-weed.weights">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolo\crop_weed_detection.weights">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Python\Models\deeplabv3plus\backbone\__pycache__\hrnetv2.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\backbone\__pycache__\mobilenetv2.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\backbone\__pycache__\resnet.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\backbone\__pycache__\xception.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\backbone\__pycache__\__init__.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\__pycache__\modeling.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\__pycache__\utils.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\__pycache__\_deeplab.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Python\Models\deeplabv3plus\__pycache__\__init__.cpython-311.pyc">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Python\Models\yolov7\utils\aws\mime.sh">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\aws\userdata.sh">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\google_app_engine\app.yaml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Python\Models\yolov7\utils\google_app_engine\Dockerfile">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Python\Output\fonts\glyphicons-halflings-regular.ttf">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -1024,7 +871,7 @@
|
|||
<Content Include="Python\Scripts\map_load.py" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Python\Models\yolov7\utils\wandb_logging\__pycache__\" />
|
||||
<Folder Include="Python\Models\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="runtimes\win-x64\native\*.dll">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace AgroBase.Forms.Atuador
|
|||
{
|
||||
PopularBicos();
|
||||
|
||||
nudPressaoSP.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.PressaoLinha);
|
||||
nudPressaoSP.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha);
|
||||
txtMMassaRef.Text = DispAtu.Dados._MassaRef.ToString();
|
||||
txtMLeituraRef.Text = DispAtu.Dados._MassaLeituraRef.ToString();
|
||||
txtPressaoVmin.Text = DispAtu.Dados._PressaoVmin.ToString();
|
||||
|
|
@ -63,7 +63,7 @@ namespace AgroBase.Forms.Atuador
|
|||
|
||||
private void PopularBicos()
|
||||
{
|
||||
for (int i = 0; i < DispAtu.Dados.QuantidadeBicos; i++)
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++)
|
||||
{
|
||||
string ID = DispAtu.Dados.BicosPulverizadores[i].ID;
|
||||
Label lblBico = new Label()
|
||||
|
|
@ -153,7 +153,7 @@ namespace AgroBase.Forms.Atuador
|
|||
private void nudPressaoSP_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
|
||||
Variaveis.OperacaoEmAndamento.Controle.PressaoLinha = Convert.ToInt32(((NumericUpDown)sender).Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha = Convert.ToInt32(((NumericUpDown)sender).Value);
|
||||
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ComandoAtuar, Bomba.ID);
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +206,7 @@ namespace AgroBase.Forms.Atuador
|
|||
|
||||
private void btnSalvar_Click(object sender, EventArgs e)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Controle.PressaoLinha = Convert.ToDouble(nudPressaoSP.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha = Convert.ToDouble(nudPressaoSP.Value);
|
||||
DispAtu.Dados._MassaRef = Convert.ToDouble(txtMMassaRef.Text);
|
||||
DispAtu.Dados._MassaLeituraRef = Convert.ToDouble(txtMLeituraRef.Text);
|
||||
DispAtu.Dados._PressaoVmin = Convert.ToDouble(txtPressaoVmin.Text);
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ namespace AgroBase.Forms.Atuador
|
|||
}
|
||||
|
||||
chbBicosAtuacao.Checked = Disp.Dados.BicosPulverizadores.Any(x => x.AtuacaoNivelAlto);
|
||||
nudBicosQtd.Value = Disp.Dados.QuantidadeBicos;
|
||||
nudBicosQtd.Value = Variaveis.OperacaoEmAndamento.Parametros.QtdBicos;
|
||||
txtDensidade.Text = Disp.Dados.DensidadeHerbicida.ToString("0.00");
|
||||
nudCapMax.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.CapacidadeReservatorio);
|
||||
nudCapMax.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Parametros.QtdCamerasSolo);
|
||||
}
|
||||
|
||||
private void frmAtuConfig_FormClosing(object sender, FormClosingEventArgs e)
|
||||
|
|
@ -41,9 +41,9 @@ namespace AgroBase.Forms.Atuador
|
|||
private void btnSalvar_Click(object sender, EventArgs e)
|
||||
{
|
||||
Disp.Dados.BicosPulverizadores.ForEach(x => x.AtuacaoNivelAlto = chbBicosAtuacao.Checked);
|
||||
Disp.Dados.QuantidadeBicos = Convert.ToInt32(nudBicosQtd.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.QtdBicos = Convert.ToInt32(nudBicosQtd.Value);
|
||||
Disp.Dados.DensidadeHerbicida = Convert.ToDouble(txtDensidade.Text.Replace(".", ","));
|
||||
Variaveis.OperacaoEmAndamento.CapacidadeReservatorio = Convert.ToDouble(nudCapMax.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.CapacidadeReservatorio = Convert.ToDouble(nudCapMax.Value);
|
||||
|
||||
Disp.SalvarParametros(Disp.Dados);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ namespace AgroBase.Forms.IHM
|
|||
chbSonarAtivado.Enabled = KinectService.Iniciado;
|
||||
if (KinectService.Iniciado)
|
||||
{
|
||||
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Controle.SonarAtivado;
|
||||
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ namespace AgroBase.Forms.IHM
|
|||
CameraCaminho = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.Clone();
|
||||
CamerasSolo = new List<OAKCameraModel>(Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo);
|
||||
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.QuantidadeCamerasSolo; i++)
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdCamerasSolo; i++)
|
||||
{
|
||||
GerarCameraSolo(i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ namespace AgroBase.Forms.IHM
|
|||
private async Task EnviarComandoBomba(bool Ligar, double Pressao, int Timeout, AtuadorModel disp = null)
|
||||
{
|
||||
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
|
||||
Variaveis.OperacaoEmAndamento.Controle.PressaoLinha = Pressao + 10;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha = Pressao + 10;
|
||||
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Ligar, Bomba.ID);
|
||||
|
||||
DateTime inicio = DateTime.Now;
|
||||
|
|
@ -941,7 +941,7 @@ namespace AgroBase.Forms.IHM
|
|||
|
||||
TipoMovimentoDirecional _oldTipoMovimento = Variaveis.OperacaoEmAndamento.Controle.TipoMovimento;
|
||||
double _oldAngulo = Variaveis.OperacaoEmAndamento.Controle.Angulo;
|
||||
double _oldVelocidadeMP = Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP;
|
||||
double _oldVelocidadeMP = Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento;
|
||||
|
||||
DispositivosService<MovimentacaoUnificadaModel> Dispositivo = (DispositivosService<MovimentacaoUnificadaModel>)Variaveis.DispositivosConectados.FirstOrDefault(x => x.Dispositivo == Enums.T_Code.Mvd);
|
||||
|
||||
|
|
@ -952,7 +952,7 @@ namespace AgroBase.Forms.IHM
|
|||
|
||||
Variaveis.OperacaoEmAndamento.Controle.TipoMovimento = TipoMovimentoDirecional.Diagnostico;
|
||||
Variaveis.OperacaoEmAndamento.Controle.Angulo = 25;
|
||||
Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP = 30;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento = 30;
|
||||
|
||||
bool SenConectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Sen);
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, SenConectado ? 1 : 0);
|
||||
|
|
@ -1001,7 +1001,7 @@ namespace AgroBase.Forms.IHM
|
|||
|
||||
Variaveis.OperacaoEmAndamento.Controle.TipoMovimento = _oldTipoMovimento;
|
||||
Variaveis.OperacaoEmAndamento.Controle.Angulo = _oldAngulo;
|
||||
Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP = _oldVelocidadeMP;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento = _oldVelocidadeMP;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1227,7 +1227,7 @@ namespace AgroBase.Forms.IHM
|
|||
bool PzmConectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Enums.T_Code.Pzm);
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, PzmConectado ? 1 : 0);
|
||||
|
||||
var S36V = Variaveis.OperacaoEmAndamento.Sensoriamento.Bateria;
|
||||
var S36V = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Bateria;
|
||||
bool S36VInicializado = S36V.Iniciado;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, S36VInicializado ? 1 : 0);
|
||||
|
||||
|
|
@ -1264,7 +1264,7 @@ namespace AgroBase.Forms.IHM
|
|||
double Corrente12V = S12V.ValoresLeituras.FirstOrDefault(x => x.funcao == FuncoesPinout.Corrente).atual.valor;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, Corrente12V);
|
||||
|
||||
var SImu = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU;
|
||||
var SImu = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.IMU;
|
||||
double Orientacao = SImu.Iniciado ? SImu.Rotacao : -1;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, Orientacao);
|
||||
|
||||
|
|
@ -1274,13 +1274,13 @@ namespace AgroBase.Forms.IHM
|
|||
bool GpsInicializado = GPSService.Iniciado;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, GpsInicializado ? 1 : 0);
|
||||
|
||||
double Precisao = GpsInicializado ? (int)Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.QualidadeFix : -1;
|
||||
double Precisao = GpsInicializado ? (int)Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.QualidadeFix : -1;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, Precisao);
|
||||
|
||||
double Satelites = GpsInicializado ? Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.NumeroSatelites : -1;
|
||||
double Satelites = GpsInicializado ? Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.NumeroSatelites : -1;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, Satelites);
|
||||
|
||||
double OrientacaoGPS = GpsInicializado ? Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.OrientacaoReal : -1;
|
||||
double OrientacaoGPS = GpsInicializado ? Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.OrientacaoReal : -1;
|
||||
idx = PreencheDadosLinha(grid, Testes, idx, OrientacaoGPS);
|
||||
|
||||
bool A05Conectado = SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Enums.T_Code.A05);
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ namespace AgroBase.Forms.IHM
|
|||
|
||||
public void AtualizarMapaDinamico()
|
||||
{
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
var _Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
|
||||
|
||||
if (_Trajetoria != null && _Trajetoria.CorredorAtual != null)
|
||||
|
|
@ -160,10 +160,10 @@ namespace AgroBase.Forms.IHM
|
|||
pnlOrientacao.Invalidate();
|
||||
pnlInclinacao.Invalidate();
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
lblUltimaLeituraSolo.Text = "Última Leitura Solo: " + Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorErvas.UltimaMensagem.ToString("HH:mm:ss.fff");
|
||||
lblUltimaLeituraCaminho.Text = "Última Leitura Caminho: " + Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual.UltimaMensagem.ToString("HH:mm:ss.fff");
|
||||
lblUltimaLeituraSolo.Text = "Última Leitura Solo: " + _Sensoriamento.OperadorErvas.UltimaMensagem.ToString("HH:mm:ss.fff");
|
||||
lblUltimaLeituraCaminho.Text = "Última Leitura Caminho: " + _Sensoriamento.OperadorVisual.UltimaMensagem.ToString("HH:mm:ss.fff");
|
||||
lblPerformance.Text = _Sensoriamento.DadosPerformance.PerformanceStr;
|
||||
|
||||
lblMapaCarregado.Text = "Operação: " + Variaveis.OperacaoEmAndamento.Descricao;
|
||||
|
|
@ -210,7 +210,7 @@ namespace AgroBase.Forms.IHM
|
|||
tkbVelocidade.Value = Convert.ToInt32(_Sensoriamento.Controle.PercentualVelocidadeSP);
|
||||
|
||||
tkbAnguloDirecional.Minimum = 0;
|
||||
tkbAnguloDirecional.Maximum = Convert.ToInt32(_Sensoriamento.Controle.Angulo_Max);
|
||||
tkbAnguloDirecional.Maximum = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo);
|
||||
tkbAnguloDirecional.Value = Math.Abs(Convert.ToInt32(_Sensoriamento.Controle.Angulo));
|
||||
}
|
||||
|
||||
|
|
@ -294,8 +294,8 @@ namespace AgroBase.Forms.IHM
|
|||
{
|
||||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria.AnguloCaminho);
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Parametros?.DadosLeitura?.Gps?.AnguloCarroDefinido ?? 0;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)(Variaveis.OperacaoEmAndamento.Parametros?.DadosLeitura?.Trajetoria?.AnguloCaminho ?? 0));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
|
@ -333,15 +333,16 @@ namespace AgroBase.Forms.IHM
|
|||
pnlJoystick.Visible = false;
|
||||
tabControl1.TabPages.Remove(tabControle);
|
||||
|
||||
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
|
||||
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
||||
cmbModoControle.SelectedIndex = (int)_Controle.TipoMovimento;
|
||||
chbSonarAtivado.Checked = _Controle.SonarAtivado;
|
||||
chbFrenagemAutomatica.Checked = _Controle.FrenagemAutomatica;
|
||||
nudVelSemErvas.Value = (int)_Controle.PercentualVelocidadeMax;
|
||||
nudVelComErvas.Value = (int)_Controle.PercentualVelocidadeMin;
|
||||
chbPulverizadorAutomatico.Checked = _Controle.PulverizadorAutomatico;
|
||||
nudPercentualAtuacaoBico.Value = (int)(_Controle.PercentualInicioPulverizacao * 100.0);
|
||||
nudPressaoLinha.Value = (int)_Controle.PressaoLinha;
|
||||
chbSonarAtivado.Checked = pControle.SonarAtivado;
|
||||
chbFrenagemAutomatica.Checked = pControle.FrenagemAutomatica;
|
||||
nudVelSemErvas.Value = (int)pControle.MovVelocidadeSErvasPercent;
|
||||
nudVelComErvas.Value = (int)pControle.MovVelocidadeCErvasPercent;
|
||||
chbPulverizadorAutomatico.Checked = pControle.PulverizadorAutomatico;
|
||||
nudPercentualAtuacaoBico.Value = (int)pControle.AtuPercentualInicioPulverizacao;
|
||||
nudPressaoLinha.Value = (int)pControle.AtuPressaoLinha;
|
||||
FuncoesGlobais.PreencheValorTrackBar(tkbAnguloDirecional, _Controle.Angulo);
|
||||
FuncoesGlobais.PreencheValorTrackBar(tkbVelocidade, _Controle.PercentualVelocidadeSP);
|
||||
|
||||
|
|
@ -670,7 +671,7 @@ namespace AgroBase.Forms.IHM
|
|||
try
|
||||
{
|
||||
// 1) Pega o estado atual do seu sistema
|
||||
var src = Variaveis.OperacaoEmAndamento.ModulosMandatorios;
|
||||
var src = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios;
|
||||
var saude = HealthWorkerService.ModulosSaude;
|
||||
|
||||
// 2) Constrói snapshot
|
||||
|
|
@ -802,7 +803,7 @@ namespace AgroBase.Forms.IHM
|
|||
|
||||
// escreve de volta na fonte oficial
|
||||
var disp = _modulosUI[idx].Disp;
|
||||
var alvo = Variaveis.OperacaoEmAndamento.ModulosMandatorios.FirstOrDefault(m => m.Dispositivo.Equals(disp));
|
||||
var alvo = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.FirstOrDefault(m => m.Dispositivo.Equals(disp));
|
||||
if (alvo != null)
|
||||
{
|
||||
if (alvo.Utilizar && alvo.Mandatorio && !novoUtilizar)
|
||||
|
|
@ -866,16 +867,16 @@ namespace AgroBase.Forms.IHM
|
|||
{ ("Não", DialogResult.No), () => { } },
|
||||
}
|
||||
);
|
||||
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
||||
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
|
||||
if (res == DialogResult.Yes)
|
||||
{
|
||||
_Controle.SonarAtivado = chbSonarAtivado.Checked;
|
||||
_Controle.FrenagemAutomatica = chbFrenagemAutomatica.Checked;
|
||||
_Controle.RPM_Max = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelSemErvas.Value));
|
||||
_Controle.RPM_Min = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelComErvas.Value));
|
||||
_Controle.PulverizadorAutomatico = chbPulverizadorAutomatico.Checked;
|
||||
_Controle.PercentualInicioPulverizacao = ((double)nudPercentualAtuacaoBico.Value / 100.0);
|
||||
_Controle.PressaoLinha = (double)nudPressaoLinha.Value;
|
||||
pControle.SonarAtivado = chbSonarAtivado.Checked;
|
||||
pControle.FrenagemAutomatica = chbFrenagemAutomatica.Checked;
|
||||
pControle.MovVelocidadeSErvasPercent = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelSemErvas.Value));
|
||||
pControle.MovVelocidadeCErvasPercent = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelComErvas.Value));
|
||||
pControle.PulverizadorAutomatico = chbPulverizadorAutomatico.Checked;
|
||||
pControle.AtuPercentualInicioPulverizacao = ((double)nudPercentualAtuacaoBico.Value / 100.0);
|
||||
pControle.AtuPressaoLinha = (double)nudPressaoLinha.Value;
|
||||
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosPesosMPC,
|
||||
|
|
@ -893,13 +894,13 @@ namespace AgroBase.Forms.IHM
|
|||
}
|
||||
else
|
||||
{
|
||||
chbSonarAtivado.Checked = _Controle.SonarAtivado;
|
||||
chbFrenagemAutomatica.Checked = _Controle.FrenagemAutomatica;
|
||||
nudVelSemErvas.Value = (int)_Controle.PercentualVelocidadeMax;
|
||||
nudVelComErvas.Value = (int)_Controle.PercentualVelocidadeMin;
|
||||
chbPulverizadorAutomatico.Checked = _Controle.PulverizadorAutomatico;
|
||||
nudPercentualAtuacaoBico.Value = (int)(_Controle.PercentualInicioPulverizacao * 100.0);
|
||||
nudPressaoLinha.Value = (int)_Controle.PressaoLinha;
|
||||
chbSonarAtivado.Checked = pControle.SonarAtivado;
|
||||
chbFrenagemAutomatica.Checked = pControle.FrenagemAutomatica;
|
||||
nudVelSemErvas.Value = (int)pControle.MovVelocidadeSErvasPercent;
|
||||
nudVelComErvas.Value = (int)pControle.MovVelocidadeCErvasPercent;
|
||||
chbPulverizadorAutomatico.Checked = pControle.PulverizadorAutomatico;
|
||||
nudPercentualAtuacaoBico.Value = (int)pControle.AtuPercentualInicioPulverizacao;
|
||||
nudPressaoLinha.Value = (int)pControle.AtuPressaoLinha;
|
||||
string pesosMpcStr = RedisService.Get(CtxKey.DadosPesosMPC);
|
||||
var pesos = JsonConvert.DeserializeObject<MPCPesosModel>(pesosMpcStr);
|
||||
txtPesoPosicao.Text = pesos.posicao.ToString();
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
{
|
||||
string disp = chb.Name.Replace("chb", "");
|
||||
T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), disp);
|
||||
chb.Checked = Variaveis.OperacaoEmAndamento.ModulosMandatorios.Any(x => x.Dispositivo == Dispositivo && x.Mandatorio);
|
||||
chb.Checked = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == Dispositivo && x.Mandatorio);
|
||||
}
|
||||
|
||||
txtModoOperacao.Text = Variaveis.OperacaoEmAndamento.Modo.ToString();
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
flwCamerasSolo.Controls.Add(pnlCam);
|
||||
}
|
||||
|
||||
chbPulverizador.Checked = Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico;
|
||||
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Controle.SonarAtivado;
|
||||
chbPulverizador.Checked = Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico;
|
||||
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado;
|
||||
|
||||
InicializarComandosDirecional();
|
||||
PopularInformacoesGerais();
|
||||
|
|
@ -151,7 +151,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
AtualizarInformacoesGerais();
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
lblDistanciaEsquerda.Text = "Distancia Esq: " + _Sensoriamento.Trajetoria.DistanciaEsquerda.ToString("0.00") + " cm";
|
||||
lblDistanciaDireita.Text = "Distancia Dir: " + _Sensoriamento.Trajetoria.DistanciaDireita.ToString("0.00") + " cm";
|
||||
|
|
@ -173,7 +173,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
chbPulverizador.Checked = false;
|
||||
}
|
||||
|
||||
bool sonarAtivado = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual.Status == StatusModulo.Operante;
|
||||
bool sonarAtivado = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.OperadorVisual.Status == StatusModulo.Operante;
|
||||
chbSonarAtivado.Enabled = sonarAtivado;
|
||||
if (!sonarAtivado)
|
||||
{
|
||||
|
|
@ -424,8 +424,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
{
|
||||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.OrientacaoReal;
|
||||
double angulo2 = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.OrientacaoReal;
|
||||
double angulo2 = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.AnguloCarroDefinido;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, -90, (float)angulo2);
|
||||
}
|
||||
catch { }
|
||||
|
|
@ -433,7 +433,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
private void pnlAnguloMagnetometro_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
var imu = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU;
|
||||
var imu = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.IMU;
|
||||
try
|
||||
{
|
||||
double angulo = imu.Rotacao;
|
||||
|
|
@ -512,7 +512,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
var AB12V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB12V");
|
||||
var AB19V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB19V");
|
||||
var AB24V = _SensoresCorrente.FirstOrDefault(x => x.ID == "AB24V");
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
gridDados.Rows[0].Cells[1].Value = _Sensoriamento.TempoDecorrido.ToString("HH:mm:ss");
|
||||
gridDados.Rows[1].Cells[1].Value = _Sensoriamento.Movimentacao.TempoMovimento.ToString("HH:mm:ss");
|
||||
|
|
@ -570,15 +570,15 @@ namespace AgroBase.Forms.Operacoes
|
|||
private void PopularBicos()
|
||||
{
|
||||
var Atuador = Variaveis.OperacaoEmAndamento.DispAtu;
|
||||
nudPressaoSP.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.PressaoLinha);
|
||||
nudPressaoSP.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha);
|
||||
|
||||
int panelWidth = pnlAtuadores.Width;
|
||||
int circleDiameter = 40; // Diâmetro dos círculos grandes
|
||||
int spaceBetweenCircles = (panelWidth - (circleDiameter * Atuador.Dados.QuantidadeBicos)) / (Atuador.Dados.QuantidadeBicos + 1);
|
||||
int spaceBetweenCircles = (panelWidth - (circleDiameter * Variaveis.OperacaoEmAndamento.Parametros.QtdBicos)) / (Variaveis.OperacaoEmAndamento.Parametros.QtdBicos + 1);
|
||||
int yPosition = (pnlAtuadores.Height - circleDiameter) / 3; // Centralizado verticalmente
|
||||
|
||||
|
||||
for (int i = 0; i < Atuador.Dados.QuantidadeBicos; i++)
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++)
|
||||
{
|
||||
// Calcula a posição x do círculo
|
||||
int xPosition = spaceBetweenCircles + (i * (circleDiameter + spaceBetweenCircles));
|
||||
|
|
@ -637,7 +637,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
private void nudPressaoSP_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
|
||||
Variaveis.OperacaoEmAndamento.Controle.PressaoLinha = Convert.ToInt32(((NumericUpDown)sender).Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha = Convert.ToInt32(((NumericUpDown)sender).Value);
|
||||
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ComandoAtuar, Bomba.ID);
|
||||
}
|
||||
|
||||
|
|
@ -678,12 +678,12 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
private void chbPulverizador_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico = ((CheckBox)sender).Checked;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico = ((CheckBox)sender).Checked;
|
||||
}
|
||||
|
||||
private void chbSonarAtivado_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Controle.SonarAtivado = ((CheckBox)sender).Checked;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado = ((CheckBox)sender).Checked;
|
||||
}
|
||||
|
||||
private void chbSonarDesvioAutomatico_CheckedChanged(object sender, EventArgs e)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
pnlCaminho.Invalidate();
|
||||
pnlAnguloCamera.Invalidate();
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
/*var ultimaLeitura = Variaveis.OperacaoEmAndamento.CamerasSolo.OrderByDescending(x => x.Leitura.timestamp).FirstOrDefault();
|
||||
if (ultimaLeitura != null)
|
||||
|
|
@ -282,7 +282,7 @@ namespace AgroBase.Forms.Operacoes
|
|||
{
|
||||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.AnguloCarroDefinido;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, -90);
|
||||
}
|
||||
catch { }
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
void CarregarParametros()
|
||||
{
|
||||
ModulosMandatorios = Variaveis.OperacaoEmAndamento.ModulosMandatorios.ToList();
|
||||
var _Parametros = Variaveis.OperacaoEmAndamento.Parametros;
|
||||
ModulosMandatorios = _Parametros.ModulosMandatorios.ToList();
|
||||
|
||||
cmbOperacao.Items.Clear();
|
||||
cmbOperacao.Items.AddRange(Enum.GetNames(typeof(ModoOperacao)));
|
||||
|
|
@ -52,24 +53,24 @@ namespace AgroBase.Forms.Operacoes
|
|||
});
|
||||
|
||||
nudVelocidadeComErvas.Minimum = 0;
|
||||
nudVelocidadeComErvas.Maximum = Convert.ToInt32(VariaveisEquipamento.RPM_Max_Roda);
|
||||
nudVelocidadeComErvas.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.RPM_Min);
|
||||
nudVelocidadeComErvas.Maximum = 100;
|
||||
nudVelocidadeComErvas.Value = Convert.ToInt32(_Parametros.Controle.MovVelocidadeCErvasPercent);
|
||||
|
||||
nudVelocidadeSemErvas.Minimum = 0;
|
||||
nudVelocidadeSemErvas.Maximum = Convert.ToInt32(VariaveisEquipamento.RPM_Max_Roda);
|
||||
nudVelocidadeSemErvas.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.RPM_Max);
|
||||
nudVelocidadeSemErvas.Maximum = 100;
|
||||
nudVelocidadeSemErvas.Value = Convert.ToInt32(_Parametros.Controle.MovVelocidadeSErvasPercent);
|
||||
|
||||
lblKmhCErvas.Text = FuncoesMatematicas.CalculaVelocidadeRPM(Variaveis.OperacaoEmAndamento.Controle.RPM_Min).ToString("0.00") + " Km/h";
|
||||
lblKmhSErvas.Text = FuncoesMatematicas.CalculaVelocidadeRPM(Variaveis.OperacaoEmAndamento.Controle.RPM_Max).ToString("0.00") + " Km/h";
|
||||
nudAnguloMaximo.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.Angulo_Max);
|
||||
nudAnguloMinimo.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.Angulo_Min);
|
||||
nudVelocidadeMP.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP);
|
||||
lblKmhCErvas.Text = FuncoesMatematicas.ConverteMsParaKmh(FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Parametros.Controle.MovVelocidadeCErvasPercent)).ToString("0.00") + " Km/h";
|
||||
lblKmhSErvas.Text = FuncoesMatematicas.ConverteMsParaKmh(FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Parametros.Controle.MovVelocidadeSErvasPercent)).ToString("0.00") + " Km/h";
|
||||
nudAnguloMaximo.Value = Convert.ToInt32(_Parametros.Controle.DirAnguloMaximo);
|
||||
nudAnguloMinimo.Value = Convert.ToInt32(-_Parametros.Controle.DirAnguloMaximo);
|
||||
nudVelocidadeMP.Value = Convert.ToInt32(_Parametros.Controle.DirVelocidadeMovimento);
|
||||
nudTemposalvarlog.Value = (decimal)Variaveis.OperacaoEmAndamento.tmrLogsInterval / 1000;
|
||||
nudQtdBicos.Value = Variaveis.OperacaoEmAndamento.DispAtu.Dados.QuantidadeBicos;
|
||||
nudQtdCameras.Value = Variaveis.OperacaoEmAndamento.QuantidadeCamerasSolo;
|
||||
nudCapacidadereservatorio.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.CapacidadeReservatorio);
|
||||
nudQtdBicos.Value = _Parametros.QtdBicos;
|
||||
nudQtdCameras.Value = _Parametros.QtdCamerasSolo;
|
||||
nudCapacidadereservatorio.Value = Convert.ToInt32(_Parametros.CapacidadeReservatorio);
|
||||
txtDensidadeherbicida.Text = Variaveis.OperacaoEmAndamento.DispAtu.Dados.DensidadeHerbicida.ToString("0.00");
|
||||
nudAtuarem.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.PercentualInicioPulverizacao * 100);
|
||||
nudAtuarem.Value = Convert.ToInt32(_Parametros.Controle.AtuPercentualInicioPulverizacao);
|
||||
cmbScriptErvas.SelectedIndex = cmbScriptErvas.Items.IndexOf(Variaveis.OperacaoEmAndamento.DispAtu.Dados.ScriptDeteccaoErvas.Replace(".py", ""));
|
||||
}
|
||||
|
||||
|
|
@ -125,19 +126,18 @@ namespace AgroBase.Forms.Operacoes
|
|||
|
||||
void SalvarOperacao()
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.ModulosMandatorios = ModulosMandatorios.Where(x => x.Utilizar).ToList();
|
||||
Variaveis.OperacaoEmAndamento.Controle.RPM_Max = (int)(nudVelocidadeSemErvas.Value);
|
||||
Variaveis.OperacaoEmAndamento.Controle.RPM_Min = (int)(nudVelocidadeComErvas.Value);
|
||||
Variaveis.OperacaoEmAndamento.Controle.Angulo_Max = (int)(nudAnguloMaximo.Value);
|
||||
Variaveis.OperacaoEmAndamento.Controle.Angulo_Min = (int)(nudAnguloMinimo.Value);
|
||||
Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP = (int)(nudVelocidadeMP.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios = ModulosMandatorios.Where(x => x.Utilizar).ToList();
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeSErvasPercent = (int)(nudVelocidadeSemErvas.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent = (int)(nudVelocidadeComErvas.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo = (int)(nudAnguloMaximo.Value);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento = (int)(nudVelocidadeMP.Value);
|
||||
Variaveis.OperacaoEmAndamento.tmrLogsInterval = (double)(nudTemposalvarlog.Value * 1000);
|
||||
Variaveis.OperacaoEmAndamento.DispAtu.Dados.QuantidadeBicos = (int)nudQtdBicos.Value;
|
||||
Variaveis.OperacaoEmAndamento.QuantidadeCamerasSolo = (int)nudQtdCameras.Value;
|
||||
Variaveis.OperacaoEmAndamento.CapacidadeReservatorio = (double)nudCapacidadereservatorio.Value;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.QtdBicos = (int)nudQtdBicos.Value;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.QtdCamerasSolo = (int)nudQtdCameras.Value;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.CapacidadeReservatorio = (double)nudCapacidadereservatorio.Value;
|
||||
Variaveis.OperacaoEmAndamento.DispAtu.Dados.DensidadeHerbicida = Convert.ToDouble(txtDensidadeherbicida.Text.Replace(".", ","));
|
||||
Variaveis.OperacaoEmAndamento.Controle.PercentualInicioPulverizacao = (double)(nudAtuarem.Value / 100);
|
||||
Variaveis.OperacaoEmAndamento.DispAtu.Dados.ScriptDeteccaoErvas = cmbScriptErvas.Text + ".py";
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPercentualInicioPulverizacao = (double)(nudAtuarem.Value / 100);
|
||||
//Variaveis.OperacaoEmAndamento.Parametros.DispAtu.Dados.ScriptDeteccaoErvas = cmbScriptErvas.Text + ".py";
|
||||
|
||||
if (chbSalvar.Checked)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace AgroBase.Forms
|
|||
{
|
||||
cmbTipoControleDirecional.Items.Clear();
|
||||
cmbTipoControleDirecional.Items.AddRange(Enum.GetNames(typeof(Enums.TiposControladorDirecional)));
|
||||
cmbTipoControleDirecional.SelectedIndex = (int)Variaveis.OperacaoEmAndamento.Controle.TipoControleDirecional;
|
||||
cmbTipoControleDirecional.SelectedIndex = (int)Variaveis.OperacaoEmAndamento.Parametros.Controle.DirTipoMovimento;
|
||||
|
||||
cmbStatusCorredor.Items.Clear();
|
||||
cmbStatusCorredor.Items.AddRange(Enum.GetNames(typeof(Enums.StatusCarroMapa)));
|
||||
|
|
@ -116,9 +116,15 @@ namespace AgroBase.Forms
|
|||
return;
|
||||
AtualizandoTela = true;
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
var _Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
|
||||
|
||||
if (_Trajetoria == null)
|
||||
{
|
||||
AtualizandoTela = false;
|
||||
return;
|
||||
}
|
||||
|
||||
lblStatusOperacao.Text = "Operação: " + Enum.GetName(typeof(StatusOperacao), _Sensoriamento.StatusOperacao);
|
||||
lblTipoMovimento.Text = _Sensoriamento.Controle.TipoMovimento.ToString();
|
||||
|
||||
|
|
@ -257,12 +263,12 @@ namespace AgroBase.Forms
|
|||
// Obtém os parâmetros
|
||||
double anguloAtual = double.Parse(txtAnguloGPS.Text);
|
||||
|
||||
var _Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
|
||||
var _Gps = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps;
|
||||
|
||||
double anguloControle = 0.0;
|
||||
TipoMovimentoDirecional tipoMovimento = Variaveis.OperacaoEmAndamento.Controle.TipoMovimento;
|
||||
|
||||
var tipoControle = Variaveis.OperacaoEmAndamento.Controle.TipoControleDirecional;
|
||||
var tipoControle = Variaveis.OperacaoEmAndamento.Parametros.Controle.DirTipoMovimento;
|
||||
|
||||
if (passosOperacao.Count > 0 && Variaveis.OperacaoEmAndamento.Simulando)
|
||||
{
|
||||
|
|
@ -319,7 +325,7 @@ namespace AgroBase.Forms
|
|||
|
||||
AtualizarPosicaoGPS();
|
||||
|
||||
Variaveis.OperacaoEmAndamento.Sensoriamento.AtualizarDados();
|
||||
Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.AtualizarDados();
|
||||
|
||||
if (!chbAutomatico.Checked)
|
||||
{
|
||||
|
|
@ -434,8 +440,8 @@ namespace AgroBase.Forms
|
|||
{
|
||||
//double angulo = Variaveis.OperacaoEmAndamento.Trajetoria.AnguloCaminho;
|
||||
//double anguloCorredor = Variaveis.OperacaoEmAndamento.Trajetoria.AnguloMedioCorredor;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Trajetoria.ProximoPonto?.Orientacao ?? 0;
|
||||
double anguloCorredor = Variaveis.OperacaoEmAndamento.Trajetoria.AnguloCaminho;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Trajetoria?.ProximoPonto?.Orientacao ?? 0;
|
||||
double anguloCorredor = Variaveis.OperacaoEmAndamento.Trajetoria?.AnguloCaminho ?? 0;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)anguloCorredor);
|
||||
}
|
||||
catch { }
|
||||
|
|
@ -445,7 +451,7 @@ namespace AgroBase.Forms
|
|||
{
|
||||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps?.AnguloCarroDefinido ?? 0;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.Gps?.AnguloCarroDefinido ?? 0;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90);
|
||||
}
|
||||
catch { }
|
||||
|
|
@ -456,7 +462,7 @@ namespace AgroBase.Forms
|
|||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.SimulacaoAnguloControle;
|
||||
double dif = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria?.ErroOrientacaoAngularProximoPonto ?? 0;
|
||||
double dif = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.Trajetoria?.ErroOrientacaoAngularProximoPonto ?? 0;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)dif);
|
||||
}
|
||||
catch { }
|
||||
|
|
@ -500,7 +506,7 @@ namespace AgroBase.Forms
|
|||
|
||||
private void cmbTipoControleDirecional_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Controle.TipoControleDirecional = (TiposControladorDirecional)cmbTipoControleDirecional.SelectedIndex;
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirTipoMovimento = (TiposControladorDirecional)cmbTipoControleDirecional.SelectedIndex;
|
||||
RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ namespace AgroBase.Forms.Simuladores
|
|||
Task.Run(async () =>
|
||||
{
|
||||
OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(CameraFrameType.Segmentacao);
|
||||
var dadosSeg = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual.Analises.segmentacao;
|
||||
var dadosSeg = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.OperadorVisual.Analises.segmentacao;
|
||||
DesenharCorredor(frame?.image(), dadosSeg.centros_corredor, dadosSeg.width, dadosSeg.height, 80);
|
||||
|
||||
this.Invoke((MethodInvoker)(() =>
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ namespace AgroBase.Forms
|
|||
{
|
||||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.AnguloCarroDefinido;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90);
|
||||
}
|
||||
catch { }
|
||||
|
|
@ -476,7 +476,7 @@ namespace AgroBase.Forms
|
|||
{
|
||||
Latitude = GPSService.UltimaLeitura.Latitude,
|
||||
Longitude = GPSService.UltimaLeitura.Longitude,
|
||||
Orientation = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido
|
||||
Orientation = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.AnguloCarroDefinido
|
||||
});
|
||||
_robotState.UpdateCurrentRobotState();
|
||||
|
||||
|
|
|
|||
|
|
@ -69,9 +69,9 @@ namespace AgroBase.Forms
|
|||
AtualizarDadosSensorCorrente("AB36V", lblB36V);
|
||||
}
|
||||
|
||||
lblMagnetometro.ForeColor = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU.Iniciado ? Color.Green : Color.Red;
|
||||
lblMagnetometro.ForeColor = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.IMU.Iniciado ? Color.Green : Color.Red;
|
||||
|
||||
var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
|
||||
var Gps = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps;
|
||||
lblGPS.ForeColor = Gps.Inicializado ? Color.Green : Color.Red;
|
||||
if (Gps.Inicializado)
|
||||
{
|
||||
|
|
@ -395,7 +395,7 @@ namespace AgroBase.Forms
|
|||
|
||||
private void pnlOrientacaoGPS_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
double Angulo = _Sensoriamento.Gps.OrientacaoReal;
|
||||
double AnguloMovimento = _Sensoriamento.Gps.OrientacaoMovimento;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, -90, (float)AnguloMovimento);
|
||||
|
|
@ -403,7 +403,7 @@ namespace AgroBase.Forms
|
|||
|
||||
private void pnlOrientacaoMagnetometro_Paint(object sender, PaintEventArgs e)
|
||||
{
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
double Angulo = _Sensoriamento.IMU.Rotacao;
|
||||
double AnguloCorrigido = _Sensoriamento.IMU.RotacaoCorrigida;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)Angulo, -90, (float)AnguloCorrigido);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace AgroBase.Forms
|
|||
|
||||
private async Task tmrLeitura_Tick()
|
||||
{
|
||||
var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
|
||||
var Gps = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps;
|
||||
|
||||
lblAltitude.Text = "Altitude: " + Gps.Altitude.ToString("0.0") + " m";
|
||||
lblDatahora.Text = "Ultima Leitura: " + Gps.DataHora.ToString("HH:mm:ss");
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace AgroBase.Forms
|
|||
|
||||
private void btnRegistrarPontos_Click(object sender, EventArgs e)
|
||||
{
|
||||
GPSModel P1 = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Clone();
|
||||
GPSModel P1 = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Clone();
|
||||
|
||||
if (Pontos[idxRua].Count == 0)
|
||||
{
|
||||
|
|
@ -127,8 +127,8 @@ namespace AgroBase.Forms
|
|||
{
|
||||
try
|
||||
{
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido;
|
||||
double anguloCorredor = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.OrientacaoMovimento;
|
||||
double angulo = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.AnguloCarroDefinido;
|
||||
double anguloCorredor = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.OrientacaoMovimento;
|
||||
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)anguloCorredor);
|
||||
}
|
||||
catch { }
|
||||
|
|
@ -180,7 +180,7 @@ namespace AgroBase.Forms
|
|||
ultimoPonto = Pontos[Pontos.Count - 2][Pontos[Pontos.Count - 2].Count - 1];
|
||||
}
|
||||
|
||||
var Gps = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
|
||||
var Gps = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps;
|
||||
|
||||
pnlOrientacaoGps.Invalidate();
|
||||
lblStatusGPS.Text = $"GPS - Precisão: {Gps.PrecisaoCm} cm, " +
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ namespace AgroBase
|
|||
|
||||
tkbVelocidade.Minimum = 0;
|
||||
tkbVelocidade.Maximum = 100;
|
||||
FuncoesGlobais.PreencheValorTrackBar(tkbVelocidade, Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP);
|
||||
FuncoesGlobais.PreencheValorTrackBar(tkbVelocidade, Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento);
|
||||
|
||||
tkbAngulo.Minimum = 0;
|
||||
tkbAngulo.Maximum = 90;
|
||||
|
|
@ -181,7 +181,7 @@ namespace AgroBase
|
|||
trkKmh.Minimum = 0;
|
||||
trkKmh.Maximum = 100;
|
||||
|
||||
trkRPM.Minimum = Variaveis.OperacaoEmAndamento.Controle.RPM_Min;
|
||||
trkRPM.Minimum = Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent;
|
||||
trkRPM.Maximum = VariaveisEquipamento.RPM_Max_Roda;
|
||||
|
||||
AtualizaRPM((int)Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP);
|
||||
|
|
@ -267,8 +267,8 @@ namespace AgroBase
|
|||
|
||||
private void tkbVelocidadeMP_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP = tkbVelocidade.Value;
|
||||
lblVelocidade.Text = "Velocidade: " + Variaveis.OperacaoEmAndamento.Controle.VelocidadeMP + "%";
|
||||
Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento = tkbVelocidade.Value;
|
||||
lblVelocidade.Text = "Velocidade: " + Variaveis.OperacaoEmAndamento.Parametros.Controle.DirVelocidadeMovimento + "%";
|
||||
}
|
||||
|
||||
private void tkbAngulo_ValueChanged(object sender, EventArgs e)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ namespace AgroBase.Forms
|
|||
|
||||
private async Task tmrLeitura_Tick()
|
||||
{
|
||||
var Imu = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU;
|
||||
var Imu = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.IMU;
|
||||
AnguloX = Imu.InclinacaoFrontal;
|
||||
AnguloY = Imu.InclinacaoLateral;
|
||||
AnguloZ = Imu.Rotacao;
|
||||
|
|
|
|||
|
|
@ -181,7 +181,8 @@
|
|||
Aguardando = 3,
|
||||
EmAndamento = 4,
|
||||
Parado = 5,
|
||||
Concluido = 6
|
||||
Concluido = 6,
|
||||
Erro = 7
|
||||
}
|
||||
|
||||
public enum StatusCarroMapa
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ namespace AgroBase.Models
|
|||
public DateTime UltimoComandoRespondido { get; set; }
|
||||
public double AnguloCarroDefinido { get; set; }
|
||||
public int Heartbeat { get; set; } = 0;
|
||||
public double LeverArmLateral { get; set; } = 0;
|
||||
public double LeverArmFrontal { get; set; } = 0;
|
||||
|
||||
public GPSModel Clone()
|
||||
{
|
||||
|
|
@ -105,6 +107,10 @@ namespace AgroBase.Models
|
|||
PDOP = PDOP,
|
||||
VDOP = VDOP,
|
||||
BaseID = BaseID,
|
||||
LeverArmFrontal = LeverArmFrontal,
|
||||
LeverArmLateral = LeverArmLateral,
|
||||
X = X,
|
||||
Y = Y
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -826,7 +826,7 @@ namespace AgroBase
|
|||
private static bool VerificaComandoValidoSonar(Keys Comando)
|
||||
{
|
||||
List<Keys> ComandosImpedidos = new List<Keys>();
|
||||
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
|
||||
var Sonar = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.OperadorVisual;
|
||||
Sonar?.Resumo?.AtualizarStatusBloqueio(false);
|
||||
var DeveParar = Sonar?.Resumo?.DeveParar ?? false;
|
||||
if (DeveParar)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public class MPCController
|
|||
|
||||
public async Task EnviarDadosTrajetoria(List<PontoTrajetoriaModel> _trajetoria)
|
||||
{
|
||||
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
||||
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
|
||||
|
||||
var trajetoria = new
|
||||
{
|
||||
|
|
@ -78,10 +78,10 @@ public class MPCController
|
|||
})
|
||||
.ToList(),
|
||||
horizonte = Horizonte,
|
||||
angulo_max_graus = _Controle.Angulo_Max,
|
||||
angulo_max_graus = pControle.DirAnguloMaximo,
|
||||
distancia_entre_eixos = (VariaveisEquipamento.DistanciaEntreEixos / 100.0),
|
||||
velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Controle.PercentualVelocidadeMin),
|
||||
velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Controle.PercentualVelocidadeMax)
|
||||
velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent),
|
||||
velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent)
|
||||
};
|
||||
|
||||
await Variaveis.MqttServiceLocal.PublishAsync(
|
||||
|
|
@ -101,7 +101,7 @@ public class MPCController
|
|||
_dt = (EnviadoEm - _ultimaAtualizacao).TotalSeconds;
|
||||
double dtCalc = Math.Max(tempoMinimo, Math.Min(tempoMaximo, _dt));
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
var dadosEnvio = new
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ public class MPCControllerAprimorado
|
|||
|
||||
public MPCControllerAprimorado()
|
||||
{
|
||||
this.maxAnguloDirecao = Variaveis.OperacaoEmAndamento?.Controle?.Angulo_Max ?? 30.0;
|
||||
this.maxAnguloDirecao = Variaveis.OperacaoEmAndamento.Parametros?.Controle?.DirAnguloMaximo ?? 30.0;
|
||||
this.maxAngulo4Rodas = this.maxAnguloDirecao * 0.8;
|
||||
this.velocidadeMin = Variaveis.OperacaoEmAndamento?.Controle?.PercentualVelocidadeMin ?? 20.0;
|
||||
this.velocidadeMax = Variaveis.OperacaoEmAndamento?.Controle?.PercentualVelocidadeMax ?? 100.0;
|
||||
this.velocidadeMin = Variaveis.OperacaoEmAndamento.Parametros?.Controle?.MovVelocidadeCErvasPercent ?? 20.0;
|
||||
this.velocidadeMax = Variaveis.OperacaoEmAndamento.Parametros?.Controle?.MovVelocidadeSErvasPercent ?? 100.0;
|
||||
}
|
||||
|
||||
public (double anguloControle, Enums.TipoMovimentoDirecional modo) CalcularControle(GPSModel posicalAtual, double velocidadeAtual, List<GPSModel> proximaTrajetoria, Enums.TipoMovimentoDirecional[] modosPermitidos)
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ public class MPCControllerSimple
|
|||
{
|
||||
// Definições baseadas em variáveis globais
|
||||
this.horizon = Convert.ToInt32(distancePredict / TrajetoriaMapaOperacaoModel.DistanciaEntrePontos);
|
||||
this.maxSteeringAngle = Variaveis.OperacaoEmAndamento?.Controle?.Angulo_Max ?? 30.0;
|
||||
this.maxSteeringAngle = Variaveis.OperacaoEmAndamento.Parametros.Controle?.DirAnguloMaximo ?? 30.0;
|
||||
this.maxSteeringAngleFourWheels = this.maxSteeringAngle * 1.0;
|
||||
this.minVelocity = Variaveis.OperacaoEmAndamento?.Controle?.PercentualVelocidadeMin ?? 20.0;
|
||||
this.maxVelocity = Variaveis.OperacaoEmAndamento?.Controle?.PercentualVelocidadeMax ?? 100.0;
|
||||
this.minVelocity = Variaveis.OperacaoEmAndamento.Parametros.Controle?.MovVelocidadeCErvasPercent ?? 20.0;
|
||||
this.maxVelocity = Variaveis.OperacaoEmAndamento.Parametros.Controle?.MovVelocidadeSErvasPercent ?? 100.0;
|
||||
this.accelerationLimit = 1.5; // Limita aceleração a valores realistas
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ public class MPCControllerSimple
|
|||
List<(double steering, Enums.TipoMovimentoDirecional mode)> candidates = GenerateControlCandidates();
|
||||
double bestCost = double.MaxValue;
|
||||
(double steeringAngle, Enums.TipoMovimentoDirecional mode) bestControl = (0, Enums.TipoMovimentoDirecional.RodasDianteiras);
|
||||
bool insideStreet = Variaveis.OperacaoEmAndamento.Sensoriamento.Trajetoria.CorredorAtual.Dentro;
|
||||
bool insideStreet = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Trajetoria.CorredorAtual.Dentro;
|
||||
|
||||
double velocity = FuncoesMatematicas.CalculaVelocidadeMsPercentual(currentVelocity);
|
||||
double distanciaPasso = dt * velocity;
|
||||
|
|
|
|||
|
|
@ -666,7 +666,7 @@ namespace AgroBase.Models
|
|||
|
||||
private void DrawObstacle(Graphics g, float xRobot, float yRobot, Color pointColor, Color borderColor, float angle, Obstaculo obstaculo, float PxToCm)
|
||||
{
|
||||
GPSModel posicaoRobo = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
|
||||
GPSModel posicaoRobo = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps;
|
||||
GPSModel posicaoObstaculo = GPSUtils.GerarPontoDeslocado(posicaoRobo, angle, obstaculo.DistanciaMedia_mm / 1000);
|
||||
|
||||
float x = xRobot + (float)((posicaoObstaculo.Longitude - posicaoRobo.Longitude) * _zoom);
|
||||
|
|
|
|||
|
|
@ -157,66 +157,66 @@ namespace AgroBase.Models
|
|||
}
|
||||
}
|
||||
|
||||
public void PopularTrajetoriaMapa()
|
||||
public void PopularTrajetoriaMapa(MapaFeatureCollectionModel dados = null)
|
||||
{
|
||||
if (mapaService.DadosMapa != null)
|
||||
if (dados != null) mapaService.DadosMapa = dados;
|
||||
if (mapaService.DadosMapa == null) return;
|
||||
|
||||
double OrientacaoRuas = -999;
|
||||
//DistanciaTotal = 0;
|
||||
/*if (!RuasPercorrer.Any())
|
||||
{
|
||||
double OrientacaoRuas = -999;
|
||||
//DistanciaTotal = 0;
|
||||
/*if (!RuasPercorrer.Any())
|
||||
{
|
||||
RuasPercorrer = mapaService.DadosMapa.features.Select(x => x.geometry.id).ToList();
|
||||
}*/
|
||||
TrajetoriaMapa = new List<List<GPSModel>>();
|
||||
RuasPercorrer = mapaService.DadosMapa.features.Select(x => x.geometry.id).ToList();
|
||||
}*/
|
||||
TrajetoriaMapa = new List<List<GPSModel>>();
|
||||
|
||||
foreach (var ID in RuasPercorrer)
|
||||
foreach (var ID in RuasPercorrer)
|
||||
{
|
||||
var rua = mapaService.DadosMapa.features.FirstOrDefault(x => ID == x.geometry.id);
|
||||
if (rua != null)
|
||||
{
|
||||
var rua = mapaService.DadosMapa.features.FirstOrDefault(x => ID == x.geometry.id);
|
||||
if (rua != null)
|
||||
TrajetoriaMapa.Add(new List<GPSModel>());
|
||||
foreach (var ponto in rua.geometry.coordinates)
|
||||
{
|
||||
TrajetoriaMapa.Add(new List<GPSModel>());
|
||||
foreach (var ponto in rua.geometry.coordinates)
|
||||
/*if (rua.geometry.coordinates.IndexOf(ponto) == 0 || rua.geometry.coordinates.IndexOf(ponto) == rua.geometry.coordinates.Count - 1)
|
||||
{
|
||||
/*if (rua.geometry.coordinates.IndexOf(ponto) == 0 || rua.geometry.coordinates.IndexOf(ponto) == rua.geometry.coordinates.Count - 1)
|
||||
{
|
||||
continue;
|
||||
}*/
|
||||
continue;
|
||||
}*/
|
||||
|
||||
GPSModel item = new GPSModel()
|
||||
{
|
||||
Longitude = ponto[0],
|
||||
Latitude = ponto[1],
|
||||
};
|
||||
TrajetoriaMapa[TrajetoriaMapa.Count - 1].Add(item);
|
||||
/*if (Trajetoria[Trajetoria.Count - 1].Count > 1)
|
||||
{
|
||||
DistanciaTotal += GPSService.DistanciaEntrePontos(Trajetoria[Trajetoria.Count - 1][Trajetoria[Trajetoria.Count - 1].Count - 2], item);
|
||||
}*/
|
||||
}
|
||||
GPSModel item = new GPSModel()
|
||||
{
|
||||
Longitude = ponto[0],
|
||||
Latitude = ponto[1],
|
||||
};
|
||||
TrajetoriaMapa[TrajetoriaMapa.Count - 1].Add(item);
|
||||
/*if (Trajetoria[Trajetoria.Count - 1].Count > 1)
|
||||
{
|
||||
DistanciaTotal += GPSService.DistanciaEntrePontos(Trajetoria[Trajetoria.Count - 1][Trajetoria[Trajetoria.Count - 1].Count - 2], item);
|
||||
}*/
|
||||
}
|
||||
|
||||
var Rua = TrajetoriaMapa[TrajetoriaMapa.Count - 1];
|
||||
if (OrientacaoRuas == -999)
|
||||
var Rua = TrajetoriaMapa[TrajetoriaMapa.Count - 1];
|
||||
if (OrientacaoRuas == -999)
|
||||
{
|
||||
OrientacaoRuas = GPSUtils.CalcularOrientacao(Rua[Rua.Count - 1], Rua[Rua.Count - 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
double MargemErroAngulo = 45;
|
||||
double orientacaoRua = GPSUtils.CalcularOrientacao(Rua[Rua.Count - 1], Rua[Rua.Count - 2]);
|
||||
double anguloOposto = (orientacaoRua + 180) % 360;
|
||||
if ((anguloOposto + MargemErroAngulo) >= OrientacaoRuas && (anguloOposto - MargemErroAngulo) <= OrientacaoRuas)
|
||||
{
|
||||
OrientacaoRuas = GPSUtils.CalcularOrientacao(Rua[Rua.Count - 1], Rua[Rua.Count - 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
double MargemErroAngulo = 45;
|
||||
double orientacaoRua = GPSUtils.CalcularOrientacao(Rua[Rua.Count - 1], Rua[Rua.Count - 2]);
|
||||
double anguloOposto = (orientacaoRua + 180) % 360;
|
||||
if ((anguloOposto + MargemErroAngulo) >= OrientacaoRuas && (anguloOposto - MargemErroAngulo) <= OrientacaoRuas)
|
||||
{
|
||||
Rua.Reverse();
|
||||
}
|
||||
Rua.Reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TrajetoriaMapa.Any())
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Trajetoria = new TrajetoriaMapaOperacaoModel(TrajetoriaMapa);
|
||||
Variaveis.OperacaoEmAndamento.Trajetoria.ProjetarTrajetoriaFixa();
|
||||
}
|
||||
if (TrajetoriaMapa.Any())
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.Trajetoria = new TrajetoriaMapaOperacaoModel(TrajetoriaMapa);
|
||||
Variaveis.OperacaoEmAndamento.Trajetoria.ProjetarTrajetoriaFixa();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace AgroBase.Models.Modules
|
|||
FuncoesPinout.SDA,
|
||||
FuncoesPinout.SCL,
|
||||
};
|
||||
public int QuantidadeBicos { get; set; } = 4;
|
||||
//public int QuantidadeBicos { get; set; } = 4;
|
||||
public double DensidadeHerbicida { get; set; } = 1.0;
|
||||
public List<AtuadorBicoModel> BicosPulverizadores { get; set; } = new List<AtuadorBicoModel>();
|
||||
public List<AtuadorBombaModel> BombasPressurizadoras { get; set; } = new List<AtuadorBombaModel>();
|
||||
|
|
@ -90,7 +90,7 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
get
|
||||
{
|
||||
return VolumeReservatorio / Variaveis.OperacaoEmAndamento.CapacidadeReservatorio * 100.0;
|
||||
return VolumeReservatorio / Variaveis.OperacaoEmAndamento.Parametros.CapacidadeReservatorio * 100.0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
|
@ -140,7 +140,7 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
public void AtualizaPercentualErvas()
|
||||
{
|
||||
double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento.TempoDecorridoSeg * 1000.0;
|
||||
double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.TempoDecorridoSeg * 1000.0;
|
||||
|
||||
if (tempoTotalOperacao > 0)
|
||||
{
|
||||
|
|
@ -225,7 +225,6 @@ namespace AgroBase.Models.Modules
|
|||
_EnderecoCAN_Rx = 0x12,
|
||||
_TaxaAmostragem = 1000,
|
||||
RequisitarDados = true,
|
||||
QuantidadeBicos = 4,
|
||||
BicosPulverizadores = new List<AtuadorBicoModel>(),
|
||||
BombasPressurizadoras = new List<AtuadorBombaModel>()
|
||||
{
|
||||
|
|
@ -422,7 +421,7 @@ namespace AgroBase.Models.Modules
|
|||
},
|
||||
},
|
||||
};
|
||||
for (int i = 0; i < Atuador.QuantidadeBicos; i++)
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++)
|
||||
{
|
||||
int posicao = (i + 1);
|
||||
Atuador.BicosPulverizadores.Add(new AtuadorBicoModel()
|
||||
|
|
@ -779,7 +778,7 @@ namespace AgroBase.Models.Modules
|
|||
bomba.ComandoAtuar = false;
|
||||
}
|
||||
// Religa a bomba caso esteja desligada, o nivel de herbicida esta estavel e o pulverizador automatico esta ligado
|
||||
else if (PercentualReservatorio >= VariaveisEquipamento.PercentualReservatorioMin && leituraEstado == false && Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico)
|
||||
else if (PercentualReservatorio >= VariaveisEquipamento.PercentualReservatorioMin && leituraEstado == false && Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico)
|
||||
{
|
||||
bomba.ComandoAtuar = true;
|
||||
}
|
||||
|
|
@ -1077,7 +1076,7 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
(byte)Componente,
|
||||
(byte)(conectar ? 1 : 0),
|
||||
(byte)Variaveis.OperacaoEmAndamento.Controle.PressaoLinha,
|
||||
(byte)Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha,
|
||||
(byte)(pinout.Pinos.FirstOrDefault(x => x.ComponenteID == ID && x.Funcao == FuncoesPinout.ENA)?.Pino ?? PinoutUtils.PINO_INVALIDO),
|
||||
(byte)(pinout.Pinos.FirstOrDefault(x => x.Funcao == FuncoesPinout.CS)?.Pino ?? PinoutUtils.PINO_INVALIDO),
|
||||
};
|
||||
|
|
@ -1105,12 +1104,12 @@ namespace AgroBase.Models.Modules
|
|||
new byte[]
|
||||
{
|
||||
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
|
||||
(byte)(Variaveis.OperacaoEmAndamento.Controle.PressaoLinha)
|
||||
(byte)(Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public bool AtingiuPressao() => Variaveis.OperacaoEmAndamento.DispAtu.Dados.PressaoLinha >= Variaveis.OperacaoEmAndamento.Controle.PressaoLinha;
|
||||
public bool AtingiuPressao() => Variaveis.OperacaoEmAndamento.DispAtu.Dados.PressaoLinha >= Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
get
|
||||
{
|
||||
return Convert.ToInt32(((Variaveis.OperacaoEmAndamento.Controle?.VelocidadeMP ?? 0) / 100.0) * Velocidade_Max);
|
||||
return Convert.ToInt32(((Variaveis.OperacaoEmAndamento.Parametros?.Controle?.DirVelocidadeMovimento ?? 0) / 100.0) * Velocidade_Max);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
|
||||
private double VelocidadeAtual =>
|
||||
FuncoesMatematicas.CalculaVelocidadePercentualMs(Variaveis.OperacaoEmAndamento.Sensoriamento.Movimentacao?.VelocidadeMedia ?? 0);
|
||||
FuncoesMatematicas.CalculaVelocidadePercentualMs(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.Movimentacao?.VelocidadeMedia ?? 0);
|
||||
|
||||
private bool StatusControleEmFreio =>
|
||||
(Variaveis.OperacaoEmAndamento.Controle?.TiposControle?
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ using static AgroBase.Models.Enums;
|
|||
using System.Globalization;
|
||||
using System.Data;
|
||||
using static AgroBase.Services.LoRaEspService;
|
||||
using System.Windows.Forms;
|
||||
using AgroBase.Services.Operadores;
|
||||
using AgroBase.Models.Operadores;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -1689,7 +1688,7 @@ namespace AgroBase.Models.Modules
|
|||
},
|
||||
};
|
||||
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.QuantidadeCamerasSolo; i++)
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdCamerasSolo; i++)
|
||||
{
|
||||
obj.CamerasSolo.Add(new OAKCameraModel());
|
||||
}
|
||||
|
|
@ -2025,7 +2024,7 @@ namespace AgroBase.Models.Modules
|
|||
GeneralJoystick.EnviarComandoSensoriamento(S_Code.sLED, ledOP.ID, comportamento);
|
||||
}
|
||||
|
||||
var statusLedAt = Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico ? StatusLED.Aceso : StatusLED.Apagado;
|
||||
var statusLedAt = Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico ? StatusLED.Aceso : StatusLED.Apagado;
|
||||
var valAt = (int?)(ledAT?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.StatusLEDComando)?.atual?.valor) ?? 0;
|
||||
if (ledAT != null && (!ledAT.Comportamento.statusLED.Equals(statusLedAt) || (valAt != (int)statusLedAt)))
|
||||
{
|
||||
|
|
@ -2931,7 +2930,7 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
case DadosLoRaParse.ComandoControle:
|
||||
{
|
||||
Keys tecla = (Keys)data[2];
|
||||
BotoesJoystick tecla = (BotoesJoystick)data[2];
|
||||
int percentualVelocidadeSp = data[3];
|
||||
TipoMovimentoDirecional tipoMovimentoDirecional = (TipoMovimentoDirecional)data[4];
|
||||
int anguloMp = data[5];
|
||||
|
|
@ -2939,15 +2938,17 @@ namespace AgroBase.Models.Modules
|
|||
T_Code dispositivo = (T_Code)data[6];
|
||||
bool emergencia = data[7] == 1;
|
||||
|
||||
OperacaoControleBaseModel Controle = new OperacaoControleBaseModel()
|
||||
OperacaoComandoBaseModel Controle = new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Tecla = tecla,
|
||||
AnguloMP = anguloMp,
|
||||
Controle = new OperacaoComandoBaseControleModel()
|
||||
{
|
||||
AnguloSP = anguloMp,
|
||||
PercentualVelocidadeSP = percentualVelocidadeSp,
|
||||
TipoMovimentoDirecional = tipoMovimentoDirecional,
|
||||
},
|
||||
Emergencia = emergencia,
|
||||
PercentualVelocidadeSP = percentualVelocidadeSp,
|
||||
TipoMovimento = tipoMovimentoDirecional,
|
||||
//VelocidadeMP = velocidadeMp,
|
||||
Dispositivo = dispositivo
|
||||
};
|
||||
Variaveis.OperacaoEmAndamento.ExecutaComandoDaBase(Controle);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -5,25 +5,55 @@ namespace AgroBase.Models.Operacoes
|
|||
{
|
||||
public class OperacaoParametrosModel
|
||||
{
|
||||
public string RoverId { get; set; }
|
||||
public bool Alive { get; set; }
|
||||
public bool Configurado { get; set; }
|
||||
public ModoOperacao Modo { get; set; }
|
||||
public string Descricao { get; set; }
|
||||
public int QtdCamerasSolo { get; set; }
|
||||
public int QtdBicos { get; set; }
|
||||
public double CapacidadeReservatorio { get; set; }
|
||||
public List<OperacaoModulosMandatoriosModel> ModulosMandatorios { get; set; }
|
||||
public List<OperacaoParametrosMandatoriosModel> ParametrosMandatorios { get; set; }
|
||||
public int MovVelocidadeSErvasPercent { get; set; }
|
||||
public int MovVelocidadeCErvasPercent { get; set; }
|
||||
public int DirAnguloMaximo { get; set; }
|
||||
public int DirVelocidadeMovimento { get; set; }
|
||||
public TiposControladorDirecional DirTipoMovimento { get; set; }
|
||||
public int AtuPercentualDeteccaoVertical { get; set; }
|
||||
public double AtuCapacidadeReservatorio { get; set; }
|
||||
public double AtuPressaoLinha { get; set; }
|
||||
public int AtuDuracaoAtuacao { get; set; }
|
||||
public MapasModel Mapa { get; set; }
|
||||
public UltrasonicA05Configuracoes ConfiguracaoUltrassom { get; set; }
|
||||
public OperacaoParametrosControleModel Controle { get; set; }
|
||||
|
||||
public MapaFeatureCollectionModel Mapa { get; set; }
|
||||
public List<string> RuasPercorrer { get; set; }
|
||||
|
||||
public OperacaoSensoriamentoLogModel DadosLeitura { get; set; }
|
||||
}
|
||||
|
||||
public class OperacaoParametrosControleModel
|
||||
{
|
||||
public bool SonarAtivado { get; set; }
|
||||
public int QtdCamerasSolo { get; set; }
|
||||
public bool MovimentoAutomatico { get; set; }
|
||||
public bool PulverizadorAutomatico { get; set; }
|
||||
public bool FrenagemAtuomatica { get; set; }
|
||||
public bool FrenagemAutomatica { get; set; }
|
||||
|
||||
public int MovVelocidadeSErvasPercent { get; set; }
|
||||
public int MovRpmMax
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.Convert.ToInt32(VariaveisEquipamento.RPM_Max_Roda * (MovVelocidadeSErvasPercent / 100.0));
|
||||
}
|
||||
}
|
||||
public int MovVelocidadeCErvasPercent { get; set; }
|
||||
public int MovRpmMin
|
||||
{
|
||||
get
|
||||
{
|
||||
return System.Convert.ToInt32(VariaveisEquipamento.RPM_Max_Roda * (MovVelocidadeCErvasPercent / 100.0));
|
||||
}
|
||||
}
|
||||
public int DirAnguloMaximo { get; set; }
|
||||
public double DirVelocidadeMovimento { get; set; }
|
||||
public TiposControladorDirecional DirTipoMovimento { get; set; }
|
||||
public double AtuPressaoLinha { get; set; }
|
||||
public int AtuDuracaoAtuacao { get; set; }
|
||||
public double AtuPercentualInicioPulverizacao { get; set; }
|
||||
public double AtuAlturaAreaPulverizacao { get; set; }
|
||||
public double AtuPercentualErvasBicoOn { get; set; }
|
||||
public double AtuPercentualErvasBicoOff { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,10 +61,10 @@ namespace AgroBase.Models.Operadores
|
|||
|
||||
public void AtualizarStatusBloqueio(bool consideraEmMovimento)
|
||||
{
|
||||
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
|
||||
var Sonar = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.OperadorVisual;
|
||||
ObstaculoDetectado = (Sonar.Analises?.matriz_confianca?.block?.decision?.parar ?? false);
|
||||
|
||||
if (!Variaveis.OperacaoEmAndamento.Controle.SonarAtivado)
|
||||
if (!Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado)
|
||||
{
|
||||
_comandoParadaEnviado = false;
|
||||
DeveParar = false;
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ namespace AgroBase.Models
|
|||
public void DetectarObstaculos(OAKDLiteSubdivisoesModel modelo)
|
||||
{
|
||||
Subdivisoes = service.ConverterSubdivisoes(modelo);
|
||||
Obstaculos = service.IdentificarObstaculos(Subdivisoes, Variaveis.OperacaoEmAndamento.Controle.SonarAtivado);
|
||||
Obstaculos = service.IdentificarObstaculos(Subdivisoes, Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado);
|
||||
|
||||
AtualizarDadosObstaculos(modelo?.x_max ?? 640, modelo?.y_max ?? 480);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
get
|
||||
{
|
||||
return DistanciaMedia / FuncoesMatematicas.ConverteKmhParaMs(Variaveis.OperacaoEmAndamento.Sensoriamento.Movimentacao.VelocidadeMedia);
|
||||
return DistanciaMedia / FuncoesMatematicas.ConverteKmhParaMs(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Movimentacao.VelocidadeMedia);
|
||||
}
|
||||
}
|
||||
public double DeslocamentoNecessarioDesvio
|
||||
|
|
@ -769,18 +769,18 @@ namespace AgroBase.Models
|
|||
{
|
||||
get
|
||||
{
|
||||
double anguloAbsolutoObstaculo = (Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.AnguloCarroDefinido + AnguloInicial + AnguloFinal) / 2.0;
|
||||
double anguloAbsolutoObstaculo = (Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.AnguloCarroDefinido + AnguloInicial + AnguloFinal) / 2.0;
|
||||
double anguloRad = anguloAbsolutoObstaculo * (Math.PI / 180.0);
|
||||
|
||||
// Supondo que a distância seja em metros e utilizando uma aproximação simples da Terra como esfera
|
||||
// para converter distância e ângulo em mudança de latitude/longitude.
|
||||
double deltaLatitude = (DistanciaMedia * Math.Cos(anguloRad)) / 111111; // Dividindo por 111111 para converter metros em graus
|
||||
double deltaLongitude = (DistanciaMedia * Math.Sin(anguloRad)) / (111111 * Math.Cos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Latitude * (Math.PI / 180.0)));
|
||||
double deltaLongitude = (DistanciaMedia * Math.Sin(anguloRad)) / (111111 * Math.Cos(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Latitude * (Math.PI / 180.0)));
|
||||
|
||||
return new GPSModel
|
||||
{
|
||||
Latitude = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Latitude + deltaLatitude,
|
||||
Longitude = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Longitude + deltaLongitude
|
||||
Latitude = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Latitude + deltaLatitude,
|
||||
Longitude = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Longitude + deltaLongitude
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ namespace AgroBase.Models
|
|||
public double TempoEntreLeituras { get; private set; }
|
||||
private void AtualizarTempoEntreLeituras()
|
||||
{
|
||||
double dt = Math.Min((1.0 / GPSService.TaxaAmostragemHz), (UltimaAtualizacaoDados - Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Momento).TotalSeconds);
|
||||
double dt = Math.Min((1.0 / GPSService.TaxaAmostragemHz), (UltimaAtualizacaoDados - Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Momento).TotalSeconds);
|
||||
TempoEntreLeituras = dt;
|
||||
UltimaAtualizacaoDados = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Momento;
|
||||
UltimaAtualizacaoDados = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Momento;
|
||||
}
|
||||
|
||||
public List<List<GPSModel>> RuasPlantacao { get; set; }
|
||||
|
|
@ -81,8 +81,8 @@ namespace AgroBase.Models
|
|||
{
|
||||
get
|
||||
{
|
||||
double distPP = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, PrimeiroPontoRuaMapa);
|
||||
double distUP = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, UltimoPontoRuaMapa);
|
||||
double distPP = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, PrimeiroPontoRuaMapa);
|
||||
double distUP = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, UltimoPontoRuaMapa);
|
||||
|
||||
// 0 para mais próximo do primeiro ponto da rua (ENTRANDO)
|
||||
// 1 para mais próximo do último ponto da rua (SAINDO)
|
||||
|
|
@ -122,7 +122,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo)
|
||||
{
|
||||
Posicao = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps,
|
||||
Posicao = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps,
|
||||
LarguraCorredor = 1.0,
|
||||
idxCorredor = CorredorAtual?.Idx ?? 0,
|
||||
Visitado = true
|
||||
|
|
@ -215,7 +215,7 @@ namespace AgroBase.Models
|
|||
private void AtualizarAnguloCaminho()
|
||||
{
|
||||
PontoTrajetoriaModel pontoComparar = PontoAtual.Aproximando ? PontoAtual : ProximoPonto != null ? ProximoPonto : PontoAtual;
|
||||
AnguloCaminho = GPSUtils.CalcularOrientacao(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, pontoComparar.Posicao);
|
||||
AnguloCaminho = GPSUtils.CalcularOrientacao(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, pontoComparar.Posicao);
|
||||
}
|
||||
[JsonProperty]
|
||||
public double DistanciaEsquerda { get; private set; }
|
||||
|
|
@ -223,8 +223,8 @@ namespace AgroBase.Models
|
|||
public double DistanciaDireita { get; private set; }
|
||||
private void AtualizarDistanciasLaterais()
|
||||
{
|
||||
DistanciaEsquerda = CalcularDistanciaLateral(true, Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual?.idxRuaEsquerda ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida);
|
||||
DistanciaDireita = CalcularDistanciaLateral(false, Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual?.idxRuaDireita ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida);
|
||||
DistanciaEsquerda = CalcularDistanciaLateral(true, Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, CorredorAtual?.idxRuaEsquerda ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida);
|
||||
DistanciaDireita = CalcularDistanciaLateral(false, Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, CorredorAtual?.idxRuaDireita ?? 0, PontoAtual?.Direcao ?? DirecaoCarroRua.Ida);
|
||||
}
|
||||
|
||||
public double CalcularDistanciaLateral(bool ladoEsquerdo, GPSModel posicaoAtual, int idxRua, DirecaoCarroRua direcaoAtual)
|
||||
|
|
@ -472,11 +472,11 @@ namespace AgroBase.Models
|
|||
{
|
||||
if (!velocidadeSemErvasMs.HasValue)
|
||||
{
|
||||
velocidadeSemErvasMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeMax) * 0.8;
|
||||
velocidadeSemErvasMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeSErvasPercent) * 0.8;
|
||||
}
|
||||
if (!velocidadeComErvasMs.HasValue)
|
||||
{
|
||||
velocidadeComErvasMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeMin);
|
||||
velocidadeComErvasMs = FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent);
|
||||
}
|
||||
|
||||
// Supondo que metade do percurso tem ervas e a outra metade não tem
|
||||
|
|
@ -527,12 +527,12 @@ namespace AgroBase.Models
|
|||
if (CorredorAtual.Idx > 0) return;
|
||||
if (!CorredorAtual.Dentro) return;
|
||||
|
||||
GPSModel posicaoAtual = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps.Clone();
|
||||
GPSModel posicaoAtual = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps.Clone();
|
||||
|
||||
if (PrimeiroPontoDentroMapa == null) PrimeiroPontoDentroMapa = posicaoAtual;
|
||||
|
||||
var OpVisual = Variaveis.OperacaoEmAndamento.Sensoriamento?.OperadorVisual ?? new VisualWorkerModel();
|
||||
StatusModulo OpVisualStatus = Variaveis.OperacaoEmAndamento.Sensoriamento.ModulosSaude.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado;
|
||||
var OpVisual = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.OperadorVisual ?? new VisualWorkerModel();
|
||||
StatusModulo OpVisualStatus = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.ModulosSaude.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado;
|
||||
|
||||
if (OpVisualStatus != StatusModulo.Operante) return;
|
||||
|
||||
|
|
@ -558,7 +558,7 @@ namespace AgroBase.Models
|
|||
|
||||
private void AtualizarErroCombinado()
|
||||
{
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
//double anguloCamera = _Sensoriamento.OperadorVisual.Leitura.obj?.segmentacao?.angulo_rua ?? 0;
|
||||
double anguloCorredor = AnguloMedioCorredor;
|
||||
|
|
@ -575,7 +575,7 @@ namespace AgroBase.Models
|
|||
double curvaDaRua = GPSUtils.CalcularDiferencaAngulo(anguloProximoPonto, anguloCorredor);
|
||||
|
||||
// Peso do desalinhamento atual (prioriza alinhar o robô ao corredor)
|
||||
double pesoAlinhamento = Math.Min(Math.Abs(desalinhamentoComRua) / Variaveis.OperacaoEmAndamento.Controle.Angulo_Max, 1.0); // Normaliza até 30°
|
||||
double pesoAlinhamento = Math.Min(Math.Abs(desalinhamentoComRua) / Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo, 1.0); // Normaliza até 30°
|
||||
|
||||
// Peso do centro (prioriza ir pro ponto central do corredor)
|
||||
double pesoCentro = 1.0 - pesoAlinhamento;
|
||||
|
|
@ -736,9 +736,9 @@ namespace AgroBase.Models
|
|||
double limiarDistanciaMargem = DistanciaErroMapaPlantacao > -1 ? DistanciaErroMapaPlantacao : 5.0;
|
||||
double distanciaCorredor = CorredorAtual.DistanciaTotal;
|
||||
double distanciaRestanteCorredor = CorredorAtual.DistanciaRestante;
|
||||
double distanciaUltimoPontoCorredor = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual.Pontos.LastOrDefault().Posicao);
|
||||
var OpVisual = Variaveis.OperacaoEmAndamento.Sensoriamento?.OperadorVisual ?? new VisualWorkerModel();
|
||||
StatusModulo OpVisualStatus = Variaveis.OperacaoEmAndamento.Sensoriamento.ModulosSaude.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado;
|
||||
double distanciaUltimoPontoCorredor = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, CorredorAtual.Pontos.LastOrDefault().Posicao);
|
||||
var OpVisual = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.OperadorVisual ?? new VisualWorkerModel();
|
||||
StatusModulo OpVisualStatus = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.ModulosSaude.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado;
|
||||
var DadosSegmentacao = OpVisual.Analises?.segmentacao ?? new VisualWorkerMessageSegmentacaoSemanticaModel();
|
||||
|
||||
if (OpVisualStatus == StatusModulo.Operante || Variaveis.OperacaoEmAndamento.Simulando) //OpVisual.Iniciado &&
|
||||
|
|
@ -782,7 +782,7 @@ namespace AgroBase.Models
|
|||
double anguloControle = Variaveis.OperacaoEmAndamento.Controle.Angulo;
|
||||
if (abrirCurva && !CorredorAtual.Ultimo)
|
||||
{
|
||||
anguloControle = CorredorAtual.idxRuaDireita > CorredorAtual.idxRuaEsquerda ? Variaveis.OperacaoEmAndamento.Controle.Angulo_Min : Variaveis.OperacaoEmAndamento.Controle.Angulo_Max;
|
||||
anguloControle = CorredorAtual.idxRuaDireita > CorredorAtual.idxRuaEsquerda ? -Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo : Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo;
|
||||
}
|
||||
|
||||
int pontosMarcar = 0;
|
||||
|
|
@ -812,7 +812,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
Console.WriteLine($"Angulo de controle definido de {Variaveis.OperacaoEmAndamento.Controle.Angulo} para {anguloControle}");
|
||||
Variaveis.OperacaoEmAndamento.Controle.Angulo = anguloControle;
|
||||
Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP = Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeMin;
|
||||
Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP = Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent;
|
||||
Variaveis.OperacaoEmAndamento.Controle.TipoMovimento = TipoMovimentoDirecional.MovimentoArco;
|
||||
Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Dir).DelayEnvioComandoExtra = 1500;
|
||||
Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Mov).DelayEnvioComandoExtra = 2000;
|
||||
|
|
@ -933,7 +933,7 @@ namespace AgroBase.Models
|
|||
Console.WriteLine("Muito tempo sem receber novo comando do Manager Worker! Reduzindo Velocidade!");
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosControle,
|
||||
("velocidade_sp", _Controle.PercentualVelocidadeMin)
|
||||
("velocidade_sp", Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1179,7 +1179,7 @@ namespace AgroBase.Models
|
|||
idxCorredor = 0,
|
||||
idxPonto = 0,
|
||||
idxPontoCorredor = 0,
|
||||
Posicao = posicaoRobo ?? Variaveis.OperacaoEmAndamento.Sensoriamento.Gps,
|
||||
Posicao = posicaoRobo ?? Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps,
|
||||
Orientacao = 0,
|
||||
Direcao = direcaoAtual,
|
||||
Visitado = true,
|
||||
|
|
@ -1478,7 +1478,7 @@ namespace AgroBase.Models
|
|||
|
||||
public void AjustarTrajetoriaParaDesvio(Obstaculo obstaculo)
|
||||
{
|
||||
GPSModel posicaoAtual = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps;
|
||||
GPSModel posicaoAtual = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps;
|
||||
|
||||
double distanciaObstaculo = ((double)obstaculo.DistanciaMedia_mm / 1000);
|
||||
double larguraObstaculo = ((double)obstaculo.Largura_mm / 1000);
|
||||
|
|
@ -1726,7 +1726,7 @@ namespace AgroBase.Models
|
|||
|
||||
private void AtualizarOrientacaoAtual()
|
||||
{
|
||||
OrientacaoAtual = GPSUtils.CalcularOrientacao(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, Posicao);
|
||||
OrientacaoAtual = GPSUtils.CalcularOrientacao(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, Posicao);
|
||||
}
|
||||
|
||||
private void AtualizarOrientacaoAnterior()
|
||||
|
|
@ -1780,7 +1780,7 @@ namespace AgroBase.Models
|
|||
|
||||
private void AtualizarDistanciaAtual()
|
||||
{
|
||||
DistanciaAtual = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, Posicao);
|
||||
DistanciaAtual = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Gps, Posicao);
|
||||
}
|
||||
|
||||
private void AtualizarDistanciaAnterior()
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace AgroBase.Models
|
|||
public static string CaminhoParametros { get; } = "Parametros/";
|
||||
public static string CaminhoModelos { get; } = "C:\\AgroBaseModels\\";
|
||||
public static List<IDispositivosService> DispositivosConectados { get; set; } = new List<IDispositivosService>();
|
||||
public static OperacaoModel OperacaoEmAndamento { get; set; } = new OperacaoModel(ModoOperacao.Manual);
|
||||
public static OperacaoModel OperacaoEmAndamento { get; set; } = new OperacaoModel(ModoOperacao.MapaGPS);
|
||||
public static MqttService MqttServiceLocal { get; set; }
|
||||
public static MqttService MqttServiceBase { get; set; }
|
||||
public static LoRaEspService LoraService
|
||||
|
|
@ -109,7 +109,7 @@ namespace AgroBase.Models
|
|||
MqttServiceBase.Topicos.Clear();
|
||||
}
|
||||
|
||||
MqttServiceLocal = new MqttService("localhost", 1883, IsAgroMonitor ? "base" : VariaveisEquipamento.Parametros.serial_number, true, msg => Console.WriteLine($"[MQTT localhost:{1883}] - {msg}"));
|
||||
MqttServiceLocal = new MqttService("localhost", 1883, VariaveisEquipamento.Parametros.serial_number, true, msg => Console.WriteLine($"[MQTT localhost:{1883}] - {msg}"));
|
||||
await MqttServiceLocal.AdicionarNovoTopico(MapasVariaveisModel.TopicoCoordenadasGPS);
|
||||
await MqttServiceLocal.AdicionarNovoTopico(MapasVariaveisModel.TopicoTrajetoriaDinamica);
|
||||
await MqttServiceLocal.AdicionarNovoTopico(MapasVariaveisModel.TopicoSelecaoRuasMapa, true, 1, async (message) =>
|
||||
|
|
@ -120,14 +120,19 @@ namespace AgroBase.Models
|
|||
MqttServiceBase = new MqttService(VariaveisEquipamento.Parametros.base_ip, 1883, VariaveisEquipamento.Parametros.serial_number, false, msg => Console.WriteLine($"[MQTT {VariaveisEquipamento.Parametros.base_ip}:{1883}] - {msg}"));
|
||||
await MqttServiceBase.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttDispositivos);
|
||||
await MqttServiceBase.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttTelemetria.Replace("<id>", VariaveisEquipamento.Parametros.serial_number));
|
||||
await MqttServiceBase.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttParametros.Replace("<id>", VariaveisEquipamento.Parametros.serial_number));
|
||||
await MqttServiceBase.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttHeartbeat.Replace("<id>", VariaveisEquipamento.Parametros.serial_number), true, 1, async (message) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Mensagem)) return;
|
||||
VariaveisOperacao.PosicaoBase.UltimoComandoRespondido = DateTime.Now;
|
||||
});
|
||||
await MqttServiceBase.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", VariaveisEquipamento.Parametros.serial_number), true, 1, async (message) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Mensagem))
|
||||
return;
|
||||
if (string.IsNullOrEmpty(message.Mensagem)) return;
|
||||
try
|
||||
{
|
||||
string json = message.Mensagem;
|
||||
var cmd = JsonConvert.DeserializeObject<OperacaoControleBaseModel>(json);
|
||||
var cmd = JsonConvert.DeserializeObject<OperacaoComandoBaseModel>(json);
|
||||
OperacaoEmAndamento.ExecutaComandoDaBase(cmd);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -160,6 +165,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
string json = message.Mensagem;
|
||||
var posicao = JsonConvert.DeserializeObject<GPSModel>(json);
|
||||
posicao.Momento = DateTime.Now;
|
||||
VariaveisOperacao.PosicaoBase = posicao;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -197,15 +203,17 @@ namespace AgroBase.Models
|
|||
_parametros = value;
|
||||
}
|
||||
}
|
||||
public static string TopicoMqttHeartbeat { get; } = $"agrobot/v1/rover/<id>/heartbeat";
|
||||
public static string TopicoMqttComandos { get; } = $"agrobot/v1/rover/<id>/cmd";
|
||||
public static string TopicoMqttTelemetria { get; } = $"agrobot/v1/rover/<id>/telemetry";
|
||||
public static string TopicoMqttParametros { get; } = $"agrobot/v1/rover/<id>/parameters";
|
||||
public static double LarguraEsquerda { get; } = 44.0; // 62
|
||||
public static double LarguraDireita { get; } = 44.0; // 22
|
||||
public static double ComprimentoFrente { get; } = 7.0; // 7
|
||||
public static double ComprimentoTras { get; } = 107.0; // 107
|
||||
public static double LeverArmFrontal { get; } = 1.0;
|
||||
public static double LeverArmLateral { get; } = 0.0;
|
||||
public static double DistanciaEntreEixos { get; } = 92.0;
|
||||
public static double LeverArmFrontal { get; set; } = 100.0; // cm
|
||||
public static double LeverArmLateral { get; set; } = 0.0; // cm
|
||||
public static double LarguraEquipamentoMm
|
||||
{
|
||||
get
|
||||
|
|
@ -219,6 +227,9 @@ namespace AgroBase.Models
|
|||
public static double PercentualTensaoBateriaMin { get; set; } = 25.0;
|
||||
public static double PercentualReservatorioMin { get; set; } = 8.0;
|
||||
public static double PercentualToleranciaPressaoLinha { get; set; } = 0.15;
|
||||
public static int QuantidadeCamerasSolo { get; set; } = 1;
|
||||
public static int QuantidadeBicosPulverizadores { get; set; } = 4;
|
||||
public static double CapacidadeReservatorio { get; set; } = 30;
|
||||
public static double ReducaoDirecional { get; set; } = 20.0;
|
||||
public static int RPM_Min_Roda { get; set; } = 15;
|
||||
public static int RPM_Max_Roda
|
||||
|
|
@ -554,6 +565,8 @@ namespace AgroBase.Models
|
|||
public bool Carregado { get; set; }
|
||||
public string serial_number { get; set; }
|
||||
public string base_ip { get; set; }
|
||||
public int base_porta_caminho { get; set; }
|
||||
public int base_porta_ervas { get; set; }
|
||||
|
||||
public void AtualizarParametros()
|
||||
{
|
||||
|
|
@ -568,6 +581,8 @@ namespace AgroBase.Models
|
|||
|
||||
serial_number = par.serial_number;
|
||||
base_ip = par.base_ip;
|
||||
base_porta_caminho = par.base_porta_caminho;
|
||||
base_porta_ervas = par.base_porta_ervas;
|
||||
|
||||
Carregado = true;
|
||||
}
|
||||
|
|
@ -590,7 +605,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
if (!Variaveis.IsAgroMonitor && Variaveis.OperacaoEmAndamento.DispAtu != null)
|
||||
{
|
||||
return Variaveis.OperacaoEmAndamento.Sensoriamento.Atuador.PercentualErvasTerreno / 100.0;
|
||||
return Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Atuador.PercentualErvasTerreno / 100.0;
|
||||
}
|
||||
return 0.3;
|
||||
}
|
||||
|
|
@ -601,7 +616,7 @@ namespace AgroBase.Models
|
|||
{
|
||||
if (!Variaveis.IsAgroMonitor && Variaveis.OperacaoEmAndamento.DispAtu != null)
|
||||
{
|
||||
return (100.0 - Variaveis.OperacaoEmAndamento.Sensoriamento.Atuador.PercentualErvasTerreno) / 100.0;
|
||||
return (100.0 - Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Atuador.PercentualErvasTerreno) / 100.0;
|
||||
}
|
||||
return 0.7;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ namespace AgroMonitor
|
|||
idxTick++;
|
||||
}
|
||||
|
||||
public static async void EnviarDadosControle(string rover_id, OperacaoControleBaseModel controle)
|
||||
public static async void EnviarDadosControle(string rover_id, OperacaoComandoBaseModel controle)
|
||||
{
|
||||
var topico = Variaveis.MqttServiceLocal.Topicos.FirstOrDefault(x => x.Topico == VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", rover_id));
|
||||
if (topico != null)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ namespace AgroBase.Services
|
|||
|
||||
public void AtualizarConsumo()
|
||||
{
|
||||
var Bateria = Variaveis.OperacaoEmAndamento.Sensoriamento.Bateria;
|
||||
var Bateria = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.Bateria;
|
||||
|
||||
if (!Bateria.Iniciado)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -943,9 +943,13 @@ namespace AgroBase.Services
|
|||
{
|
||||
PenultimaLeitura.Ntrip_ativado = UltimaLeitura.Ntrip_ativado;
|
||||
PenultimaLeitura.Heartbeat = UltimaLeitura.Heartbeat;
|
||||
PenultimaLeitura.LeverArmFrontal = UltimaLeitura.LeverArmFrontal;
|
||||
PenultimaLeitura.LeverArmLateral = UltimaLeitura.LeverArmLateral;
|
||||
|
||||
UltimaLeitura.Ntrip_ativado = CorrecaoRTK_Ntrip;
|
||||
UltimaLeitura.Heartbeat = (UltimaLeitura.Heartbeat + 1) % 10;
|
||||
UltimaLeitura.LeverArmFrontal = VariaveisEquipamento.LeverArmFrontal;
|
||||
UltimaLeitura.LeverArmLateral = VariaveisEquipamento.LeverArmLateral;
|
||||
|
||||
if (Variaveis.IsAgroMonitor)
|
||||
{
|
||||
|
|
@ -1142,7 +1146,7 @@ namespace AgroBase.Services
|
|||
{
|
||||
double anguloFinal = 0.0;
|
||||
|
||||
bool imuIniciado = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU?.Iniciado ?? false;
|
||||
bool imuIniciado = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.IMU?.Iniciado ?? false;
|
||||
bool gpsIniciado = Iniciado;
|
||||
|
||||
if (imuIniciado)
|
||||
|
|
@ -1162,7 +1166,7 @@ namespace AgroBase.Services
|
|||
double heading = UltimaLeitura.OrientacaoReal;
|
||||
double angMov = UltimaLeitura.OrientacaoMovimento;
|
||||
double distJan = UltimaLeitura.Distancia;
|
||||
double velPercent = Variaveis.OperacaoEmAndamento.Simulando ? Variaveis.OperacaoEmAndamento.Controle.RPM_SP : Variaveis.OperacaoEmAndamento.Sensoriamento.Movimentacao?.RPMMedio ?? 0;
|
||||
double velPercent = Variaveis.OperacaoEmAndamento.Simulando ? Variaveis.OperacaoEmAndamento.Controle.RPM_SP : Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura?.Movimentacao?.RPMMedio ?? 0;
|
||||
bool rtkFix = UltimaLeitura.QualidadeFix == TiposCorrecaoGPS.RTKFixo;
|
||||
double angAnterior = UltimaLeitura.AnguloCarroDefinido;
|
||||
|
||||
|
|
@ -1173,7 +1177,7 @@ namespace AgroBase.Services
|
|||
else if (imuIniciado)
|
||||
{
|
||||
// Apenas o WT901C está disponível
|
||||
anguloFinal = Variaveis.OperacaoEmAndamento.Sensoriamento.IMU.RotacaoCorrigida;
|
||||
anguloFinal = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.IMU.RotacaoCorrigida;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1330,10 +1334,10 @@ namespace AgroBase.Services
|
|||
|
||||
public class GeoLeverArm
|
||||
{
|
||||
public GeoLeverArm(double _xb = 0, double _yb = 0, bool _invH = false, bool _mirrL = false)
|
||||
public GeoLeverArm(double _xbCm = 0, double _ybCm = 0, bool _invH = false, bool _mirrL = false)
|
||||
{
|
||||
xB = _xb;
|
||||
yB = _yb;
|
||||
xB = _xbCm / 100.0;
|
||||
yB = _ybCm / 100.0;
|
||||
invertHeading = _invH;
|
||||
mirrorLateral = _mirrL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -624,7 +624,7 @@ namespace AgroBase.Services
|
|||
|
||||
public static Bitmap ExibirObstaculos(Bitmap bitmap, List<Subdivisao> subdivisoes, List<Obstaculo> obstaculos, bool ExibirTexto = false)
|
||||
{
|
||||
if (bitmap == null || (!Variaveis.OperacaoEmAndamento.Controle.SonarAtivado && Variaveis.OperacaoEmAndamento.Iniciado))
|
||||
if (bitmap == null || (!Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado && Variaveis.OperacaoEmAndamento.Iniciado))
|
||||
{
|
||||
return bitmap;
|
||||
}
|
||||
|
|
@ -968,7 +968,7 @@ namespace AgroBase.Services
|
|||
|
||||
private static List<Obstaculo> IdentificarObstaculos()
|
||||
{
|
||||
if (!Variaveis.OperacaoEmAndamento.Controle.SonarAtivado || Parametros.Subdivisoes == null)
|
||||
if (!Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado || Parametros.Subdivisoes == null)
|
||||
{
|
||||
return new List<Obstaculo>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -682,7 +682,7 @@ namespace AgroBase.Services
|
|||
}
|
||||
}
|
||||
|
||||
public static void EnviarDadosComandoControle(OperacaoControleBaseModel Controle, byte EnderecoDestinatario)
|
||||
public static void EnviarDadosComandoControle(OperacaoComandoBaseModel Controle, byte EnderecoDestinatario)
|
||||
{
|
||||
if (Iniciado)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ namespace AgroBase.Services
|
|||
if (ageRxMs > beaconPeriodoMs + 2000) return;
|
||||
|
||||
// --- ENVIO (ideal: agregue em 1-2 frames) ---
|
||||
var s = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var s = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
foreach (var dado in LoRaSerializer.SerializeGPS(s.Gps))
|
||||
Variaveis.LoraService?.EnviarDadosLoRaViaCAN(dado);
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ namespace AgroBase.Services
|
|||
return (Endereco, model);
|
||||
}
|
||||
|
||||
public static byte[] SerializeControleModel(OperacaoControleBaseModel model)
|
||||
public static byte[] SerializeControleModel(OperacaoComandoBaseModel model)
|
||||
{
|
||||
List<byte> bytes = new List<byte>();
|
||||
|
||||
|
|
@ -174,26 +174,26 @@ namespace AgroBase.Services
|
|||
bytes.AddRange(BitConverter.GetBytes((int)model.Dispositivo));
|
||||
|
||||
// Serializar RPM
|
||||
bytes.AddRange(BitConverter.GetBytes(model.PercentualVelocidadeSP));
|
||||
bytes.AddRange(BitConverter.GetBytes(model.Controle.PercentualVelocidadeSP));
|
||||
|
||||
// Serializar AnguloMP
|
||||
bytes.AddRange(BitConverter.GetBytes(model.AnguloMP));
|
||||
bytes.AddRange(BitConverter.GetBytes(model.Controle.AnguloSP));
|
||||
|
||||
// Serializar VelocidadeMP
|
||||
bytes.AddRange(BitConverter.GetBytes(model.VelocidadeMP));
|
||||
bytes.AddRange(BitConverter.GetBytes(model.Controle.VelocidadeMP));
|
||||
|
||||
// Serializar Emergencia
|
||||
bytes.AddRange(BitConverter.GetBytes(model.Emergencia));
|
||||
|
||||
// Serializar TipoMovimento (int)
|
||||
bytes.AddRange(BitConverter.GetBytes((int)model.TipoMovimento));
|
||||
bytes.AddRange(BitConverter.GetBytes((int)model.Controle.TipoMovimentoDirecional));
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
public static OperacaoControleBaseModel DeserializeControleModel(byte[] bytes)
|
||||
public static OperacaoComandoBaseModel DeserializeControleModel(byte[] bytes)
|
||||
{
|
||||
OperacaoControleBaseModel model = new OperacaoControleBaseModel();
|
||||
OperacaoComandoBaseModel model = new OperacaoComandoBaseModel();
|
||||
int index = 0;
|
||||
|
||||
// Desserializar Momento (DateTime)
|
||||
|
|
@ -201,7 +201,7 @@ namespace AgroBase.Services
|
|||
index += sizeof(long);
|
||||
|
||||
// Desserializar Tecla (int)
|
||||
model.Tecla = (Keys)BitConverter.ToInt32(bytes, index);
|
||||
model.Tecla = (BotoesJoystick)BitConverter.ToInt32(bytes, index);
|
||||
index += sizeof(int);
|
||||
|
||||
// Desserializar Dispositivo (int)
|
||||
|
|
@ -209,15 +209,15 @@ namespace AgroBase.Services
|
|||
index += sizeof(int);
|
||||
|
||||
// Desserializar RPM
|
||||
model.PercentualVelocidadeSP = BitConverter.ToDouble(bytes, index);
|
||||
model.Controle.PercentualVelocidadeSP = BitConverter.ToDouble(bytes, index);
|
||||
index += sizeof(double);
|
||||
|
||||
// Desserializar AnguloMP
|
||||
model.AnguloMP = BitConverter.ToDouble(bytes, index);
|
||||
model.Controle.AnguloSP = BitConverter.ToDouble(bytes, index);
|
||||
index += sizeof(double);
|
||||
|
||||
// Desserializar VelocidadeMP
|
||||
model.VelocidadeMP = BitConverter.ToDouble(bytes, index);
|
||||
model.Controle.VelocidadeMP = BitConverter.ToDouble(bytes, index);
|
||||
index += sizeof(double);
|
||||
|
||||
// Desserializar Emergencia
|
||||
|
|
@ -225,7 +225,7 @@ namespace AgroBase.Services
|
|||
index += sizeof(bool);
|
||||
|
||||
// Desserializar TipoMovimento (int)
|
||||
model.TipoMovimento = (TipoMovimentoDirecional)BitConverter.ToInt32(bytes, index);
|
||||
model.Controle.TipoMovimentoDirecional = (TipoMovimentoDirecional)BitConverter.ToInt32(bytes, index);
|
||||
index += sizeof(int);
|
||||
|
||||
return model;
|
||||
|
|
@ -274,14 +274,14 @@ namespace AgroBase.Services
|
|||
};
|
||||
}
|
||||
|
||||
public static byte[] SerializeComandoControle(OperacaoControleBaseModel Controle)
|
||||
public static byte[] SerializeComandoControle(OperacaoComandoBaseModel Controle)
|
||||
{
|
||||
List<byte> dados = new List<byte>();
|
||||
dados.AddRange(CanPrefix(DadosLoRaParse.ComandoControle));
|
||||
dados.Add((byte)Controle.Tecla); // 1 byte
|
||||
dados.Add((byte)Controle.PercentualVelocidadeSP); // 1 byte
|
||||
dados.Add((byte)Controle.TipoMovimento); // 1 byte
|
||||
dados.Add((byte)Controle.AnguloMP); // 1 byte
|
||||
dados.Add((byte)Controle.Controle.PercentualVelocidadeSP); // 1 byte
|
||||
dados.Add((byte)Controle.Controle.TipoMovimentoDirecional); // 1 byte
|
||||
dados.Add((byte)Controle.Controle.AnguloSP); // 1 byte
|
||||
//dados.Add((byte)Controle.VelocidadeMP); // 1 byte
|
||||
dados.Add((byte)Controle.Dispositivo); // 1 byte
|
||||
dados.Add((byte)(Controle.Emergencia ? 1 : 0)); // 1 byte
|
||||
|
|
@ -296,7 +296,8 @@ namespace AgroBase.Services
|
|||
dados.Add((byte)Controle.PercentualVelocidadeSP); // 1 byte
|
||||
dados.Add((byte)Controle.TipoMovimento); // 1 byte
|
||||
dados.Add((byte)Controle.Angulo); // 1 byte
|
||||
dados.Add((byte)Controle.VelocidadeMP); // 1 byte
|
||||
//dados.Add((byte)Controle.VelocidadeMP); // 1 byte
|
||||
dados.Add((byte)0); // 1 byte
|
||||
return dados.ToArray();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace AgroBase.Services.Operadores
|
|||
AtualizarDadosModulos();
|
||||
AtualizarDadosControleOperacao();
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
|
||||
if (_Sensoriamento == null)
|
||||
{
|
||||
|
|
@ -165,6 +165,9 @@ namespace AgroBase.Services.Operadores
|
|||
{
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosEquipamento,
|
||||
("base_ip", VariaveisEquipamento.Parametros.base_ip),
|
||||
("base_porta_caminho", VariaveisEquipamento.Parametros.base_porta_caminho),
|
||||
("base_porta_ervas", VariaveisEquipamento.Parametros.base_porta_ervas),
|
||||
("largura", VariaveisEquipamento.LarguraEquipamentoMm / 1000.0),
|
||||
("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixos / 100.0),
|
||||
("percentual_reservatorio_min", VariaveisEquipamento.PercentualReservatorioMin),
|
||||
|
|
@ -195,6 +198,8 @@ namespace AgroBase.Services.Operadores
|
|||
return;
|
||||
}
|
||||
|
||||
var _Parametros = Variaveis.OperacaoEmAndamento.Parametros;
|
||||
var pControle = _Parametros.Controle;
|
||||
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
||||
|
||||
RedisService.AtualizarCampos(
|
||||
|
|
@ -202,20 +207,20 @@ namespace AgroBase.Services.Operadores
|
|||
("configurado", true),
|
||||
("modo", Variaveis.OperacaoEmAndamento.Modo),
|
||||
("tempo_aguardar_inicio_operacao", Variaveis.OperacaoEmAndamento.TempoIniciarOperacao),
|
||||
("modulos_mandatorios", Variaveis.OperacaoEmAndamento.ModulosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
|
||||
("modulos_opcionais", Variaveis.OperacaoEmAndamento.ModulosMandatorios.Where(x => !x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
|
||||
("parametros_mandatorios", Variaveis.OperacaoEmAndamento.ParametrosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Parametro).ToArray()),
|
||||
("modulos_mandatorios", _Parametros.ModulosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
|
||||
("modulos_opcionais", _Parametros.ModulosMandatorios.Where(x => !x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
|
||||
("parametros_mandatorios", _Parametros.ParametrosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Parametro).ToArray()),
|
||||
("Mov", new
|
||||
{
|
||||
percent_vel_max = _Controle.PercentualVelocidadeMax,
|
||||
percent_vel_min = _Controle.PercentualVelocidadeMin,
|
||||
percent_vel_max = pControle.MovVelocidadeSErvasPercent,
|
||||
percent_vel_min = pControle.MovVelocidadeCErvasPercent,
|
||||
}
|
||||
),
|
||||
("Dir", new
|
||||
{
|
||||
angulo_max = _Controle.Angulo_Max,
|
||||
vel_movimento = _Controle.VelocidadeMP,
|
||||
tipo_controle = (int)_Controle.TipoControleDirecional,
|
||||
angulo_max = pControle.DirAnguloMaximo,
|
||||
vel_movimento = pControle.DirVelocidadeMovimento,
|
||||
tipo_controle = (int)pControle.DirTipoMovimento,
|
||||
mpc = new
|
||||
{
|
||||
pontos = Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?
|
||||
|
|
@ -228,9 +233,9 @@ namespace AgroBase.Services.Operadores
|
|||
})
|
||||
.ToList(),
|
||||
horizonte = 2.5,
|
||||
angulo_max_graus = _Controle.Angulo_Max,
|
||||
velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Controle.PercentualVelocidadeMin),
|
||||
velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Controle.PercentualVelocidadeMax),
|
||||
angulo_max_graus = pControle.DirAnguloMaximo,
|
||||
velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent),
|
||||
velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent),
|
||||
tempo_entre_comandos = (Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == Enums.T_Code.Dir)?.DelayEnvioComando ?? 500) / 1000.0,
|
||||
passos_atraso = 1
|
||||
}
|
||||
|
|
@ -238,11 +243,14 @@ namespace AgroBase.Services.Operadores
|
|||
),
|
||||
("Atu", new
|
||||
{
|
||||
qtd_bicos = Variaveis.OperacaoEmAndamento.DispAtu.Dados.QuantidadeBicos,
|
||||
tempo_atuacao = _Controle.TempoAtuacao,
|
||||
capacidade_reservatorio = Variaveis.OperacaoEmAndamento.CapacidadeReservatorio,
|
||||
pressao_linha = _Controle.PressaoLinha,
|
||||
percent_vertical_deteccao = _Controle.PercentualInicioPulverizacao,
|
||||
qtd_bicos = _Parametros.QtdBicos,
|
||||
tempo_atuacao = pControle.AtuDuracaoAtuacao,
|
||||
capacidade_reservatorio = _Parametros.CapacidadeReservatorio,
|
||||
pressao_linha = pControle.AtuPressaoLinha,
|
||||
percent_vertical_deteccao = pControle.AtuPercentualInicioPulverizacao,
|
||||
height_area_deteccao = pControle.AtuAlturaAreaPulverizacao,
|
||||
pct_erva_bico_on = pControle.AtuPercentualErvasBicoOn,
|
||||
pct_erva_bico_off = pControle.AtuPercentualErvasBicoOff
|
||||
}
|
||||
),
|
||||
("Snr", new
|
||||
|
|
@ -268,12 +276,13 @@ namespace AgroBase.Services.Operadores
|
|||
|
||||
public static void AtualizarDadosControleOperacao()
|
||||
{
|
||||
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosControle,
|
||||
("pulverizador_automatico", Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico),
|
||||
("movimento_automatico", Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico),
|
||||
("frenagem_automatica", Variaveis.OperacaoEmAndamento.Controle.FrenagemAutomatica),
|
||||
("sonar_ativado", Variaveis.OperacaoEmAndamento.Controle.SonarAtivado)
|
||||
("pulverizador_automatico", pControle.PulverizadorAutomatico),
|
||||
("movimento_automatico", pControle.MovimentoAutomatico),
|
||||
("frenagem_automatica", pControle.FrenagemAutomatica),
|
||||
("sonar_ativado", pControle.SonarAtivado)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +290,7 @@ namespace AgroBase.Services.Operadores
|
|||
{
|
||||
if (Variaveis.OperacaoEmAndamento.DispMvd == null) return;
|
||||
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
||||
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
||||
var agora = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
|
||||
//Console.WriteLine(RedisService.Get(RedisService.ModKey(Enums.T_Code.Gps)));
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ namespace AgroBase.Services.Operadores
|
|||
break;
|
||||
|
||||
case ManagerWorkerCommandType.EnviarDadosControle:
|
||||
if (Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico)
|
||||
if (Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico)
|
||||
{
|
||||
AtualizarControle(comando.@params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace AgroBase.Services.Operadores
|
|||
if (!Conectado)
|
||||
{
|
||||
TempoDesconectado++;
|
||||
if (Variaveis.OperacaoEmAndamento.Iniciado && Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico)
|
||||
if (Variaveis.OperacaoEmAndamento.Iniciado && Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico)
|
||||
{
|
||||
RedisService.AtualizarCampos(
|
||||
CtxKey.DadosOperacao,
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ namespace AgroBase.Services.Operadores
|
|||
break;
|
||||
|
||||
case WeedWorkerCommandType.EnviarDadosControle:
|
||||
if (Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico)
|
||||
if (Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico)
|
||||
{
|
||||
AtualizarControle(comando.@params);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -371,7 +371,7 @@ namespace AgroBase.Services
|
|||
});
|
||||
if (PrimeiraExecucao)
|
||||
{
|
||||
OperacaoModel.CarregarParametrosOperacaoPadrao(ModoOperacao.Manual);
|
||||
OperacaoModel.CarregarParametrosOperacaoPadrao(ModoOperacao.MapaGPS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ namespace AgroBase.Services
|
|||
|
||||
public static Bitmap ExibirObstaculos(Bitmap bitmap, SonarCamModel leitura, bool ExibirTexto = false)
|
||||
{
|
||||
if (bitmap == null || (!Variaveis.OperacaoEmAndamento.Controle.SonarAtivado && Variaveis.OperacaoEmAndamento.Iniciado))
|
||||
if (bitmap == null || (!Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado && Variaveis.OperacaoEmAndamento.Iniciado))
|
||||
{
|
||||
return bitmap;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -6,12 +6,23 @@ from health_worker.modulos.imu import IMUCamera
|
|||
from shared.enums import StatusModulo, T_Code
|
||||
from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey
|
||||
|
||||
import subprocess
|
||||
import cv2
|
||||
GST_LAUNCH = r"C:\Program Files\gstreamer\1.0\msvc_x86_64\bin\gst-launch-1.0.exe"
|
||||
|
||||
class CameraOak:
|
||||
def __init__(self, mostrar_log, mx_id, modelo_ia_seg=None, modelo_ia_det=None):
|
||||
self.mostrar_log = mostrar_log
|
||||
self.modelo_ia_seg = modelo_ia_seg
|
||||
self.modelo_ia_det = modelo_ia_det
|
||||
|
||||
self.gst_proc = None
|
||||
self.gst_WIDTH = 640
|
||||
self.gst_HEIGHT = 360
|
||||
self.gst_FPS = 10
|
||||
self.gst_BIT_RATE = 500
|
||||
self._ultimo_envio_gst = 0.0
|
||||
|
||||
self.dispositivo = T_Code.Vzo
|
||||
self.modelo = "Desconhecido"
|
||||
self.ultima_saude = {}
|
||||
|
|
@ -72,6 +83,39 @@ class CameraOak:
|
|||
_camera["tem_depht"] = self.tem_depth
|
||||
_camera["tem_imu"] = self.tem_imu
|
||||
|
||||
# Criar processo para transmissao de video
|
||||
try:
|
||||
_cfg = ContextoGlobalRedis.get_equipamento() or {}
|
||||
_ip = _cfg.get("base_ip")
|
||||
_porta = _cfg.get("base_porta_caminho") if self.dispositivo == T_Code.Snr else _cfg.get("base_porta_ervas")
|
||||
if _ip is not None and _porta is not None:
|
||||
self.mostrar_log(f"Iniciando GStreamer para {_ip}:{_porta}...")
|
||||
gst_cmd = [
|
||||
GST_LAUNCH,
|
||||
"fdsrc", "fd=0",
|
||||
"!", "videoparse",
|
||||
f"width={self.gst_WIDTH}", f"height={self.gst_HEIGHT}",
|
||||
"format=bgr",
|
||||
f"framerate={self.gst_FPS}/1",
|
||||
"!", "videoconvert",
|
||||
"!", "videoscale",
|
||||
"!", f"video/x-raw,width={self.gst_WIDTH},height={self.gst_HEIGHT}",
|
||||
"!", "x264enc", "tune=zerolatency", "speed-preset=ultrafast",
|
||||
f"bitrate={self.gst_BIT_RATE}", "key-int-max=20",
|
||||
"!", "rtph264pay", "config-interval=-1", "pt=96",
|
||||
#"!", "h264parse", "!", "mpegtsmux",
|
||||
"!", "udpsink",
|
||||
f"host={_ip}", f"port={_porta}",
|
||||
"sync=false", "async=false",
|
||||
]
|
||||
self.gst_proc = subprocess.Popen(
|
||||
gst_cmd,
|
||||
stdin=subprocess.PIPE,
|
||||
)
|
||||
except Exception as e:
|
||||
self.gst_proc = None
|
||||
self.mostrar_log(f"Erro ao criar script de transmissao de video: {e}")
|
||||
|
||||
# Fase 2: criar pipeline e instanciar normalmente
|
||||
try:
|
||||
self.pipeline = self._criar_pipeline()
|
||||
|
|
@ -350,6 +394,32 @@ class CameraOak:
|
|||
#self.timestamp_ultimo_frame_rgb = time.time()
|
||||
dur = time.time() - start
|
||||
|
||||
_stream_on = (ContextoGlobalRedis.get_camera(self.mx_id) or {}).get("streaming", False)
|
||||
if self.gst_proc is not None and _stream_on:
|
||||
# --- CONTROLE DE FPS PARA STREAMING ---
|
||||
enviar_para_gst = True
|
||||
if getattr(self, "gst_FPS", None) and self.gst_FPS > 0:
|
||||
intervalo_min = 1.0 / float(self.gst_FPS)
|
||||
agora = time.time()
|
||||
if (agora - self._ultimo_envio_gst) < intervalo_min:
|
||||
enviar_para_gst = False
|
||||
else:
|
||||
self._ultimo_envio_gst = agora
|
||||
if frame is not None and frame.size > 0 and enviar_para_gst:
|
||||
# --- RESIZE SÓ PARA O STREAM ---
|
||||
if frame.shape[1] != self.gst_WIDTH or frame.shape[0] != self.gst_HEIGHT:
|
||||
frame_stream = cv2.resize(
|
||||
frame,
|
||||
(self.gst_WIDTH, self.gst_HEIGHT),
|
||||
interpolation=cv2.INTER_AREA
|
||||
)
|
||||
else:
|
||||
frame_stream = frame
|
||||
try:
|
||||
self.gst_proc.stdin.write(frame_stream.tobytes())
|
||||
except BrokenPipeError:
|
||||
self.mostrar_log("GStreamer fechou o pipe. Encerrando.")
|
||||
|
||||
resultado = {
|
||||
"erro": None,
|
||||
"duracao": dur,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ def load_seg_config(force_reload=False):
|
|||
# "frames_histerese": 2,
|
||||
# "min_area_px": 400,
|
||||
# "max_area_frac": 0.2,
|
||||
# "area_atuacao_bicos": 0.1,
|
||||
# "ia_roi_begin": 0.0,
|
||||
# "ia_roi_size": 1.0,
|
||||
# "ia_resolution": [512,288],
|
||||
|
|
@ -79,7 +78,6 @@ def load_seg_config(force_reload=False):
|
|||
"frames_histerese": 2,
|
||||
"min_area_px": 400,
|
||||
"max_area_frac": 0.2,
|
||||
"area_atuacao_bicos": 0.1,
|
||||
"ia_roi_begin": 0.0,
|
||||
"ia_roi_size": 1.0,
|
||||
"ia_resolution": [512,288],
|
||||
|
|
@ -97,8 +95,6 @@ def load_seg_config(force_reload=False):
|
|||
"det_every_n": 0,
|
||||
|
||||
"usar_radar_global_gate": True,
|
||||
"min_frac_erva_por_bico_on": 0.02,
|
||||
"min_frac_erva_por_bico_off": 0.01,
|
||||
"max_frac_cana_por_bico": 0.009,
|
||||
"ema_frac_bico": 0.35,
|
||||
"on_frames_required": 3,
|
||||
|
|
@ -115,7 +111,10 @@ def load_seg_config(force_reload=False):
|
|||
|
||||
_CONFIG_CACHE["ia_model_path"] = ContextoGlobalRedis.get_equipamento().get("path_ia_model_ervas", "C:/AgroBaseModels/Ervas/model-2_1.blob")
|
||||
_CONFIG_CACHE["ia_labelmap_path"] = ContextoGlobalRedis.get_equipamento().get("path_ia_labelmap_ervas", "C:/AgroBaseModels/Ervas/model-2_1.txt")
|
||||
_CONFIG_CACHE["faixa_atuacao_bicos"] = dadosAtu.get("percent_vertical_deteccao", 0.3)
|
||||
_CONFIG_CACHE["faixa_atuacao_bicos"] = dadosAtu.get("percent_vertical_deteccao", 0.7)
|
||||
_CONFIG_CACHE["area_atuacao_bicos"] = dadosAtu.get("height_area_deteccao", 0.1)
|
||||
_CONFIG_CACHE["min_frac_erva_por_bico_on"] = dadosAtu.get("pct_erva_bico_on", 0.02)
|
||||
_CONFIG_CACHE["min_frac_erva_por_bico_off"] = dadosAtu.get("pct_erva_bico_off", 0.01)
|
||||
return _CONFIG_CACHE
|
||||
|
||||
def reload_seg_config():
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ namespace AgroMonitor.Forms
|
|||
Keys[] TeclasDir = { Keys.A, Keys.D };
|
||||
Keys[] TeclasMov = { Keys.W, Keys.S, Keys.Space };
|
||||
|
||||
OperacaoControleBaseModel Controle = new OperacaoControleBaseModel()
|
||||
OperacaoComandoBaseModel Controle = new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Tecla = DeParaTeclas[Tecla],
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using OperationControl.Models;
|
||||
using System.Windows;
|
||||
using Application = System.Windows.Application;
|
||||
|
||||
namespace OperationControl
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
</LinearGradientBrush>
|
||||
|
||||
<conv:MultiplyConverter x:Key="MultiplyConverter"/>
|
||||
<conv:LateralErrorToOffsetConverter x:Key="LateralErrorToOffsetConverter"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<!-- MOLDURA -->
|
||||
|
|
@ -30,6 +31,13 @@
|
|||
BorderBrush="#2ECC71">
|
||||
<Grid>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<!-- parte de cima: horizonte / attitude -->
|
||||
<RowDefinition/>
|
||||
<!-- parte de baixo: barra de erro lateral -->
|
||||
<RowDefinition Height="24"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- VIEWPORT: corta o conteúdo dentro do quadro -->
|
||||
<Grid x:Name="Viewport" ClipToBounds="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
|
||||
|
|
@ -101,6 +109,37 @@
|
|||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- BARRA DE ERRO LATERAL (linha 1) -->
|
||||
<Grid Grid.Row="1" Margin="2,6,2,0">
|
||||
<Border x:Name="LateralTrack" CornerRadius="4" Background="#222" BorderBrush="#555" BorderThickness="1">
|
||||
<Grid>
|
||||
<!-- linha de referência (meio da rua) -->
|
||||
<Rectangle Width="2" Fill="#666" HorizontalAlignment="Center" RadiusX="1" RadiusY="1"/>
|
||||
|
||||
<!-- barrinha que se move com o erro -->
|
||||
<Rectangle Width="32" Height="6" RadiusX="3" RadiusY="3" Fill="#F1C40F" Stroke="#222" StrokeThickness="0.5">
|
||||
<Rectangle.RenderTransform>
|
||||
<TranslateTransform>
|
||||
<TranslateTransform.X>
|
||||
<MultiBinding Converter="{StaticResource LateralErrorToOffsetConverter}">
|
||||
<!-- Largura do trilho -->
|
||||
<Binding ElementName="LateralTrack" Path="ActualWidth"/>
|
||||
|
||||
<!-- Erro normalizado (-1 a +1) -->
|
||||
<Binding Path="LateralNormalized" RelativeSource="{RelativeSource AncestorType=UserControl}"/>
|
||||
</MultiBinding>
|
||||
</TranslateTransform.X>
|
||||
</TranslateTransform>
|
||||
</Rectangle.RenderTransform>
|
||||
</Rectangle>
|
||||
|
||||
<!-- valor numérico opcional (no canto direito) -->
|
||||
<TextBlock Text="{Binding LateralError, RelativeSource={RelativeSource AncestorType=UserControl}, StringFormat={}{0:0.00} cm}" Foreground="#AAA" FontSize="10" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,4,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
@ -81,6 +84,54 @@ namespace OperationControl.Controls
|
|||
set => SetValue(CriticalLimitProperty, value);
|
||||
}
|
||||
|
||||
|
||||
// === LATERAL ERROR ===
|
||||
public static readonly DependencyProperty LateralErrorProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(LateralError),
|
||||
typeof(double),
|
||||
typeof(AttitudeIndicator),
|
||||
new PropertyMetadata(0.0, OnLateralChanged));
|
||||
|
||||
public static readonly DependencyProperty LateralMaxAbsProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(LateralMaxAbs),
|
||||
typeof(double),
|
||||
typeof(AttitudeIndicator),
|
||||
new PropertyMetadata(50.0, OnLateralChanged)); // 0,5 m por padrão
|
||||
|
||||
private static readonly DependencyPropertyKey LateralNormalizedPropertyKey =
|
||||
DependencyProperty.RegisterReadOnly(
|
||||
nameof(LateralNormalized),
|
||||
typeof(double),
|
||||
typeof(AttitudeIndicator),
|
||||
new PropertyMetadata(0.0));
|
||||
|
||||
public static readonly DependencyProperty LateralNormalizedProperty =
|
||||
LateralNormalizedPropertyKey.DependencyProperty;
|
||||
|
||||
public double LateralError
|
||||
{
|
||||
get => (double)GetValue(LateralErrorProperty);
|
||||
set => SetValue(LateralErrorProperty, value);
|
||||
}
|
||||
|
||||
public double LateralMaxAbs
|
||||
{
|
||||
get => (double)GetValue(LateralMaxAbsProperty);
|
||||
set => SetValue(LateralMaxAbsProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erro lateral normalizado em [-1, 1]
|
||||
/// -1 = limite à esquerda, 0 = centro, +1 = limite à direita
|
||||
/// </summary>
|
||||
public double LateralNormalized
|
||||
{
|
||||
get => (double)GetValue(LateralNormalizedProperty);
|
||||
private set => SetValue(LateralNormalizedPropertyKey, value);
|
||||
}
|
||||
|
||||
// Derivados
|
||||
public double MaxAbsAngle => Math.Max(Math.Abs(RollDeg), Math.Abs(PitchDeg));
|
||||
|
||||
|
|
@ -108,5 +159,29 @@ namespace OperationControl.Controls
|
|||
else
|
||||
Chrome.BorderBrush = new SolidColorBrush(Color.FromRgb(0x2E, 0xCC, 0x71)); // verde
|
||||
}
|
||||
|
||||
static void OnLateralChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var c = (AttitudeIndicator)d;
|
||||
c.UpdateLateral();
|
||||
c.Raise(nameof(LateralNormalized));
|
||||
}
|
||||
|
||||
void UpdateLateral()
|
||||
{
|
||||
var max = Math.Max(0.0001, LateralMaxAbs);
|
||||
|
||||
// normaliza para [-1, 1] e faz clamp
|
||||
var n = LateralError / max;
|
||||
if (n > 1) n = 1;
|
||||
if (n < -1) n = -1;
|
||||
|
||||
LateralNormalized = n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using OpenTK.Wpf;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
@ -244,7 +244,7 @@ namespace OperationControl.Controls
|
|||
if (e.ChangedButton == MouseButton.Middle) dragMid = false;
|
||||
if (!dragLeft && !dragMid) Mouse.Capture(null);
|
||||
}
|
||||
void OnMouseMove(object s, MouseEventArgs e)
|
||||
void OnMouseMove(object s, System.Windows.Input.MouseEventArgs e)
|
||||
{
|
||||
var p = e.GetPosition(GLHost);
|
||||
if (dragLeft)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
<UserControl x:Class="OperationControl.Controls.GstVideoView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:OperationControl.Controls"
|
||||
mc:Ignorable="d"
|
||||
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
|
||||
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
|
||||
xmlns:ffme="clr-namespace:Unosquare.FFME;assembly=ffme.win"
|
||||
Height="247" Width="420">
|
||||
<Grid Background="Black">
|
||||
<ffme:MediaElement x:Name="Media" Background="Gray" LoadedBehavior="Play" UnloadedBehavior="Manual" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
using System.Windows;
|
||||
using Gst;
|
||||
using GstVideo;
|
||||
using Unosquare.FFME;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for GstVideoView.xaml
|
||||
/// </summary>
|
||||
public partial class GstVideoView : UserControl
|
||||
{
|
||||
private Pipeline? _pipeline;
|
||||
private Element? _videoSink;
|
||||
private Bus? _bus;
|
||||
|
||||
#region DP: Host e Port
|
||||
|
||||
public string Host
|
||||
{
|
||||
get => (string)GetValue(HostProperty);
|
||||
set => SetValue(HostProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HostProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Host),
|
||||
typeof(string),
|
||||
typeof(GstVideoView),
|
||||
new PropertyMetadata("0.0.0.0", OnEndpointChanged));
|
||||
|
||||
public int Port
|
||||
{
|
||||
get => (int)GetValue(PortProperty);
|
||||
set => SetValue(PortProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PortProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Port),
|
||||
typeof(int),
|
||||
typeof(GstVideoView),
|
||||
new PropertyMetadata(5000, OnEndpointChanged));
|
||||
|
||||
private static void OnEndpointChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var view = (GstVideoView)d;
|
||||
// Se já estiver carregado, reinicia o pipeline com IP/porta novos
|
||||
if (view.IsLoaded)
|
||||
{
|
||||
//view.RestartPipeline();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public string SourceUrl { get; set; } = "udp://0.0.0.0:5000";
|
||||
|
||||
public GstVideoView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
InitGStreamer();
|
||||
|
||||
Loaded += (_, _) =>
|
||||
{
|
||||
//if (VideoPanel.IsHandleCreated == false)
|
||||
// VideoPanel.CreateControl();
|
||||
};
|
||||
Unloaded += (_, _) => Stop();
|
||||
}
|
||||
|
||||
private void InitGStreamer()
|
||||
{
|
||||
//Gst.Application.Init();
|
||||
}
|
||||
|
||||
public void StartPipeline()
|
||||
{
|
||||
if (_pipeline != null)
|
||||
return;
|
||||
|
||||
// pipeline simples só pra testar: videotestsrc → videoconvert → autovideosink
|
||||
_pipeline = new Pipeline();
|
||||
|
||||
var src = ElementFactory.Make("videotestsrc", "src");
|
||||
var conv = ElementFactory.Make("videoconvert", "conv");
|
||||
var sink = ElementFactory.Make("autovideosink", "sink");
|
||||
|
||||
if (src is null || conv is null || sink is null)
|
||||
throw new Exception("Falha ao criar algum elemento do pipeline.");
|
||||
|
||||
_pipeline.Add(src);
|
||||
_pipeline.Add(conv);
|
||||
_pipeline.Add(sink);
|
||||
|
||||
if (!src.Link(conv) || !conv.Link(sink))
|
||||
throw new Exception("Falha ao linkar o pipeline.");
|
||||
|
||||
// >>> AQUI entra a correção do Bus (ver seção 2) <<<
|
||||
|
||||
_pipeline.SetState(State.Playing);
|
||||
}
|
||||
|
||||
public void Start2()
|
||||
{
|
||||
if (_pipeline != null)
|
||||
return;
|
||||
|
||||
//if (!VideoPanel.IsHandleCreated)
|
||||
// VideoPanel.CreateControl();
|
||||
|
||||
// Monta o pipeline de recepção (ajuste caps se precisar)
|
||||
string pipeDesc =
|
||||
$"udpsrc port={Port} " +
|
||||
"caps = application/x-rtp, media=video, encoding-name=H264, payload=96 " +
|
||||
"! rtph264depay ! h264parse ! avdec_h264 ! videoconvert " +
|
||||
"! d3d11videosink name=vsink sync=false";
|
||||
|
||||
// Cria pipeline a partir da string
|
||||
_pipeline = new Pipeline(new Gst.Internal.PipelineHandle(1, false));
|
||||
|
||||
if (_pipeline is null)
|
||||
throw new InvalidOperationException("Falha ao criar pipeline GStreamer.");
|
||||
|
||||
// Pega o sink pelo nome
|
||||
_videoSink = _pipeline.GetChildByName("vsink") as Element;
|
||||
|
||||
if (_videoSink is null)
|
||||
throw new InvalidOperationException("Não foi possível encontrar o elemento 'vsink' no pipeline.");
|
||||
|
||||
// Faz o cast para VideoOverlay
|
||||
var overlay = _videoSink as VideoOverlay;
|
||||
|
||||
if (overlay is null)
|
||||
throw new InvalidOperationException("O sink não implementa VideoOverlay.");
|
||||
|
||||
// Passa o handle da janela do Panel para o sink
|
||||
//var hwnd = VideoPanel.Handle;
|
||||
//overlay.SetWindowHandle((nuint)hwnd);
|
||||
|
||||
// (Opcional) configurar bus para logar erros
|
||||
_bus = _pipeline.GetBus();
|
||||
_bus.AddSignalWatch();
|
||||
_bus.OnMessage += OnBusMessage;
|
||||
|
||||
// Play!
|
||||
_pipeline.SetState(State.Playing);
|
||||
}
|
||||
|
||||
public void Stop2()
|
||||
{
|
||||
if (_pipeline == null)
|
||||
return;
|
||||
|
||||
_pipeline.SetState(State.Null);
|
||||
|
||||
if (_bus != null)
|
||||
{
|
||||
_bus.OnMessage -= OnBusMessage;
|
||||
_bus.Dispose();
|
||||
_bus = null;
|
||||
}
|
||||
|
||||
_pipeline.Dispose();
|
||||
_pipeline = null;
|
||||
_videoSink = null;
|
||||
}
|
||||
|
||||
private void OnBusMessage(object? sender, Bus.MessageSignalArgs e)
|
||||
{
|
||||
switch (e.Message.Type)
|
||||
{
|
||||
case MessageType.Error:
|
||||
//e.Message.ParseError(out var err, out var debug);
|
||||
//Console.WriteLine($"[GST ERROR] {err}: {debug}");
|
||||
Console.WriteLine($"[GST ERROR] {e.Message}");
|
||||
break;
|
||||
|
||||
case MessageType.Eos:
|
||||
Console.WriteLine("[GST] End of stream");
|
||||
// Se quiser, reinicia ou dá Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Media.IsOpen)
|
||||
return;
|
||||
|
||||
// Abre o stream (udp, rtsp, http…)
|
||||
await Media.Open(new System.Uri(SourceUrl));
|
||||
|
||||
await Media.Play();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[FFME] Erro ao iniciar vídeo: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
public async void Stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Media.IsOpen)
|
||||
{
|
||||
await Media.Stop();
|
||||
await Media.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"[FFME] Erro ao parar vídeo: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Media;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Color = System.Windows.Media.Color;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
@ -101,7 +102,7 @@ namespace OperationControl.Controls
|
|||
if (Chrome == null) return;
|
||||
|
||||
bool no_course = double.IsNaN(CourseHeading);
|
||||
var a = no_course ? 0 : DifHeading;
|
||||
var a = no_course ? 0 : Math.Abs(DifHeading);
|
||||
var cor = new SolidColorBrush(Color.FromRgb(0x2E, 0xCC, 0x71)); // verde
|
||||
if (a >= 10)
|
||||
cor = new SolidColorBrush(Color.FromRgb(0xE7, 0x4C, 0x3C)); // vermelho
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
using Color = System.Windows.Media.Color;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<UserControl x:Class="OperationControl.Controls.ManualControlPad"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:OperationControl.Controls"
|
||||
x:Name="Root" Focusable="True" MinWidth="382">
|
||||
|
||||
<Border CornerRadius="8" Background="#111" BorderBrush="Black" BorderThickness="1" Width="382" MinHeight="66">
|
||||
|
|
@ -49,24 +50,72 @@
|
|||
|
||||
<!-- Botões + Modo Manual à direita -->
|
||||
<Canvas Grid.Column="1" Margin="0,0,-184,0">
|
||||
<!-- Emergência (ícone MDL2) -->
|
||||
<Button Content="" FontFamily="Segoe MDL2 Assets" ToolTip="Parada de Emergência" Background="#E74C3C" Foreground="White" Width="70" Height="20" Click="OnEmergencyClick" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="1"/>
|
||||
<!-- Iniciar | Pausar -->
|
||||
<ToggleButton x:Name="BtnRun" Width="108" Height="20" Checked="OnRunToggle" Unchecked="OnRunToggle" Canvas.Left="75" Canvas.Top="1" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<ToggleButton.Style>
|
||||
<Style TargetType="ToggleButton">
|
||||
<Setter Property="Content" Value="Iniciar"/>
|
||||
<Button x:Name="btnEmergencia" FontFamily="Segoe UI Emoji" Width="70" Height="20" Click="OnEmergencyClick" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="1">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<!-- estado normal (desativado) -->
|
||||
<Setter Property="Content" Value="🚨"/>
|
||||
<Setter Property="Background" Value="#E74C3C"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="ToolTip" Value="Ativar Parada de Emergência"/>
|
||||
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter Property="Content" Value="Pausar"/>
|
||||
</Trigger>
|
||||
<!-- quando a emergência estiver ATIVA -->
|
||||
<DataTrigger Value="True" Binding="{Binding EmergencyActivated, RelativeSource={RelativeSource AncestorType=local:ManualControlPad}}">
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="Foreground" Value="#E74C3C"/>
|
||||
<Setter Property="Content" Value="⛔"/>
|
||||
<Setter Property="ToolTip" Value="Desativar Parada de Emergência"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ToggleButton.Style>
|
||||
</ToggleButton>
|
||||
<!-- Referenciar -->
|
||||
<Button Content="Referenciar" Width="70" Height="20" Click="OnRefClick" Canvas.Top="23" HorizontalAlignment="Left" VerticalAlignment="Top"/>
|
||||
<!-- Modo Manual (abre/fecha painel) -->
|
||||
</Button.Style>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="BtnPausa" Width="70" Height="20" Click="OnPauseClick" Canvas.Top="23" HorizontalAlignment="Left" VerticalAlignment="Center">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<!-- estado normal (desativado) -->
|
||||
<Setter Property="Content" Value="⏸️"/>
|
||||
<Setter Property="Background" Value="Yellow"/>
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="ToolTip" Value="Colocar Operação em Espera"/>
|
||||
|
||||
<Style.Triggers>
|
||||
<!-- quando a emergência estiver ATIVA -->
|
||||
<DataTrigger Value="True" Binding="{Binding PauseActivated, RelativeSource={RelativeSource AncestorType=local:ManualControlPad}}">
|
||||
<Setter Property="Content" Value="▶️"/>
|
||||
<Setter Property="Background" Value="#27AE60"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="ToolTip" Value="Retomar Operação"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="BtnReferenciar" Width="108" Height="20" Click="OnRefClick" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Left="75" Canvas.Top="1">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="IsEnabled" Value="True"/>
|
||||
<Setter Property="Content" Value="⚙️ Recalibrar"/>
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="ToolTip" Value="Realizar processo de calibragem do equipamento"/>
|
||||
|
||||
<Style.Triggers>
|
||||
<DataTrigger Value="True" Binding="{Binding RefActivated, RelativeSource={RelativeSource AncestorType=local:ManualControlPad}}">
|
||||
<Setter Property="IsEnabled" Value="False"/>
|
||||
<Setter Property="Content" Value="🔄 Calibrando"/>
|
||||
<Setter Property="Foreground" Value="Black"/>
|
||||
<Setter Property="ToolTip" Value="Calibragem em andamento"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
|
||||
<ToggleButton x:Name="TgManual" Width="108" Height="20" Checked="OnManualToggle" Unchecked="OnManualToggle" Canvas.Left="75" Canvas.Top="23" HorizontalAlignment="Left" VerticalAlignment="Top">
|
||||
<ToggleButton.Style>
|
||||
<Style TargetType="ToggleButton">
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using OperationControl.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
||||
using Binding = System.Windows.Data.Binding;
|
||||
using Application = System.Windows.Application;
|
||||
using Point = System.Windows.Point;
|
||||
using Size = System.Windows.Size;
|
||||
using Mapsui;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
@ -26,21 +32,38 @@ namespace OperationControl.Controls
|
|||
InitializeComponent();
|
||||
|
||||
MoveModes.Clear();
|
||||
MoveModes.Add("RodasDianteiras");
|
||||
MoveModes.Add("RodasTraseiras");
|
||||
MoveModes.Add("RotacionarNoEixo");
|
||||
MoveModes.Add("MovimentoArco");
|
||||
MoveModes.Add("MovimentoLateral");
|
||||
MoveModes.Add("MovimentoDiagonal");
|
||||
MoveModes.Add("Diagnostico");
|
||||
|
||||
foreach (var t in Enum.GetNames(typeof(AgroBase.Models.Enums.TipoMovimentoDirecional)))
|
||||
{
|
||||
MoveModes.Add(t);
|
||||
}
|
||||
SelectedMoveMode = MoveModes[0];
|
||||
|
||||
Loaded += (_, __) => UpdateThumb();
|
||||
SizeChanged += (_, __) => { if (ManualContainer.Height > 0) AnimateManual(true, instant: true); };
|
||||
|
||||
EmergencyClicked += ManualControlPad_EmergencyClicked;
|
||||
PauseClicked += ManualControlPad_PauseClicked;
|
||||
ReferenceClicked += ManualControlPad_ReferenceClicked;
|
||||
ModeChanged += ManualControlPad_ModeChanged;
|
||||
CommandChanged += ManualControlPad_CommandChanged;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ======= Header displays (bind do app) =======
|
||||
public bool EmergencyActivated { get => (bool)GetValue(EmergencyActivatedProperty); set => SetValue(EmergencyActivatedProperty, value); }
|
||||
public static readonly DependencyProperty EmergencyActivatedProperty = DependencyProperty.Register(nameof(EmergencyActivated), typeof(bool), typeof(ManualControlPad), new PropertyMetadata(false));
|
||||
public bool PauseActivated { get => (bool)GetValue(PauseActivatedProperty); set => SetValue(PauseActivatedProperty, value); }
|
||||
public static readonly DependencyProperty PauseActivatedProperty = DependencyProperty.Register(nameof(PauseActivated), typeof(bool), typeof(ManualControlPad), new PropertyMetadata(false));
|
||||
public bool RefActivated { get => (bool)GetValue(RefActivatedProperty); set => SetValue(RefActivatedProperty, value); }
|
||||
public static readonly DependencyProperty RefActivatedProperty = DependencyProperty.Register(nameof(RefActivated), typeof(bool), typeof(ManualControlPad), new PropertyMetadata(false));
|
||||
|
||||
public double SpeedSpKmh { get => (double)GetValue(SpeedSpKmhProperty); set => SetValue(SpeedSpKmhProperty, value); }
|
||||
public static readonly DependencyProperty SpeedSpKmhProperty = DependencyProperty.Register(nameof(SpeedSpKmh), typeof(double), typeof(ManualControlPad), new PropertyMetadata(0d));
|
||||
public double SpeedCurKmh { get => (double)GetValue(SpeedCurKmhProperty); set => SetValue(SpeedCurKmhProperty, value); }
|
||||
|
|
@ -51,8 +74,8 @@ namespace OperationControl.Controls
|
|||
public double AngleCurDeg { get => (double)GetValue(AngleCurDegProperty); set => SetValue(AngleCurDegProperty, value); }
|
||||
public static readonly DependencyProperty AngleCurDegProperty = DependencyProperty.Register(nameof(AngleCurDeg), typeof(double), typeof(ManualControlPad), new PropertyMetadata(0d));
|
||||
|
||||
public string MoveType { get => (string)GetValue(MoveTypeProperty); set => SetValue(MoveTypeProperty, value); }
|
||||
public static readonly DependencyProperty MoveTypeProperty = DependencyProperty.Register(nameof(MoveType), typeof(string), typeof(ManualControlPad), new PropertyMetadata("—"));
|
||||
public AgroBase.Models.Enums.TipoMovimentoDirecional MoveType { get => (AgroBase.Models.Enums.TipoMovimentoDirecional)GetValue(MoveTypeProperty); set => SetValue(MoveTypeProperty, value); }
|
||||
public static readonly DependencyProperty MoveTypeProperty = DependencyProperty.Register(nameof(MoveType), typeof(AgroBase.Models.Enums.TipoMovimentoDirecional), typeof(ManualControlPad), new PropertyMetadata(AgroBase.Models.Enums.TipoMovimentoDirecional.RodasDianteiras));
|
||||
|
||||
// ======= Ajustes (painel manual) =======
|
||||
public double SpeedPercent { get => (double)GetValue(SpeedPercentProperty); set => SetValue(SpeedPercentProperty, value); }
|
||||
|
|
@ -69,7 +92,7 @@ namespace OperationControl.Controls
|
|||
// ===== Eventos públicos =====
|
||||
public event PropertyChangedEventHandler PropertyChanged; void Raise(string n) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(n));
|
||||
public event EventHandler EmergencyClicked;
|
||||
public event EventHandler RunToggled; // BtnRun.IsChecked
|
||||
public event EventHandler PauseClicked;
|
||||
public event EventHandler ReferenceClicked;
|
||||
public event EventHandler ModeChanged;
|
||||
public event EventHandler CommandChanged;
|
||||
|
|
@ -77,7 +100,7 @@ namespace OperationControl.Controls
|
|||
// Botões
|
||||
void OnEmergencyClick(object s, RoutedEventArgs e) => EmergencyClicked?.Invoke(this, EventArgs.Empty);
|
||||
void OnRefClick(object s, RoutedEventArgs e) => ReferenceClicked?.Invoke(this, EventArgs.Empty);
|
||||
void OnRunToggle(object s, RoutedEventArgs e) => RunToggled?.Invoke(this, EventArgs.Empty);
|
||||
void OnPauseClick(object s, RoutedEventArgs e) => PauseClicked?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// Modo Manual → anima painel
|
||||
void OnManualToggle(object s, RoutedEventArgs e)
|
||||
|
|
@ -201,8 +224,73 @@ namespace OperationControl.Controls
|
|||
ThumbTT.Y = -ThrottleCmd * r; // cima +
|
||||
}
|
||||
|
||||
// Helpers
|
||||
public bool IsRunning => BtnRun.IsChecked == true;
|
||||
|
||||
|
||||
public void AtualizarDadosControle(double? angMax = null, double? angSp = null, double? angCur = null, AgroBase.Models.Enums.TipoMovimentoDirecional? tipoMov = null, double? velPct = null, double? velSp = null, double? velKmh = null, bool? emg = null, bool? pause = null, bool? refing = null)
|
||||
{
|
||||
if (angMax != null) MaxSteerDeg = (double)angMax;
|
||||
if (angSp != null) AngleSpDeg = (double)angSp;
|
||||
if (angCur != null) AngleCurDeg = (double)angCur;
|
||||
if (tipoMov != null) MoveType = (AgroBase.Models.Enums.TipoMovimentoDirecional)tipoMov;
|
||||
if (velPct != null) SpeedPercent = (double)velPct;
|
||||
if (velSp != null) SpeedSpKmh = (double)velSp;
|
||||
if (velKmh != null) SpeedCurKmh = (double)velKmh;
|
||||
if (emg != null) EmergencyActivated = (bool)emg;
|
||||
if (pause != null) PauseActivated = (bool)pause;
|
||||
if (refing != null) RefActivated = (bool)refing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void ManualControlPad_EmergencyClicked(object? sender, EventArgs e)
|
||||
{
|
||||
EmergencyActivated = !EmergencyActivated;
|
||||
VariaveisControleOperacao.EnviarComandoParada(emergencia: EmergencyActivated);
|
||||
}
|
||||
|
||||
private void ManualControlPad_PauseClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (VariaveisControleOperacao.RoverEmFoco.DadosLeitura?.OperacaoIniciada ?? false)
|
||||
{
|
||||
//PauseActivated = !PauseActivated;
|
||||
//VariaveisControleOperacao.EnviarComandoParada(pausa: PauseActivated);
|
||||
|
||||
if (System.Windows.MessageBox.Show("Deseja finalizar a operação em andamento?", "Finalizar Operação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||
{
|
||||
VariaveisControleOperacao.EnviarComandoIniciarOperacao(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(TgManual.IsChecked ?? false) && !(((App)Application.Current).Shell.Main?.MAP?.RuasMapaCarregado?.Any(x => x.Selected) ?? false))
|
||||
{
|
||||
System.Windows.MessageBox.Show("Para iniciar a operação automática, é necessário carregar um mapa e selecionar as ruas onde o equipamento irá operar!", "Parametrização", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (System.Windows.MessageBox.Show("Deseja iniciar a operação com os parâmetros atuais?", "Iniciar Operação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||
{
|
||||
VariaveisControleOperacao.EnviarComandoIniciarOperacao(true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ManualControlPad_ReferenceClicked(object? sender, EventArgs e)
|
||||
{
|
||||
RefActivated = !RefActivated;
|
||||
VariaveisControleOperacao.EnviarComandoReferenciamento();
|
||||
}
|
||||
|
||||
private void ManualControlPad_CommandChanged(object? sender, EventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void ManualControlPad_ModeChanged(object? sender, EventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ===== visuais
|
||||
|
|
@ -213,4 +301,5 @@ namespace OperationControl.Controls
|
|||
public object Convert(object v, Type t, object p, System.Globalization.CultureInfo c) => (v is bool b && b) ? EnabledOpacity : DisabledOpacity;
|
||||
public object ConvertBack(object v, Type t, object p, System.Globalization.CultureInfo c) => Binding.DoNothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using BruTile;
|
||||
using BruTile.MbTiles;
|
||||
using BruTile.Predefined;
|
||||
using SQLite;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using NetTopologySuite.IO;
|
||||
using NetTopologySuite.Features;
|
||||
|
|
@ -21,11 +19,18 @@ using Mapsui.Nts;
|
|||
using Mapsui.UI.Wpf;
|
||||
|
||||
// Aliases para evitar conflito com NetTopologySuite.* (NTS)
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
|
||||
using MIFeature = Mapsui.IFeature;
|
||||
using Brush = Mapsui.Styles.Brush;
|
||||
using Pen = Mapsui.Styles.Pen;
|
||||
using Color = Mapsui.Styles.Color;
|
||||
using Font = Mapsui.Styles.Font;
|
||||
using NFeature = NetTopologySuite.Features.Feature;
|
||||
using Mapsui.Manipulations;
|
||||
using Mapsui.Extensions;
|
||||
using OperationControl.Models;
|
||||
using static AgroBase.Models.Enums;
|
||||
|
||||
|
||||
namespace OperationControl.Controls
|
||||
|
|
@ -67,6 +72,8 @@ namespace OperationControl.Controls
|
|||
public event EventHandler<MapMarkerManager.MarkerClickedEventArgs>? MarkerClicked;
|
||||
protected virtual void OnMarkerClicked(string markerId)
|
||||
{
|
||||
if (markerId == null) markers?.ClearMarkerFocused();
|
||||
else markers?.SetMarkerFocused(markerId, true);
|
||||
MarkerClicked?.Invoke(this, new MapMarkerManager.MarkerClickedEventArgs(markerId));
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +85,7 @@ namespace OperationControl.Controls
|
|||
#region RUAS PLANTACAO
|
||||
|
||||
private Layer MapaPlantacao_Layer;
|
||||
private List<StreetMapDictionaryModel> RuasMapaCarregado;
|
||||
public List<StreetMapDictionaryModel> RuasMapaCarregado;
|
||||
|
||||
public event EventHandler<StreetMapClickedEventArgs>? StreetMapClicked;
|
||||
protected virtual void OnStreetMapClicked(string streetId)
|
||||
|
|
@ -461,24 +468,18 @@ namespace OperationControl.Controls
|
|||
var info = Mapa.GetMapInfo(sp, Mapa.Map.Layers /*, 18*/);
|
||||
var feat = info?.Feature;
|
||||
|
||||
if (info?.Layer == markers.Layer)
|
||||
if (info?.Layer == markers.Layer && feat != null && markers != null && markers.TryGetIdFromFeature(feat, out var id))
|
||||
{
|
||||
if (feat != null && markers != null && markers.TryGetIdFromFeature(feat, out var id))
|
||||
{
|
||||
markers.SetMarkerFocused(id, true);
|
||||
Mapa.Cursor = System.Windows.Input.Cursors.Hand;
|
||||
OnMarkerClicked(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
markers?.ClearMarkerFocused();
|
||||
OnMarkerClicked(null);
|
||||
}
|
||||
OnMarkerClicked(id);
|
||||
}
|
||||
else if (info?.Layer == MapaPlantacao_Layer && feat is MIFeature roadFeature)
|
||||
{
|
||||
HighlightRoad(roadFeature);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnMarkerClicked(null);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -492,7 +493,9 @@ namespace OperationControl.Controls
|
|||
var info = Mapa.GetMapInfo(sp, Mapa.Map.Layers /*, 18*/);
|
||||
var feat = info?.Feature;
|
||||
|
||||
if ((feat != null && markers != null && markers.TryGetIdFromFeature(feat, out _)) || feat != null)
|
||||
if (feat != null && markers != null && markers.TryGetIdFromFeature(feat, out _))
|
||||
Mapa.Cursor = System.Windows.Input.Cursors.Hand;
|
||||
else if (feat != null && info?.Layer == MapaPlantacao_Layer && feat is MIFeature roadFeature)
|
||||
Mapa.Cursor = System.Windows.Input.Cursors.Hand;
|
||||
else
|
||||
Mapa.Cursor = System.Windows.Input.Cursors.Arrow;
|
||||
|
|
@ -777,6 +780,52 @@ namespace OperationControl.Controls
|
|||
return dict.TryGetValue(fieldName, out var v) ? v : null;
|
||||
}
|
||||
|
||||
public AgroBase.Models.MapaFeatureCollectionModel CriarDadosMapa()
|
||||
{
|
||||
AgroBase.Models.MapaFeatureCollectionModel _mapa = new AgroBase.Models.MapaFeatureCollectionModel() { type = "FeatureCollection", features = new List<AgroBase.Models.MapaFeatureModel>() };
|
||||
foreach (var x in RuasMapaCarregado.Where(x => x.Selected))
|
||||
{
|
||||
string id = ((dynamic)x.Feature).Id.ToString();
|
||||
string type = ((dynamic)x.Feature).Geometry.GeometryType;
|
||||
string s = ((dynamic)x.Feature).Geometry.CoordinateSequence.ToString();
|
||||
s = s.Trim().TrimStart('(').TrimEnd(')');
|
||||
var pairs = s.Split("),", StringSplitOptions.RemoveEmptyEntries);
|
||||
var coordinates = new List<List<double>>();
|
||||
foreach (var p in pairs)
|
||||
{
|
||||
var clean = p.Replace("(", "").Replace(")", "").Trim();
|
||||
var parts = clean.Split(',', StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 2 && double.TryParse(parts[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double lon) && double.TryParse(parts[1], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out double lat))
|
||||
{
|
||||
coordinates.Add(new List<double> { lon, lat });
|
||||
}
|
||||
}
|
||||
|
||||
AgroBase.Models.MapaFeatureGeometryModel geometry = new AgroBase.Models.MapaFeatureGeometryModel()
|
||||
{
|
||||
id = GetAttr(x.Feature, "Id"),
|
||||
type = type,
|
||||
coordinates = coordinates
|
||||
};
|
||||
|
||||
_mapa.features.Add(new AgroBase.Models.MapaFeatureModel()
|
||||
{
|
||||
type = "Feature",
|
||||
geometry = geometry,
|
||||
properties = new AgroBase.Models.MapaFeaturePropertiesModel()
|
||||
{
|
||||
Id = GetAttr(x.Feature, "Id"),
|
||||
Dist1 = double.Parse(GetAttr(x.Feature, "Dist1")),
|
||||
Dist2 = double.Parse(GetAttr(x.Feature, "Dist2")),
|
||||
Length = double.Parse(GetAttr(x.Feature, "Length")),
|
||||
Name = GetAttr(x.Feature, "Name")
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return _mapa;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class MapMarkerManager
|
||||
|
|
@ -805,6 +854,14 @@ namespace OperationControl.Controls
|
|||
private readonly Layer _layer;
|
||||
public Layer Layer { get { return _layer; } }
|
||||
|
||||
public enum MarkerStatus
|
||||
{
|
||||
Normal,
|
||||
Warning,
|
||||
Error,
|
||||
Offline
|
||||
}
|
||||
|
||||
|
||||
|
||||
public bool Added(string id)
|
||||
|
|
@ -826,6 +883,7 @@ namespace OperationControl.Controls
|
|||
|
||||
public void SetMarkerFocused(string id, bool focused)
|
||||
{
|
||||
ClearMarkerFocused();
|
||||
var f = _features.FirstOrDefault(x => x.Id == id);
|
||||
if (f != null) f.Focused = focused;
|
||||
}
|
||||
|
|
@ -856,7 +914,7 @@ namespace OperationControl.Controls
|
|||
}
|
||||
}
|
||||
|
||||
public void AddMarker(string id, double lat, double lon, double headingDeg, System.Windows.Media.Color color, string? label = null, bool center = false)
|
||||
public void AddMarker(string id, bool isBase, double? lat = null, double? lon = null, double? heading = null, System.Windows.Media.Color? color = null, string? label = null, StatusOperacao? status = null, bool? pulv = null, bool center = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id)) throw new ArgumentException("id inválido", nameof(id));
|
||||
|
||||
|
|
@ -865,7 +923,7 @@ namespace OperationControl.Controls
|
|||
var marker = _features.FirstOrDefault(x => x.Id == id);
|
||||
if (marker != null)
|
||||
{
|
||||
marker.UpdateData(lat, lon, headingDeg, label, color);
|
||||
marker.UpdateData(lat: lat, lon: lon, heading: heading, label: label, color: color, status: status, pulverizando: pulv);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -873,15 +931,18 @@ namespace OperationControl.Controls
|
|||
{
|
||||
Id = id,
|
||||
Features = new List<MIFeature>(),
|
||||
Color = color,
|
||||
Heading = headingDeg,
|
||||
Lat = lat,
|
||||
Lon = lon,
|
||||
Color = color ?? GetColorForMarker(id, isBase),
|
||||
Heading = heading ?? 0,
|
||||
Lat = lat ?? 0,
|
||||
Lon = lon ?? 0,
|
||||
Label = lbl,
|
||||
Seta = new List<GeometryFeature>(),
|
||||
Status = status ?? StatusOperacao.NaoIniciado,
|
||||
Pulverizando = pulv ?? false,
|
||||
Focused = false
|
||||
};
|
||||
marker.CreateTrajectory(_map);
|
||||
marker.UpdateData(lat, lon, headingDeg);
|
||||
marker.UpdateData();
|
||||
_features.Add(marker);
|
||||
}
|
||||
|
||||
|
|
@ -891,12 +952,26 @@ namespace OperationControl.Controls
|
|||
_map.Map?.Navigator?.CenterOn(marker.Point.Point);
|
||||
}
|
||||
|
||||
public void UpdateMarkerPosition(string id, double lat, double lon, double headingDeg, bool pulv = false)
|
||||
public void UpdateMarkerPosition(string id, double? lat = null, double? lon = null, double? heading = null, List<double[]>? predict = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id)) throw new ArgumentException("id inválido", nameof(id));
|
||||
|
||||
var marker = _features.FirstOrDefault(x => x.Id == id);
|
||||
if (marker == null) return;
|
||||
|
||||
marker.UpdateData(lat, lon, headingDeg, pulverizando: pulv);
|
||||
marker.UpdateData(lat: lat, lon: lon, heading: heading, predict: predict);
|
||||
|
||||
UpdateFeatures();
|
||||
}
|
||||
|
||||
public void UpdateMarkerInfo(string id, StatusOperacao? status = null, bool? pulv = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(id)) throw new ArgumentException("id inválido", nameof(id));
|
||||
|
||||
var marker = _features.FirstOrDefault(x => x.Id == id);
|
||||
if (marker == null) return;
|
||||
|
||||
marker.UpdateData(status: status, pulverizando: pulv);
|
||||
|
||||
UpdateFeatures();
|
||||
}
|
||||
|
|
@ -922,10 +997,19 @@ namespace OperationControl.Controls
|
|||
Style = null
|
||||
};
|
||||
_map.Map!.Layers.Add(_trajLayer);
|
||||
_predProvider = new MemoryProvider(_predFeatures);
|
||||
_predLayer = new Layer
|
||||
{
|
||||
Name = $"pred_{Id}",
|
||||
DataSource = _predProvider,
|
||||
Style = null
|
||||
};
|
||||
_map.Map!.Layers.Add(_predLayer);
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public bool Focused { get; set; }
|
||||
public bool Pulverizando { get; set; }
|
||||
public PointFeature Point { get; set; }
|
||||
public List<MIFeature> Features { get; set; }
|
||||
public double Lat { get; set; }
|
||||
|
|
@ -933,18 +1017,23 @@ namespace OperationControl.Controls
|
|||
public double Heading { get; set; }
|
||||
public string Label { get; set; }
|
||||
public System.Windows.Media.Color Color { get; set; }
|
||||
public StatusOperacao Status { get; set; }
|
||||
public List<GeometryFeature> Seta { get; set; }
|
||||
public Coordinate Position { get; set; }
|
||||
public List<double[]> Predict { get; set; }
|
||||
|
||||
public void UpdateData(double lat, double lon, double heading, string? label = null, System.Windows.Media.Color? color = null, bool pulverizando = false)
|
||||
public void UpdateData(double? lat = null, double? lon = null, double? heading = null, string? label = null, System.Windows.Media.Color? color = null, bool? pulverizando = null, StatusOperacao? status = null, List<double[]>? predict = null)
|
||||
{
|
||||
Features.Clear();
|
||||
|
||||
Lat = lat;
|
||||
Lon = lon;
|
||||
Heading = heading;
|
||||
if (lat != null) Lat = (double)lat;
|
||||
if (lon != null) Lon = (double)lon;
|
||||
if (heading != null) Heading = (double)heading;
|
||||
if (label != null) Label = label;
|
||||
if (color != null) Color = (System.Windows.Media.Color)color;
|
||||
if (status != null) Status = (StatusOperacao)status;
|
||||
if (pulverizando != null) Pulverizando = (bool)pulverizando;
|
||||
if (predict != null) Predict = predict;
|
||||
|
||||
var (x, y) = Mapsui.Projections.SphericalMercator.FromLonLat(Lon, Lat);
|
||||
var newPoint = new MPoint(x, y);
|
||||
|
|
@ -957,7 +1046,10 @@ namespace OperationControl.Controls
|
|||
Features.Add(Point);
|
||||
Seta.ForEach(f => Features.Add(f));
|
||||
|
||||
UpdateRoverPosition(pulverizando);
|
||||
if (lat != null || lon != null)
|
||||
UpdateRoverPosition();
|
||||
if (predict != null)
|
||||
UpdatePredictTrajectory();
|
||||
}
|
||||
|
||||
private void UpsertHeadingFeature(MPoint centerWorld, bool withArrowHead = true)
|
||||
|
|
@ -1024,55 +1116,129 @@ namespace OperationControl.Controls
|
|||
});
|
||||
}
|
||||
|
||||
private void SetStyles()
|
||||
private void SetStyles(double _pulseFactor = 1.0)
|
||||
{
|
||||
if (Point.Styles == null) Point.Styles = new List<IStyle>();
|
||||
else Point.Styles.Clear();
|
||||
|
||||
// cor base
|
||||
var c = new Mapsui.Styles.Color(Color.R, Color.G, Color.B, Color.A);
|
||||
// Pega o “visual” conforme o Status
|
||||
var (baseColor, statusGlyph, labelBackColor) = GetStatusVisual();
|
||||
|
||||
// 1) Ponto central minúsculo (precisão)
|
||||
Point.Styles.Add(new SymbolStyle
|
||||
{
|
||||
SymbolScale = 0.22, // ponto bem pequeno
|
||||
Fill = new Brush(c),
|
||||
SymbolScale = 0.22,
|
||||
Fill = new Brush(baseColor),
|
||||
Outline = null
|
||||
});
|
||||
|
||||
// 2) “Aura” simulando gradiente (3 círculos com alpha/escala crescentes)
|
||||
Point.Styles.Add(new SymbolStyle
|
||||
{
|
||||
SymbolScale = 0.55,
|
||||
Fill = new Brush(new Mapsui.Styles.Color(c.R, c.G, c.B, 120)),
|
||||
SymbolScale = _pulseFactor * 0.55,
|
||||
Fill = new Brush(new Color(baseColor.R, baseColor.G, baseColor.B, 120)),
|
||||
Outline = null
|
||||
});
|
||||
Point.Styles.Add(new SymbolStyle
|
||||
{
|
||||
SymbolScale = 0.95,
|
||||
Fill = new Brush(new Mapsui.Styles.Color(c.R, c.G, c.B, 70)),
|
||||
SymbolScale = _pulseFactor * 0.95,
|
||||
Fill = new Brush(new Color(baseColor.R, baseColor.G, baseColor.B, 70)),
|
||||
Outline = null
|
||||
});
|
||||
Point.Styles.Add(new SymbolStyle
|
||||
{
|
||||
SymbolScale = 1.4,
|
||||
Fill = new Brush(new Mapsui.Styles.Color(c.R, c.G, c.B, 30)),
|
||||
SymbolScale = _pulseFactor * 1.4,
|
||||
Fill = new Brush(new Color(baseColor.R, baseColor.G, baseColor.B, 30)),
|
||||
Outline = null
|
||||
});
|
||||
|
||||
// 3) Rótulo do id (pequeno, acima do ponto)
|
||||
if (!string.IsNullOrWhiteSpace(Label))
|
||||
{
|
||||
// texto: se tiver glyph, coloca na frente
|
||||
var texto = string.IsNullOrEmpty(statusGlyph)
|
||||
? Label
|
||||
: $"{Label} {statusGlyph}";
|
||||
|
||||
var backColor = labelBackColor ?? new Color(0, 0, 0, 140);
|
||||
|
||||
Point.Styles.Add(new LabelStyle
|
||||
{
|
||||
Text = Label,
|
||||
Text = texto,
|
||||
ForeColor = Mapsui.Styles.Color.White,
|
||||
BackColor = new Brush(new Mapsui.Styles.Color(0, 0, 0, 140)),
|
||||
Offset = new Offset(0, -30)
|
||||
BackColor = new Brush(backColor),
|
||||
Offset = new Offset(0, -30),
|
||||
Font = new Font { FontFamily = "Segoe UI Emoji", Size = 18 }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private (Mapsui.Styles.Color baseColor, string statusGlyph, Mapsui.Styles.Color? labelBackColor) GetStatusVisual()
|
||||
{
|
||||
string glyph = "";
|
||||
Mapsui.Styles.Color? back = null;
|
||||
|
||||
// Base default = cor do robô (personalizada)
|
||||
var baseColor = new Mapsui.Styles.Color(Color.R, Color.G, Color.B, Color.A);
|
||||
|
||||
switch (Status)
|
||||
{
|
||||
case StatusOperacao.NaoIniciado:
|
||||
glyph = "⏳";
|
||||
baseColor = new Mapsui.Styles.Color(150, 150, 150, 255); // cinza médio
|
||||
back = new Mapsui.Styles.Color(60, 60, 60, 160); // cinza escuro translúcido
|
||||
break;
|
||||
|
||||
case StatusOperacao.Parametrizando:
|
||||
glyph = "🔧";
|
||||
baseColor = new Mapsui.Styles.Color(40, 120, 255, 255); // azul forte
|
||||
back = new Mapsui.Styles.Color(100, 160, 255, 140); // azul claro translúcido
|
||||
break;
|
||||
|
||||
case StatusOperacao.Calibrando:
|
||||
glyph = "🎯";
|
||||
baseColor = new Mapsui.Styles.Color(160, 70, 255, 255); // roxo vibrante
|
||||
back = new Mapsui.Styles.Color(180, 120, 255, 140); // roxo suave
|
||||
break;
|
||||
|
||||
case StatusOperacao.Aguardando:
|
||||
glyph = "💤";
|
||||
baseColor = new Mapsui.Styles.Color(0, 110, 140, 255); // azul petróleo
|
||||
back = new Mapsui.Styles.Color(0, 150, 180, 140); // turquesa suave
|
||||
break;
|
||||
|
||||
case StatusOperacao.EmAndamento:
|
||||
glyph = "▶";
|
||||
baseColor = new Mapsui.Styles.Color(0, 220, 40, 255); // verde limão
|
||||
back = new Mapsui.Styles.Color(0, 200, 30, 140); // verde limão translúcido
|
||||
break;
|
||||
|
||||
case StatusOperacao.Parado:
|
||||
glyph = "⏸";
|
||||
baseColor = new Mapsui.Styles.Color(255, 180, 0, 255); // amarelo dourado
|
||||
back = new Mapsui.Styles.Color(255, 210, 80, 140); // amarelo claro suaaave
|
||||
break;
|
||||
|
||||
case StatusOperacao.Concluido:
|
||||
glyph = "✔";
|
||||
baseColor = new Mapsui.Styles.Color(0, 150, 60, 255); // verde escuro
|
||||
back = new Mapsui.Styles.Color(0, 130, 50, 140); // verde escuro suave
|
||||
break;
|
||||
|
||||
case StatusOperacao.Erro:
|
||||
glyph = "⛔";
|
||||
baseColor = new Mapsui.Styles.Color(220, 40, 40, 255);
|
||||
back = new Mapsui.Styles.Color(120, 0, 0, 190);
|
||||
break;
|
||||
|
||||
default:
|
||||
glyph = "";
|
||||
break;
|
||||
}
|
||||
|
||||
return (baseColor, glyph, back);
|
||||
}
|
||||
|
||||
|
||||
#region TRAJETORIA
|
||||
|
||||
|
|
@ -1080,9 +1246,9 @@ namespace OperationControl.Controls
|
|||
private Layer _trajLayer;
|
||||
private List<MIFeature> _trajFeatures { get; set; } = new List<MIFeature>();
|
||||
|
||||
private VectorStyle CreateTrajectoryStyle(string roverId, bool pulverizando)
|
||||
private VectorStyle CreateTrajectoryStyle()
|
||||
{
|
||||
if (pulverizando)
|
||||
if (Pulverizando)
|
||||
{
|
||||
return new VectorStyle
|
||||
{
|
||||
|
|
@ -1098,7 +1264,7 @@ namespace OperationControl.Controls
|
|||
}
|
||||
}
|
||||
|
||||
public void UpdateRoverPosition(bool pulverizando)
|
||||
public void UpdateRoverPosition()
|
||||
{
|
||||
var (x, y) = Mapsui.Projections.SphericalMercator.FromLonLat(Lon, Lat);
|
||||
var newCoord = new Coordinate(x, y);
|
||||
|
|
@ -1109,8 +1275,8 @@ namespace OperationControl.Controls
|
|||
Geometry = line
|
||||
};
|
||||
gf["RoverId"] = Id;
|
||||
gf["Pulverizando"] = pulverizando ? "1" : "0";
|
||||
gf.Styles.Add(CreateTrajectoryStyle(Id, pulverizando));
|
||||
gf["Pulverizando"] = Pulverizando ? "1" : "0";
|
||||
gf.Styles.Add(CreateTrajectoryStyle());
|
||||
_trajFeatures.Add(gf);
|
||||
_trajLayer.DataSource = new MemoryProvider(_trajFeatures);
|
||||
_trajLayer.DataHasChanged();
|
||||
|
|
@ -1118,6 +1284,67 @@ namespace OperationControl.Controls
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SIMULACAO
|
||||
|
||||
private MemoryProvider _predProvider;
|
||||
private Layer _predLayer;
|
||||
private List<MIFeature> _predFeatures { get; set; } = new List<MIFeature>();
|
||||
|
||||
public void UpdatePredictTrajectory()
|
||||
{
|
||||
if (_predLayer == null || Predict == null || Predict.Count < 2)
|
||||
return;
|
||||
|
||||
_predFeatures.Clear();
|
||||
|
||||
// Converte lista (lon, lat) -> coordenadas em SphericalMercator
|
||||
var coords = new List<Coordinate>();
|
||||
foreach (var lon_lat in Predict)
|
||||
{
|
||||
double lon = lon_lat[0];
|
||||
double lat = lon_lat[1];
|
||||
var (x, y) = Mapsui.Projections.SphericalMercator.FromLonLat(lon, lat);
|
||||
coords.Add(new Coordinate(x, y));
|
||||
}
|
||||
|
||||
// Garante que tem pelo menos 2 pontos
|
||||
if (coords.Count < 2)
|
||||
return;
|
||||
|
||||
var line = new LineString(coords.ToArray());
|
||||
|
||||
var gf = new GeometryFeature
|
||||
{
|
||||
Geometry = line
|
||||
};
|
||||
|
||||
gf["RoverId"] = Id;
|
||||
gf["Tipo"] = "Predict";
|
||||
|
||||
gf.Styles.Add(CreatePredictStyle());
|
||||
|
||||
_predFeatures.Add(gf);
|
||||
|
||||
_predLayer.DataSource = new MemoryProvider(_predFeatures);
|
||||
_predLayer.DataHasChanged();
|
||||
}
|
||||
|
||||
private IStyle CreatePredictStyle()
|
||||
{
|
||||
return new VectorStyle
|
||||
{
|
||||
Line = new Pen
|
||||
{
|
||||
Color = Mapsui.Styles.Color.Lime, // verde-limão
|
||||
Width = 2,
|
||||
PenStyle = PenStyle.Dash // linha tracejada
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
public class MarkerClickedEventArgs : EventArgs
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
using Color = System.Windows.Media.Color;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Color = System.Windows.Media.Color;
|
||||
|
||||
namespace OperationControl.Controls
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using ColorConverter = System.Windows.Media.ColorConverter;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Binding = System.Windows.Data.Binding;
|
||||
|
||||
namespace OperationControl.Converters
|
||||
{
|
||||
|
|
@ -96,4 +101,27 @@ namespace OperationControl.Converters
|
|||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
=> Binding.DoNothing;
|
||||
}
|
||||
|
||||
public class LateralErrorToOffsetConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType,
|
||||
object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length < 2) return 0;
|
||||
|
||||
double width = System.Convert.ToDouble(values[0], culture);
|
||||
double errorN = System.Convert.ToDouble(values[1], culture);
|
||||
|
||||
// limite visual: 40% da meia largura
|
||||
double maxFactor = 0.4;
|
||||
|
||||
return errorN * (width * 0.5 * maxFactor);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes,
|
||||
object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ namespace OperationControl.Models
|
|||
|
||||
public void Inicializar()
|
||||
{
|
||||
Show();
|
||||
|
||||
APIService.IniciarRotinas();
|
||||
Variaveis.IniciarMQTT();
|
||||
|
||||
tmrComunicacao.Elapsed += (_, __) => tmrComunicacao_Elapsed();
|
||||
tmrComunicacao.Start();
|
||||
|
||||
Show();
|
||||
}
|
||||
|
||||
private void Show()
|
||||
|
|
@ -36,13 +36,20 @@ namespace OperationControl.Models
|
|||
{
|
||||
if (tmrComunicacaoTicking) return;
|
||||
tmrComunicacaoTicking = true;
|
||||
if (tmrComunicacaoTicks % VariaveisEquipamento.TempoEntrePingsConexao == 0 && Variaveis.GpsService != null)
|
||||
try
|
||||
{
|
||||
VariaveisControleOperacao.EnviarDadosPosicao(Variaveis.GpsService.UltimaLeitura);
|
||||
if (tmrComunicacaoTicks % (VariaveisEquipamento.TempoEntrePingsConexao / 1000) == 0 && Variaveis.GpsService != null)
|
||||
{
|
||||
VariaveisControleOperacao.EnviarDadosPosicao(Variaveis.GpsService.UltimaLeitura);
|
||||
}
|
||||
VariaveisControleOperacao.EnviarDadosHeartbeat();
|
||||
VariaveisControleOperacao.AtualizarListaRoversNaRede();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tmrComunicacaoTicks++;
|
||||
tmrComunicacaoTicking = false;
|
||||
}
|
||||
VariaveisControleOperacao.AtualizarListaRoversNaRede();
|
||||
tmrComunicacaoTicks++;
|
||||
tmrComunicacaoTicking = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
using AgroBase.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using OperationControl.Services;
|
||||
using AgroMonitor;
|
||||
using Application = System.Windows.Application;
|
||||
using AgroBase.Models.Operacoes;
|
||||
using Mapsui;
|
||||
|
||||
namespace OperationControl.Models
|
||||
{
|
||||
|
|
@ -29,8 +32,9 @@ namespace OperationControl.Models
|
|||
|
||||
MqttService = new MqttService("localhost", 1883, "base", true, msg => MostrarLog($"[MQTT localhost:1883] - {msg}"));
|
||||
|
||||
await MqttService.AdicionarNovoTopico(VariaveisControleOperacao.TopicoMqttRTCM);
|
||||
await MqttService.AdicionarNovoTopico(VariaveisControleOperacao.TopicoMqttDispositivos, true, 1, async (message) =>
|
||||
await MqttService.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttPosicao);
|
||||
await MqttService.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttRTCM);
|
||||
await MqttService.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttDispositivos, true, 1, async (message) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -50,108 +54,159 @@ namespace OperationControl.Models
|
|||
|
||||
public class VariaveisControleOperacao
|
||||
{
|
||||
public static double LeverArmFrontal { get; } = 0.0;
|
||||
public static double LeverArmLateral { get; } = 0.0;
|
||||
public static double LeverArmFrontal { get; } = 0.0; // cm
|
||||
public static double LeverArmLateral { get; } = 0.0; // cm
|
||||
|
||||
public static readonly string BaseMarkerID = "BASE";
|
||||
public static string TopicoMqttDispositivos { get; } = $"agrobot/v1/base/devices";
|
||||
public static string TopicoMqttPosicao { get; } = $"agrobot/v1/base/position";
|
||||
public static string TopicoMqttRTCM { get; } = $"agrobot/v1/base/rtcm";
|
||||
private static readonly object _RoversLock = new object();
|
||||
public static Dictionary<string, OperacaoSensoriamentoLogModel> RoversNaRede { get; set; } = new Dictionary<string, OperacaoSensoriamentoLogModel>();
|
||||
private static double TempoRoverVivo = 5.0;
|
||||
private static bool AdicionandoNovoRover = false;
|
||||
private static bool AtualizandoListaRovers = false;
|
||||
public static List<OperacaoParametrosModel> RoversNaRede { get; set; } = new List<OperacaoParametrosModel>();
|
||||
public static string SelectedRoverId { get; set; } = BaseMarkerID;
|
||||
public static OperacaoParametrosModel? RoverEmFoco => RoversNaRede.FirstOrDefault(x => x.RoverId == SelectedRoverId);
|
||||
public static bool BaseEmFoco => SelectedRoverId == BaseMarkerID;
|
||||
|
||||
public static async void AdicionarNovoRoverNaRede(string device_id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(device_id))
|
||||
return;
|
||||
if (AdicionandoNovoRover) return;
|
||||
AdicionandoNovoRover = true;
|
||||
|
||||
bool rover_ja_adicionado = false;
|
||||
lock (_RoversLock)
|
||||
try
|
||||
{
|
||||
rover_ja_adicionado = RoversNaRede.ContainsKey(device_id);
|
||||
}
|
||||
if (string.IsNullOrEmpty(device_id))
|
||||
return;
|
||||
|
||||
if (!rover_ja_adicionado)
|
||||
{
|
||||
bool rover_ja_adicionado = false;
|
||||
lock (_RoversLock)
|
||||
{
|
||||
RoversNaRede.Add(device_id, new OperacaoSensoriamentoLogModel() { Momento = DateTime.Now });
|
||||
rover_ja_adicionado = RoversNaRede.Any(x => x.RoverId == device_id);
|
||||
}
|
||||
|
||||
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", device_id));
|
||||
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttTelemetria.Replace("<id>", device_id), true, 1, async (message) =>
|
||||
if (!rover_ja_adicionado)
|
||||
{
|
||||
try
|
||||
lock (_RoversLock)
|
||||
{
|
||||
string json = message.Mensagem;
|
||||
var obj = JsonConvert.DeserializeObject<OperacaoSensoriamentoLogModel>(json);
|
||||
lock (_RoversLock)
|
||||
RoversNaRede.Add(new OperacaoParametrosModel()
|
||||
{
|
||||
RoversNaRede[device_id] = obj;
|
||||
RoverId = device_id,
|
||||
Configurado = false,
|
||||
Alive = true,
|
||||
DadosLeitura = new OperacaoSensoriamentoLogModel()
|
||||
{
|
||||
Momento = DateTime.Now
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
((App)Application.Current).Shell.Main.AtualizarDadosTela_Telemetria(device_id);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao deserializar dados de telemetria do rover {device_id}: {ex.Message}");
|
||||
}
|
||||
});
|
||||
bool t_hbt_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttHeartbeat.Replace("<id>", device_id));
|
||||
if (!t_hbt_added)
|
||||
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttHeartbeat.Replace("<id>", device_id));
|
||||
bool t_cmd_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", device_id));
|
||||
if (!t_cmd_added)
|
||||
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", device_id));
|
||||
bool t_tel_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttTelemetria.Replace("<id>", device_id));
|
||||
if (!t_tel_added)
|
||||
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttTelemetria.Replace("<id>", device_id), true, 1, async (message) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = message.Mensagem;
|
||||
if (string.IsNullOrEmpty(json)) return;
|
||||
var obj = JsonConvert.DeserializeObject<OperacaoSensoriamentoLogModel>(json);
|
||||
lock (_RoversLock)
|
||||
{
|
||||
var rover = RoversNaRede.FirstOrDefault(x => x.RoverId == device_id);
|
||||
if (rover != null)
|
||||
{
|
||||
obj.Momento = DateTime.Now;
|
||||
rover.DadosLeitura = obj;
|
||||
}
|
||||
}
|
||||
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(device_id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao deserializar dados de telemetria do rover {device_id}: {ex.Message}");
|
||||
}
|
||||
});
|
||||
bool t_par_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttParametros.Replace("<id>", device_id));
|
||||
if (!t_par_added)
|
||||
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttParametros.Replace("<id>", device_id), true, 1, async (message) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = message.Mensagem;
|
||||
if (string.IsNullOrEmpty(json)) return;
|
||||
var obj = JsonConvert.DeserializeObject<OperacaoParametrosModel>(json);
|
||||
lock (_RoversLock)
|
||||
{
|
||||
var rover = RoversNaRede.FirstOrDefault(x => x.RoverId == device_id);
|
||||
if (rover != null)
|
||||
{
|
||||
rover = obj;
|
||||
}
|
||||
}
|
||||
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(device_id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao deserializar dados de parametros do rover {device_id}: {ex.Message}");
|
||||
}
|
||||
});
|
||||
|
||||
await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
|
||||
List<string> dispositivos_ids = new List<string>() { "BASE" };
|
||||
lock (_RoversLock)
|
||||
{
|
||||
List<string> dispositivos_ids = new List<string>() { "BASE" };
|
||||
dispositivos_ids.Union(RoversNaRede.Select(x => x.Key).ToList());
|
||||
((App)Application.Current).Shell.Main.AtualizarListaDispositivos(dispositivos_ids);
|
||||
dispositivos_ids = dispositivos_ids.Union(RoversNaRede.Select(x => x.RoverId).ToList()).ToList();
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI lista dispositivos: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
((App)Application.Current).Shell.Main?.AtualizarListaDispositivos(dispositivos_ids);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AdicionandoNovoRover = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async void AtualizarListaRoversNaRede()
|
||||
{
|
||||
List<string> rovers_desconectados = new List<string>();
|
||||
var rovers_atual = new Dictionary<string, OperacaoSensoriamentoLogModel>();
|
||||
lock (_RoversLock)
|
||||
{
|
||||
rovers_atual = new Dictionary<string, OperacaoSensoriamentoLogModel>(RoversNaRede);
|
||||
}
|
||||
foreach (var rover in rovers_atual)
|
||||
{
|
||||
double tempo_sem_resposta = (DateTime.Now - rover.Value.Momento).TotalSeconds;
|
||||
if (tempo_sem_resposta > 5.0)
|
||||
{
|
||||
rovers_desconectados.Add(rover.Key);
|
||||
}
|
||||
}
|
||||
foreach (var device_id in rovers_desconectados)
|
||||
if (AtualizandoListaRovers) return;
|
||||
AtualizandoListaRovers = true;
|
||||
|
||||
try
|
||||
{
|
||||
var rovers_atual = new List<OperacaoParametrosModel>();
|
||||
lock (_RoversLock)
|
||||
{
|
||||
RoversNaRede.Remove(device_id);
|
||||
|
||||
if (SelectedRoverId == device_id)
|
||||
rovers_atual = new List<OperacaoParametrosModel>(RoversNaRede);
|
||||
}
|
||||
foreach (var rover in rovers_atual)
|
||||
{
|
||||
rover.Alive = (DateTime.Now - rover.DadosLeitura.Momento).TotalSeconds < TempoRoverVivo;
|
||||
if (!rover.Alive)
|
||||
{
|
||||
((App)Application.Current).Shell.Main.LimparDadosTela_Telemetria();
|
||||
((App)Application.Current).Shell.Main?.MAP?.markers?.UpdateMarkerInfo(rover.RoverId, status: AgroBase.Models.Enums.StatusOperacao.Erro);
|
||||
}
|
||||
}
|
||||
var topicos_rover = Variaveis.MqttService.Topicos.Where(x => x.Topico.Contains(device_id)).ToList();
|
||||
foreach (var topico in topicos_rover)
|
||||
{
|
||||
await Variaveis.MqttService.UnsubscribeAsync(topico);
|
||||
Variaveis.MqttService.Topicos.Remove(topico);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
AtualizandoListaRovers = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async void EnviarDadosControle(string rover_id, OperacaoControleBaseModel controle)
|
||||
public static async void EnviarDadosHeartbeat()
|
||||
{
|
||||
var topicos = Variaveis.MqttService.Topicos.Where(x => x.Topico.Contains(VariaveisEquipamento.TopicoMqttHeartbeat.Split("/")[VariaveisEquipamento.TopicoMqttHeartbeat.Split("/").Length - 1]));
|
||||
foreach (var topico in topicos)
|
||||
{
|
||||
await Variaveis.MqttService.PublishAsync(topico, "0");
|
||||
}
|
||||
}
|
||||
|
||||
private static async void EnviarDadosControle(string rover_id, OperacaoComandoBaseModel controle)
|
||||
{
|
||||
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", rover_id));
|
||||
if (topico != null)
|
||||
|
|
@ -163,7 +218,7 @@ namespace OperationControl.Models
|
|||
|
||||
public static async void EnviarDadosPosicao(GPSModel posicao)
|
||||
{
|
||||
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == TopicoMqttPosicao);
|
||||
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == VariaveisMonitoramento.TopicoMqttPosicao);
|
||||
if (topico != null)
|
||||
{
|
||||
string json = JsonConvert.SerializeObject(posicao);
|
||||
|
|
@ -173,12 +228,74 @@ namespace OperationControl.Models
|
|||
|
||||
public static async void EnviarDadosCorrecaoRTCM(byte[] correcao)
|
||||
{
|
||||
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == TopicoMqttRTCM);
|
||||
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == VariaveisMonitoramento.TopicoMqttRTCM);
|
||||
if (topico != null)
|
||||
{
|
||||
await Variaveis.MqttService.PublishAsync(topico, correcao);
|
||||
}
|
||||
}
|
||||
|
||||
#region Controle
|
||||
|
||||
public static void EnviarComandoIniciarOperacao(bool iniciar, bool simulador = false)
|
||||
{
|
||||
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Dispositivo = AgroBase.Models.Enums.T_Code.Mod,
|
||||
Tecla = simulador ? AgroBase.Models.Enums.BotoesJoystick.Share : iniciar ? AgroBase.Models.Enums.BotoesJoystick.PS : AgroBase.Models.Enums.BotoesJoystick.Vazio
|
||||
});
|
||||
}
|
||||
|
||||
public static void EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code disp, bool ligar)
|
||||
{
|
||||
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Dispositivo = disp,
|
||||
Tecla = ligar ? AgroBase.Models.Enums.BotoesJoystick.L1 : AgroBase.Models.Enums.BotoesJoystick.Vazio
|
||||
});
|
||||
}
|
||||
|
||||
public static void EnviarComandoParada(bool? emergencia = null, bool? pausa = null)
|
||||
{
|
||||
var cmd = new OperacaoComandoBaseModel() { Momento = DateTime.Now };
|
||||
if (emergencia != null) cmd.Emergencia = (bool)emergencia;
|
||||
if (pausa != null) cmd.Pausa = (bool)pausa;
|
||||
if (emergencia != null || pausa != null)
|
||||
EnviarDadosControle(SelectedRoverId, cmd);
|
||||
}
|
||||
|
||||
public static void EnviarComandoReferenciamento()
|
||||
{
|
||||
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Tecla = AgroBase.Models.Enums.BotoesJoystick.R3
|
||||
});
|
||||
}
|
||||
|
||||
public static void EnviarComandoLeverArm(double valorCm)
|
||||
{
|
||||
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Dispositivo = AgroBase.Models.Enums.T_Code.Gps,
|
||||
LeverArmLateral = Math.Round(valorCm, 0),
|
||||
});
|
||||
}
|
||||
|
||||
public static void EnviarParametrosOperacao(OperacaoParametrosModel parametros)
|
||||
{
|
||||
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
|
||||
{
|
||||
Momento = DateTime.Now,
|
||||
Parametros = parametros,
|
||||
Tecla = (!(RoverEmFoco.DadosLeitura?.OperacaoIniciada ?? false) ? AgroBase.Models.Enums.BotoesJoystick.Options : AgroBase.Models.Enums.BotoesJoystick.Vazio)
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>True</UseWindowsForms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -21,6 +22,12 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="BruTile" Version="6.0.0" />
|
||||
<PackageReference Include="BruTile.MbTiles" Version="6.0.0" />
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="5.0.0" />
|
||||
<PackageReference Include="FFME.Windows" Version="7.0.361-beta.1" />
|
||||
<PackageReference Include="GirCore.Gst-1.0" Version="0.7.0-preview.3" />
|
||||
<PackageReference Include="GirCore.GstVideo-1.0" Version="0.7.0-preview.3" />
|
||||
<PackageReference Include="LibVLCSharp" Version="3.9.4" />
|
||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.4" />
|
||||
<PackageReference Include="Mapsui" Version="5.0.0" />
|
||||
<PackageReference Include="Mapsui.Extensions" Version="5.0.0" />
|
||||
<PackageReference Include="Mapsui.Wpf" Version="5.0.0" />
|
||||
|
|
@ -31,6 +38,7 @@
|
|||
<PackageReference Include="OpenTK" Version="4.9.4" />
|
||||
<PackageReference Include="ScottPlot.WPF" Version="5.1.57" />
|
||||
<PackageReference Include="System.IO.Ports" Version="10.0.0" />
|
||||
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.21" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
<Compile Update="Controls\Bbox3DViewer.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\GstVideoView.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\HeadingIndicator.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
|
@ -42,6 +45,9 @@
|
|||
<Page Update="Controls\Bbox3DViewer.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\GstVideoView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\HeadingIndicator.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using AgroBase.Models;
|
|||
using static AgroBase.Models.Enums;
|
||||
using OperationControl.Models;
|
||||
using System.Windows;
|
||||
using Application = System.Windows.Application;
|
||||
|
||||
namespace OperationControl.Services
|
||||
{
|
||||
|
|
@ -1199,6 +1200,7 @@ namespace OperationControl.Services
|
|||
{
|
||||
Models.Variaveis.MostrarLog("Poucas amostras de RTK FIX coletadas. Tente aumentar o tempo ou verificar sinais.");
|
||||
CorrecaoAbsoluta = false;
|
||||
FixLiberado = false;
|
||||
return CorrecaoAbsoluta;
|
||||
}
|
||||
|
||||
|
|
@ -1211,6 +1213,7 @@ namespace OperationControl.Services
|
|||
Models.Variaveis.MostrarLog($"[BASE/FIX] Coordenadas aplicadas (n={nAmostras}):");
|
||||
Models.Variaveis.MostrarLog($" lat = {lat:0.000000000}, lon = {lon:0.000000000}, h = {h:0.000}");
|
||||
CorrecaoAbsoluta = true;
|
||||
FixLiberado = false;
|
||||
return CorrecaoAbsoluta;
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:scott="clr-namespace:ScottPlot.WPF;assembly=ScottPlot.WPF"
|
||||
xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
|
||||
xmlns:controls="clr-namespace:OperationControl.Controls"
|
||||
mc:Ignorable="d"
|
||||
Title="Controle da Opearação Agrobot" Height="1025" Width="1920" WindowStartupLocation="CenterScreen" WindowState="Maximized">
|
||||
|
|
@ -26,30 +27,30 @@
|
|||
<Canvas>
|
||||
<Label Content="Resumo Operacional" FontWeight="Bold" FontSize="10" HorizontalAlignment="Left" Canvas.Top="-4" VerticalAlignment="Center" Canvas.Left="-2"/>
|
||||
<Label Content="Rua Atual" FontSize="10" HorizontalAlignment="Center" Canvas.Top="12" VerticalAlignment="Top" RenderTransformOrigin="0.756,0.502"/>
|
||||
<controls:ProgressBarText Height="10" Canvas.Left="57" Canvas.Top="19" Width="92" HorizontalAlignment="Left" VerticalAlignment="Center" Value="63"/>
|
||||
<Label Content="74,17 m / 135,84 m (1)" FontSize="10" Canvas.Top="12" HorizontalAlignment="Center" VerticalAlignment="Center" Canvas.Left="154"/>
|
||||
<controls:ProgressBarText x:Name="pgbResumo_RuaAtual" Height="10" Canvas.Left="57" Canvas.Top="19" Width="92" HorizontalAlignment="Left" VerticalAlignment="Center" Value="63"/>
|
||||
<Label x:Name="lblResumo_RuaAtual" Content="74,17 m / 135,84 m (1)" FontSize="10" Canvas.Top="12" HorizontalAlignment="Center" VerticalAlignment="Center" Canvas.Left="154"/>
|
||||
<Label Content="Área Total" FontSize="10" HorizontalAlignment="Center" Canvas.Top="28" VerticalAlignment="Top"/>
|
||||
<controls:ProgressBarText Height="10" Canvas.Left="57" Canvas.Top="34" Width="92" HorizontalAlignment="Left" VerticalAlignment="Top" Value="78"/>
|
||||
<Label Content="365,32 m / 1.366,10 m" FontSize="10" Canvas.Top="28" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Left="154"/>
|
||||
<controls:ProgressBarText x:Name="pgbResumo_AreaTotal" Height="10" Canvas.Left="57" Canvas.Top="34" Width="92" HorizontalAlignment="Left" VerticalAlignment="Top" Value="78"/>
|
||||
<Label x:Name="lblResumo_AreaTotal" Content="365,32 m / 1.366,10 m" FontSize="10" Canvas.Top="28" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Left="154"/>
|
||||
<Label Content="Bateria" FontSize="10" HorizontalAlignment="Center" Canvas.Top="44" VerticalAlignment="Top"/>
|
||||
<controls:ProgressBarText Height="10" Canvas.Left="57" Canvas.Top="51" Width="92" HorizontalAlignment="Left" VerticalAlignment="Top" Value="84"/>
|
||||
<Label Content="40,85 V (01:36:45)" FontSize="9" HorizontalAlignment="Center" Canvas.Top="44" VerticalAlignment="Center" Canvas.Left="154"/>
|
||||
<controls:ProgressBarText x:Name="pgbResumo_Bateria" Height="10" Canvas.Left="57" Canvas.Top="51" Width="92" HorizontalAlignment="Left" VerticalAlignment="Top" Value="84"/>
|
||||
<Label x:Name="lblResumo_Bateria" Content="40,85 V (01:36:45)" FontSize="9" HorizontalAlignment="Center" Canvas.Top="44" VerticalAlignment="Center" Canvas.Left="154"/>
|
||||
<Label Content="Herbicida" FontSize="10" HorizontalAlignment="Center" Canvas.Top="60" VerticalAlignment="Top"/>
|
||||
<controls:ProgressBarText Height="10" Canvas.Left="57" Canvas.Top="67" Width="92" HorizontalAlignment="Left" VerticalAlignment="Top" Value="73"/>
|
||||
<Label Content="21,90 L (584,32 m)" FontSize="9" HorizontalAlignment="Left" Canvas.Top="60" VerticalAlignment="Center" Canvas.Left="154"/>
|
||||
<controls:ProgressBarText x:Name="pgbResumo_Herbicida" Height="10" Canvas.Left="57" Canvas.Top="67" Width="92" HorizontalAlignment="Left" VerticalAlignment="Top" Value="73"/>
|
||||
<Label x:Name="lblResumo_Herbicida" Content="21,90 L (584,32 m)" FontSize="9" HorizontalAlignment="Left" Canvas.Top="60" VerticalAlignment="Center" Canvas.Left="154"/>
|
||||
<Label Content="Infestação" FontSize="10" Canvas.Top="76" HorizontalAlignment="Center" VerticalAlignment="Top"/>
|
||||
<controls:ProgressBarText Height="10" Canvas.Left="57" Canvas.Top="83" Width="92" HorizontalAlignment="Center" VerticalAlignment="Top" Value="23"/>
|
||||
<Label Content="234,51 mL/erva" FontSize="9" HorizontalAlignment="Center" Canvas.Top="76" VerticalAlignment="Top" Canvas.Left="154"/>
|
||||
<controls:ProgressBarText x:Name="pgbResumo_Infestacao" Height="10" Canvas.Left="57" Canvas.Top="83" Width="92" HorizontalAlignment="Center" VerticalAlignment="Top" Value="23"/>
|
||||
<Label x:Name="lblResumo_Infestacao" Content="234,51 mL/erva" FontSize="9" HorizontalAlignment="Center" Canvas.Top="76" VerticalAlignment="Top" Canvas.Left="154"/>
|
||||
<Label Content="Conexão" FontSize="10" Canvas.Top="92" HorizontalAlignment="Center" VerticalAlignment="Top"/>
|
||||
<controls:ProgressBarText Height="10" Canvas.Left="57" Canvas.Top="99" Width="92" HorizontalAlignment="Center" VerticalAlignment="Top" Value="97"/>
|
||||
<Label Content="4,9 dBi (574,65 m)" FontSize="9" HorizontalAlignment="Center" Canvas.Top="92" VerticalAlignment="Top" Canvas.Left="154"/>
|
||||
<controls:ProgressBarText x:Name="pgbResumo_Conexao" Height="10" Canvas.Left="57" Canvas.Top="99" Width="92" HorizontalAlignment="Center" VerticalAlignment="Top" Value="97"/>
|
||||
<Label x:Name="lblResumo_Conexao" Content="4,9 dBi (574,65 m)" FontSize="9" HorizontalAlignment="Center" Canvas.Top="92" VerticalAlignment="Top" Canvas.Left="154"/>
|
||||
|
||||
<Label Content="Operação Liberado" FontSize="10" Canvas.Top="12" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label Content="Modo Automático" FontSize="10" Canvas.Top="28" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label Content="Status EmAndamento" FontSize="10" Canvas.Top="44" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label Content="Carro CaminhandoRua" FontSize="10" Canvas.Top="60" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label Content="Temperatura 45,32°C" FontSize="10" Canvas.Top="76" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label Content="Duração 00:23:15 / 00:54:15" FontSize="10" Canvas.Top="92" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label x:Name="lblResumo_OperacaoLiberada" Content="Operação Liberado" FontFamily="Segoe UI Emoji" FontSize="10" Canvas.Top="12" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label x:Name="lblResumo_OperacaoModo" Content="Modo Automático" FontSize="10" Canvas.Top="28" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label x:Name="lblResumo_OperacaoStatus" Content="Status EmAndamento" FontSize="10" Canvas.Top="44" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label x:Name="lblResumo_StatusCarro" Content="Carro CaminhandoRua" FontSize="10" Canvas.Top="60" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label x:Name="lblResumo_TemperaturaGeral" Content="Temperatura 45,32°C" FontSize="10" Canvas.Top="76" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
<Label x:Name="lblResumo_OperacaoDuracao" Content="Duração 00:23:15 / 00:54:15" FontSize="10" Canvas.Top="92" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="286"/>
|
||||
|
||||
|
||||
</Canvas>
|
||||
|
|
@ -143,8 +144,13 @@
|
|||
<Label x:Name="lblGNSS_Correcao" Content="Correção RTKFixo B 1,3 s" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="16" FontSize="9"/>
|
||||
<Label x:Name="lblGNSS_Satelites" Content="Satélites 29 (0,60 cm)" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="29" FontSize="9"/>
|
||||
<Label x:Name="lblGNSS_Altitude" Content="Altitude 634,21 m" HorizontalAlignment="Left" VerticalAlignment="Top" Canvas.Left="-1" Canvas.Top="42" FontSize="9"/>
|
||||
<Button x:Name="btnGNSS_FixarBase" Content="Fixar" Canvas.Left="127" Canvas.Top="17" Click="btnGNSS_FixarBase_Click" HorizontalAlignment="Left" VerticalAlignment="Center" Width="50"/>
|
||||
<Label x:Name="lblGNSS_Progresso" Content="0,00%" HorizontalAlignment="Right" VerticalAlignment="Center" Canvas.Left="143" Canvas.Top="42" FontSize="9"/>
|
||||
|
||||
<Slider x:Name="sldGNSS_LeverArm" Canvas.Left="67" Canvas.Top="1" Width="116" HorizontalAlignment="Center" Height="18" VerticalAlignment="Center" Maximum="5" Minimum="-5" TickFrequency="1" Value="0" ValueChanged="sldGNSS_LeverArm_ValueChanged"/>
|
||||
<Label x:Name="lblGNSS_Progresso" Content="0,00%" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Left="143" Canvas.Top="16" FontSize="9"/>
|
||||
<Button x:Name="btnGNSS_FixarBase" Content="Fixar" Canvas.Left="127" Canvas.Top="42" Click="btnGNSS_FixarBase_Click" HorizontalAlignment="Center" VerticalAlignment="Center" Width="50"/>
|
||||
|
||||
|
||||
|
||||
</Canvas>
|
||||
</Border>
|
||||
|
||||
|
|
@ -154,25 +160,28 @@
|
|||
<Canvas Height="64" VerticalAlignment="Bottom">
|
||||
<Label Content="Parâmetros da Operação" FontWeight="Bold" FontSize="11" Canvas.Top="-3" HorizontalAlignment="Center" VerticalAlignment="Top"/>
|
||||
<Label Content="Vel. com Ervas" FontSize="9" Canvas.Top="15" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<Label Content="Vel. sem Ervas" FontSize="9" Canvas.Top="30" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Left="1"/>
|
||||
<Label Content="Angulo Máximo" FontSize="9" Canvas.Top="45" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Left="1"/>
|
||||
<TextBox Canvas.Left="73" TextWrapping="Wrap" Text="1,5" Canvas.Top="19" Width="30" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Velocidade que o equipamento se move quando há presença de ervas no radar, em km/h"/>
|
||||
<TextBox Canvas.Left="73" TextWrapping="Wrap" Text="3,5" Canvas.Top="34" Width="30" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Velocidade que o equipamento se move quando não há presença de ervas no radar, em km/h"/>
|
||||
<TextBox Canvas.Left="73" TextWrapping="Wrap" Text="30" Canvas.Top="49" Width="30" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Angulo máximo de controle direcional, em graus"/>
|
||||
<Label Content="km/h" FontSize="9" Canvas.Top="15" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="100"/>
|
||||
<Label Content="km/h" FontSize="9" Canvas.Top="30" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="100"/>
|
||||
<Label Content="°" FontSize="9" Canvas.Top="45" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="100"/>
|
||||
<Label Content="Ervas % ROI" FontSize="9" Canvas.Top="15" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="130"/>
|
||||
<Label Content="Ervas % Area" FontSize="9" Canvas.Top="30" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="130"/>
|
||||
<Label Content="Pressão Linha" FontSize="9" Canvas.Top="45" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="130"/>
|
||||
<TextBox Canvas.Left="194" TextWrapping="Wrap" Text="70" Canvas.Top="19" Width="30" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Percentual da imagem onde a erva detectada envia o comando para atuação dos bicos pulverizadores, onde 100% em cima e 0% em baixo"/>
|
||||
<TextBox Canvas.Left="194" TextWrapping="Wrap" Text="10" Canvas.Top="34" Width="30" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Percentual de ervas detectada sobre a região de um bico para ligar e desligar o bico pulverizador"/>
|
||||
<TextBox Canvas.Left="194" TextWrapping="Wrap" Text="85" Canvas.Top="49" Width="30" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Pressão da linha, em psi"/>
|
||||
<Label Content="psi" FontSize="9" Canvas.Top="45" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="224"/>
|
||||
<CheckBox Content="Modo Manual" Canvas.Left="249" Canvas.Top="2" FontSize="9" VerticalAlignment="Top" ToolTip="Ativa controle manual do equipamento selecionado" HorizontalAlignment="Left"/>
|
||||
<CheckBox Content="Pulverizador Automático" Canvas.Left="249" Canvas.Top="18" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Top" ToolTip="Atuação automática do pulverizador ao detectar ervas no radar sobre a área de um bico"/>
|
||||
<CheckBox Content="Frenagem Automática" Canvas.Left="249" Canvas.Top="33" FontSize="10" HorizontalAlignment="Left" VerticalAlignment="Center" ToolTip="Acionamento automático dos freios ao detectar obstáculos próximos"/>
|
||||
<CheckBox Content="Sonar Ativado" Canvas.Left="249" Canvas.Top="48" FontSize="10" HorizontalAlignment="Left" VerticalAlignment="Center" ToolTip="Utilizar dados do sonar na tomada de decisão de controle direcional automático"/>
|
||||
<Label Content="Vel. sem Ervas" FontSize="9" Canvas.Top="30" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||||
<Label Content="Angulo Máx" FontSize="9" Canvas.Top="45" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||||
<TextBox x:Name="txtParametros_VelCErvas" Canvas.Left="64" TextWrapping="Wrap" Text="1,5" Canvas.Top="19" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Velocidade que o equipamento se move quando há presença de ervas no radar, em km/h"/>
|
||||
<TextBox x:Name="txtParametros_VelSErvas" Canvas.Left="64" TextWrapping="Wrap" Text="3,5" Canvas.Top="34" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Velocidade que o equipamento se move quando não há presença de ervas no radar, em km/h"/>
|
||||
<TextBox x:Name="txtParametros_AngMax" Canvas.Left="64" TextWrapping="Wrap" Text="30" Canvas.Top="49" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Angulo máximo de controle direcional, em graus"/>
|
||||
<Label Content="Início Atuação" FontSize="9" Canvas.Top="15" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="93"/>
|
||||
<Label Content="Area Atuação" FontSize="9" Canvas.Top="30" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="93"/>
|
||||
<Label Content="Pressão Linha" FontSize="9" Canvas.Top="45" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="93"/>
|
||||
<TextBox x:Name="txtParametros_RoiAtuacao" Canvas.Left="156" TextWrapping="Wrap" Text="70" Canvas.Top="19" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Percentual da imagem onde a erva detectada envia o comando para atuação dos bicos pulverizadores, onde 100% em cima e 0% em baixo"/>
|
||||
<TextBox x:Name="txtParametros_AreaAtuacao" Canvas.Left="156" TextWrapping="Wrap" Text="10" Canvas.Top="34" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Percentual de altura da imagem para atuação dos bicos quando as ervas entrarem nessa região"/>
|
||||
<TextBox x:Name="txtParametros_PressaoLiha" Canvas.Left="156" TextWrapping="Wrap" Text="85" Canvas.Top="49" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Pressão da linha, em psi"/>
|
||||
<Label Content="Erva % On" FontSize="9" Canvas.Top="15" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="185"/>
|
||||
<Label Content="Erva % Off" FontSize="9" Canvas.Top="30" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="185"/>
|
||||
<Label Content="Tempo On" FontSize="9" Canvas.Top="45" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="185"/>
|
||||
<TextBox x:Name="txtParametros_PctErvaOn" Canvas.Left="234" TextWrapping="Wrap" Text="2" Canvas.Top="19" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Percentual de ervas detectado na região de um bico para ligar o bico pulverizador"/>
|
||||
<TextBox x:Name="txtParametros_PctErvaOff" Canvas.Left="234" TextWrapping="Wrap" Text="1" Canvas.Top="34" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Percentual de ervas detectado na região de um bico para desligar o bico pulverizador"/>
|
||||
<TextBox x:Name="txtParametros_TempoOn" Canvas.Left="234" TextWrapping="Wrap" Text="200" Canvas.Top="49" Width="25" FontSize="9" HorizontalAlignment="Left" VerticalAlignment="Center" TextAlignment="Center" ToolTip="Tempo em que o bico pulverizador fica atuado após detectar a erva, em milissegundos"/>
|
||||
<CheckBox x:Name="chbParametros_Sonar" Content="Sonar Ativado" Canvas.Left="265" Canvas.Top="18" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Top" ToolTip="Utilizar dados do sonar na tomada de decisão de controle direcional automático"/>
|
||||
<CheckBox x:Name="chbParametros_Frenagem" Content="Frenagem Automática" Canvas.Left="265" Canvas.Top="33" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Top" ToolTip="Acionamento automático dos freios ao detectar obstáculos próximos"/>
|
||||
<CheckBox x:Name="chbParametros_Pulverizador" Content="Pulverizador Automático" Canvas.Left="265" Canvas.Top="48" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Top" ToolTip="Atuação automática do pulverizador ao detectar ervas no radar sobre a área de um bico"/>
|
||||
<Button x:Name="btnParametros_Salvar" Content="💾" FontSize="10" Canvas.Left="372" Canvas.Top="3" Click="btnParametros_Salvar_Click" HorizontalAlignment="Left" VerticalAlignment="Center" ToolTip="Salva os ajustes realizados nos parâmetros da operação, e envia para o equipamento em foco"/>
|
||||
<Button x:Name="btnParametros_Atualizar" Content="🔄" FontSize="10" Canvas.Left="351" Canvas.Top="3" Click="btnParametros_Atualizar_Click" HorizontalAlignment="Left" VerticalAlignment="Center" ToolTip="Atualiza os dados de parâmetros da operação do equipaento em foco"/>
|
||||
</Canvas>
|
||||
</Border>
|
||||
|
||||
|
|
@ -186,27 +195,27 @@
|
|||
|
||||
<Border x:Name="brdControle" Margin="659,0,877,943">
|
||||
<Canvas>
|
||||
<controls:ManualControlPad x:Name="PadCtl" MaxSteerDeg="90" SpeedSpKmh="3.2" SpeedCurKmh="3.31" AngleSpDeg="2.92" AngleCurDeg="2.4" MoveType="MovimentoDiagonal"/>
|
||||
<controls:ManualControlPad x:Name="CTRL"/>
|
||||
</Canvas>
|
||||
</Border>
|
||||
|
||||
<Border Name="brdMapaInfo" BorderBrush="Black" BorderThickness="1" Height="26" Width="980" Canvas.Top="878" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="465,951,0,0">
|
||||
<Canvas>
|
||||
<Label Content="Próximo Ponto: 15 | Aproximando | Distância próximo ponto: 1,32 m | Distância ponto anterior: 0,74 m | Corredor: Dentro | Margem: Não | Disância Esquerda: 34 cm | Distância Direita: 36 cm | Status: CaminhandoRua" FontSize="9" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="1"/>
|
||||
<Label x:Name="lblMapaInfo_Debug" Content="Próximo Ponto: 15 | Aproximando | Distância próximo ponto: 1,32 m | Distância ponto anterior: 0,74 m | Corredor: Dentro | Margem: Não | Disância Esquerda: 34 cm | Distância Direita: 36 cm | Status: CaminhandoRua" FontSize="9" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="1"/>
|
||||
</Canvas>
|
||||
</Border>
|
||||
|
||||
<Border x:Name="brdCameraFrontal" BorderBrush="Black" BorderThickness="1" CornerRadius="8" Margin="1453,0,7,735">
|
||||
<Canvas>
|
||||
<Label Content="Câmera frontal | 12 fps | 230 kbps | 0,00% cana | 43 cm - 27 cm | 12,95° | CaminhandoRua" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="-3"/>
|
||||
<Image HorizontalAlignment="Center" Height="243" VerticalAlignment="Top" Width="438" Source="/Resources/caminho.jpeg" Stretch="UniformToFill" Canvas.Top="21" Canvas.Left="10"/>
|
||||
<vlc:VideoView x:Name="VideoFront" Background="Black" Height="237" Width="438" HorizontalAlignment="Center" Canvas.Top="25" VerticalAlignment="Top" Canvas.Left="10"/>
|
||||
</Canvas>
|
||||
</Border>
|
||||
|
||||
<Border x:Name="brdCameraTraseira" BorderBrush="Black" BorderThickness="1" CornerRadius="8" Margin="1453,281,7,491">
|
||||
<Canvas>
|
||||
<Label Content="Câmera traseira | 10 fps | 193 kbps | 5,41% erva | 0,00% cana" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Top" Canvas.Top="-3"/>
|
||||
<Image HorizontalAlignment="Left" Height="201" VerticalAlignment="Center" Width="438" Source="/Resources/solo.jpeg" Stretch="UniformToFill" Canvas.Top="21" Canvas.Left="10"/>
|
||||
<vlc:VideoView x:Name="VideoWeed" Background="Black" Height="200" Width="438" HorizontalAlignment="Center" Canvas.Top="25" VerticalAlignment="Top" Canvas.Left="10"/>
|
||||
</Canvas>
|
||||
</Border>
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ using OperationControl.Services;
|
|||
using System.Windows.Controls;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Media;
|
||||
using DotSpatial.Projections.Transforms;
|
||||
using System;
|
||||
using LibVLCSharp.Shared;
|
||||
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;
|
||||
using System.IO;
|
||||
using ComboBox = System.Windows.Controls.ComboBox;
|
||||
using Application = System.Windows.Application;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
|
||||
namespace OperationControl.Windows
|
||||
{
|
||||
|
|
@ -36,6 +44,11 @@ namespace OperationControl.Windows
|
|||
DispatcherTimer _clock = new DispatcherTimer();
|
||||
Random _rand = new Random();
|
||||
|
||||
private LibVLC _libVLC;
|
||||
private MediaPlayer _playerFront;
|
||||
private MediaPlayer _playerWeed;
|
||||
private Media _mediaFront;
|
||||
private Media _mediaWeed;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
|
|
@ -71,6 +84,36 @@ namespace OperationControl.Windows
|
|||
// new AgroBase.Models.LivoxBboxModel{ cx=3.0, cy=-0.7, cz=0.6, d=0.8, w=0.5, h=1.2 },
|
||||
//});
|
||||
|
||||
|
||||
// Opções focadas em baixa latência
|
||||
_libVLC = new LibVLC(
|
||||
"--network-caching=1000", // ms (ajusta depois)
|
||||
"--clock-jitter=0",
|
||||
"--clock-synchro=0"
|
||||
);
|
||||
|
||||
// Player da câmera frontal
|
||||
_playerFront = new MediaPlayer(_libVLC);
|
||||
VideoFront.MediaPlayer = _playerFront;
|
||||
_playerWeed = new MediaPlayer(_libVLC);
|
||||
VideoWeed.MediaPlayer = _playerWeed;
|
||||
|
||||
|
||||
Loaded += MainWindow_Loaded;
|
||||
Closed += MainWindow_Closed;
|
||||
|
||||
}
|
||||
|
||||
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void MainWindow_Closed(object? sender, EventArgs e)
|
||||
{
|
||||
PararStreamCameraFrontal(true);
|
||||
PararStreamCameraErvas(true);
|
||||
_libVLC?.Dispose();
|
||||
}
|
||||
|
||||
private void PushSample(bool initial = false)
|
||||
|
|
@ -151,101 +194,404 @@ namespace OperationControl.Windows
|
|||
|
||||
public void AtualizarListaDispositivos(List<string> dispositivos)
|
||||
{
|
||||
cmbDispositivo.Items.Clear();
|
||||
foreach (var d in dispositivos)
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
cmbDispositivo.Items.Add(d);
|
||||
if (!MAP.markers.Added(d))
|
||||
try
|
||||
{
|
||||
if (d == VariaveisControleOperacao.BaseMarkerID)
|
||||
cmbDispositivo.Items.Clear();
|
||||
foreach (var d in dispositivos)
|
||||
{
|
||||
MAP.markers.AddMarker(
|
||||
d,
|
||||
Variaveis.GpsService?.UltimaLeitura?.Latitude ?? 0,
|
||||
Variaveis.GpsService?.UltimaLeitura?.Longitude ?? 0,
|
||||
Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal ?? 0,
|
||||
MAP.markers.GetColorForMarker(d, isBase: true),
|
||||
"Base"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.Key == d);
|
||||
if (rover.Value != null)
|
||||
cmbDispositivo.Items.Add(d);
|
||||
if (!MAP.markers.Added(d))
|
||||
{
|
||||
MAP.markers.AddMarker(
|
||||
d,
|
||||
rover.Value.Gps?.Latitude ?? 0,
|
||||
rover.Value.Gps?.Longitude ?? 0,
|
||||
rover.Value.Gps?.AnguloCarroDefinido ?? 0,
|
||||
MAP.markers.GetColorForMarker(d, isBase: false),
|
||||
rover.Key
|
||||
);
|
||||
if (d == VariaveisControleOperacao.BaseMarkerID)
|
||||
{
|
||||
MAP.markers.AddMarker(
|
||||
d,
|
||||
true,
|
||||
lat: Variaveis.GpsService?.UltimaLeitura?.Latitude ?? 0,
|
||||
lon: Variaveis.GpsService?.UltimaLeitura?.Longitude ?? 0,
|
||||
heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal ?? 0,
|
||||
label: "Base"
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == d);
|
||||
if (rover != null)
|
||||
{
|
||||
MAP.markers.AddMarker(
|
||||
d,
|
||||
false,
|
||||
lat: rover.DadosLeitura?.Gps?.Latitude ?? 0,
|
||||
lon: rover.DadosLeitura?.Gps?.Longitude ?? 0,
|
||||
heading: rover.DadosLeitura?.Gps?.AnguloCarroDefinido ?? 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int idx_selected = dispositivos.IndexOf(VariaveisControleOperacao.SelectedRoverId);
|
||||
if (idx_selected > -1)
|
||||
cmbDispositivo.SelectedIndex = idx_selected;
|
||||
}
|
||||
}
|
||||
int idx_selected = dispositivos.IndexOf(VariaveisControleOperacao.SelectedRoverId);
|
||||
if (idx_selected > -1)
|
||||
cmbDispositivo.SelectedIndex = idx_selected;
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI lista dispositivos: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void cmbDispositivo_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
AtualizarDadosTela_Telemetria(((ComboBox)sender).SelectedValue.ToString());
|
||||
var selecionado = ((ComboBox)sender).SelectedItem;
|
||||
if (selecionado == null) return;
|
||||
bool dados_base = selecionado == VariaveisControleOperacao.BaseMarkerID;
|
||||
if (dados_base && !VariaveisControleOperacao.BaseEmFoco)
|
||||
{
|
||||
PararStreamCameraFrontal();
|
||||
PararStreamCameraErvas();
|
||||
}
|
||||
|
||||
VariaveisControleOperacao.SelectedRoverId = selecionado.ToString();
|
||||
MAP.markers.SetMarkerFocused(selecionado.ToString(), true);
|
||||
AtualizarDadosTela_Telemetria(selecionado.ToString());
|
||||
|
||||
brdResumo.IsEnabled = !dados_base;
|
||||
brdDiagnostico.IsEnabled = !dados_base;
|
||||
brdControle.IsEnabled = !dados_base;
|
||||
brdAjustesOperacao.IsEnabled = !dados_base;
|
||||
if (!dados_base)
|
||||
{
|
||||
sldGNSS_LeverArm.Value = VariaveisControleOperacao.RoverEmFoco.DadosLeitura?.Gps?.LeverArmLateral ?? 0;
|
||||
btnParametros_Atualizar_Click(sender, e);
|
||||
IniciarStreamCameraFrontal();
|
||||
IniciarStreamCameraErvas();
|
||||
}
|
||||
}
|
||||
|
||||
public void LimparDadosTela_Telemetria()
|
||||
public void LimparDadosTela_Telemetria(string rover_id)
|
||||
{
|
||||
VariaveisControleOperacao.SelectedRoverId = "";
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(rover_id))
|
||||
{
|
||||
//MAP.markers.RemoveMarker(rover_id);
|
||||
//cmbDispositivo.Items.Remove(rover_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
//cmbDispositivo.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI telemetria (clear): {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void AtualizarDadosTela_Telemetria(string rover_id)
|
||||
{
|
||||
bool dados_base = rover_id == VariaveisControleOperacao.BaseMarkerID;
|
||||
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover_id)?.DadosLeitura;
|
||||
if (dados_base)
|
||||
{
|
||||
MAP.markers.UpdateMarkerPosition(rover_id, lat: Variaveis.GpsService?.UltimaLeitura?.Latitude, lon: Variaveis.GpsService?.UltimaLeitura?.Longitude, heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal);
|
||||
}
|
||||
else if (rover != null)
|
||||
{
|
||||
var simulacao = rover.Controle?.SimulacaoMPC?.Select(x => new double[] { x.longitude, x.latitude })?.ToList();
|
||||
MAP.markers.UpdateMarkerPosition(rover_id, lat: rover?.Gps?.Latitude, lon: rover?.Gps?.Longitude, heading: rover?.Gps?.OrientacaoReal, predict: simulacao);
|
||||
MAP.markers.UpdateMarkerInfo(rover_id, status: rover.StatusOperacao);
|
||||
}
|
||||
|
||||
if (rover_id != VariaveisControleOperacao.SelectedRoverId) return;
|
||||
|
||||
if (rover_id == VariaveisControleOperacao.BaseMarkerID)
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
Variaveis.MostrarLog($"Atualizando dados da tela para a base");
|
||||
try
|
||||
{
|
||||
if (rover_id == VariaveisControleOperacao.BaseMarkerID)
|
||||
{
|
||||
Variaveis.MostrarLog($"Atualizando dados da tela para a base");
|
||||
|
||||
AtualizarDadosTela_GNSS(Variaveis.GpsService?.UltimaLeitura ?? new AgroBase.Models.GPSModel());
|
||||
AtualizarDadosTela_Heading(Variaveis.GpsService?.UltimaLeitura?.AnguloCarroDefinido ?? 0);
|
||||
AtualizarDadosTela_GNSS(Variaveis.GpsService?.UltimaLeitura ?? new AgroBase.Models.GPSModel(), marker_id: VariaveisControleOperacao.BaseMarkerID);
|
||||
AtualizarDadosTela_Heading(Variaveis.GpsService?.UltimaLeitura?.AnguloCarroDefinido ?? 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rover == null) return;
|
||||
|
||||
Variaveis.MostrarLog($"Atualizando dados da tela para o dispositivo {rover_id}");
|
||||
|
||||
if (rover.Trajetoria != null)
|
||||
AtualizarDadosTela_Resumo(rover);
|
||||
if (rover.Gps != null)
|
||||
AtualizarDadosTela_GNSS(rover.Gps, marker_id: rover_id);
|
||||
if (rover.Controle != null)
|
||||
AtualizarDadosTela_Controle(rover.Controle, rover.Movimentacao.AnguloMedio, rover.Movimentacao.VelocidadeMedia, rover.Emergencia, !rover.OperacaoIniciada, rover.StatusOperacao == AgroBase.Models.Enums.StatusOperacao.Calibrando);
|
||||
//if (rover.Value.Controle != null)
|
||||
// AtualizarDadosTela_ParametrosOperacao(rover.Value.Controle);
|
||||
if (rover.Trajetoria != null)
|
||||
AtualizarDadosTela_Mapa(rover.Trajetoria);
|
||||
if (rover.Gps != null)
|
||||
AtualizarDadosTela_Heading(rover.Gps.AnguloCarroDefinido, rover.Modo == AgroBase.Models.Enums.ModoOperacao.Manual ? double.NaN : rover.Trajetoria.AnguloCaminho);
|
||||
if (rover.IMU != null)
|
||||
AtualizarDadosTela_IMU(rover.IMU.InclinacaoLateral, rover.IMU.InclinacaoFrontal);
|
||||
if (rover.LivoxLidar != null)
|
||||
AtualizarDadostela_LIDAR(rover.LivoxLidar.bboxes);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI telemetria (set): {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region RESUMO OPERACIONAL
|
||||
|
||||
public void AtualizarDadosTela_Resumo(AgroBase.Models.OperacaoSensoriamentoLogModel dados)
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
pgbResumo_RuaAtual.Value = dados.Trajetoria.PercentualRuaAtual;
|
||||
lblResumo_RuaAtual.Content = $"{dados.Trajetoria.CorredorAtual.DistanciaPercorridaCorredor.ToString("0.00")} / {dados.Trajetoria.CorredorAtual.DistanciaTotal.ToString("0.00")}";
|
||||
pgbResumo_AreaTotal.Value = dados.Trajetoria.PercentualOperacao;
|
||||
lblResumo_AreaTotal.Content = $"{dados.Trajetoria.DistanciaPercorrida.ToString("0.00")} / {dados.Trajetoria.DistanciaTotal.ToString("0.00")}";
|
||||
pgbResumo_Bateria.Value = dados.Bateria.PorcentagemBateria;
|
||||
lblResumo_Bateria.Content = $"{dados.Bateria.TensaoInstantanea.ToString("0.00")} V ({dados.Bateria.TempoEstimadoRestanteMinutos})";
|
||||
pgbResumo_Herbicida.Value = dados.Atuador.PercentualReservatorio;
|
||||
lblResumo_Herbicida.Content = $"{dados.Atuador.VolumeReservatorio.ToString("0.00")} L ({0.ToString("0.00")})";
|
||||
pgbResumo_Infestacao.Value = dados.Atuador.PercentualErvasTerreno;
|
||||
lblResumo_Infestacao.Content = $"{dados.Atuador.VazaoMedia.ToString("0.00")}";
|
||||
pgbResumo_Conexao.Value = 0;
|
||||
lblResumo_Conexao.Content = $"0,0 dBi (0,00 m)";
|
||||
|
||||
lblResumo_OperacaoLiberada.Content = $"Operação " + (dados.OperacaoLiberada ? "🔓 Liberada" : "🔒 Bloqueada");
|
||||
lblResumo_OperacaoModo.Content = $"Modo {dados.Modo}";
|
||||
lblResumo_OperacaoStatus.Content = $"Status {dados.StatusOperacao}" + (dados.StatusOperacao == AgroBase.Models.Enums.StatusOperacao.Aguardando ? $" ({dados.TempoAguardandoSeg.ToString("0")})" : "");
|
||||
lblResumo_StatusCarro.Content = $"Carro {dados.Trajetoria.StatusCarro}";
|
||||
lblResumo_TemperaturaGeral.Content = $"Temperatura {(dados.DadosPerformance.CPU_temp ?? 0).ToString("0.00")} °C";
|
||||
lblResumo_OperacaoDuracao.Content = $"Duração {dados.TempoDecorrido.ToString("HH:mm:ss")} / {dados.Trajetoria.TempoEstimadoOperacao}";
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI Resumo: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region POSICAO
|
||||
|
||||
public void AtualizarDadosTela_GNSS(AgroBase.Models.GPSModel dados, string? marker_id = null, double progresso = double.NaN)
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
bool dados_base = marker_id == VariaveisControleOperacao.BaseMarkerID;
|
||||
|
||||
lblGNSS_Posicao.Foreground = new SolidColorBrush(dados.Inicializado ? System.Windows.Media.Colors.Green : System.Windows.Media.Colors.Red);
|
||||
lblGNSS_Correcao.Content = $"Correção {dados.QualidadeFix} " +
|
||||
(dados.QualidadeFix == AgroBase.Models.Enums.TiposCorrecaoGPS.BaseFix ?
|
||||
(dados.OrientacaoReal.ToString("0.00") + "°") :
|
||||
((dados.Ntrip_ativado ? "N" : "B") + $" {dados.IdadeCorrecao.ToString("0.0")} s"));
|
||||
lblGNSS_Satelites.Content = $"Satélites {dados.NumeroSatelites} ({dados.PrecisaoCm.ToString("0.00")} cm)";
|
||||
lblGNSS_Altitude.Content = $"Altitude {dados.Altitude.ToString("0.00")} m";
|
||||
|
||||
if (dados_base)
|
||||
{
|
||||
sldGNSS_LeverArm.Visibility = Visibility.Hidden;
|
||||
if (double.IsNaN(progresso))
|
||||
{
|
||||
lblGNSS_Progresso.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
lblGNSS_Progresso.Visibility = Visibility.Visible;
|
||||
lblGNSS_Progresso.Content = $"{progresso.ToString("0.00")}%";
|
||||
}
|
||||
|
||||
bool gnss_fix_preciso = new List<AgroBase.Models.Enums.TiposCorrecaoGPS>() { AgroBase.Models.Enums.TiposCorrecaoGPS.RTKFixo, AgroBase.Models.Enums.TiposCorrecaoGPS.RTKFlutuante }.Contains(Variaveis.GpsService?.UltimaLeitura?.QualidadeFix ?? AgroBase.Models.Enums.TiposCorrecaoGPS.SemCorrecao);
|
||||
bool gnss_fixado = Variaveis.GpsService?.BaseFix?.CorrecaoAbsoluta ?? false;
|
||||
bool gnss_fixando = btnGNSS_FixarBase.Content.ToString() == "Parar";
|
||||
|
||||
btnGNSS_FixarBase.IsEnabled = (gnss_fix_preciso && !gnss_fixado) || gnss_fixando || gnss_fixado;
|
||||
btnGNSS_FixarBase.Content = gnss_fixado || !gnss_fixando ? "Fixar" : "Parar";
|
||||
}
|
||||
else
|
||||
{
|
||||
btnGNSS_FixarBase.IsEnabled = true;
|
||||
sldGNSS_LeverArm.Visibility = Visibility.Visible;
|
||||
lblGNSS_Progresso.Visibility = Visibility.Visible;
|
||||
lblGNSS_Progresso.Content = $"{(sldGNSS_LeverArm.Value * 10.0).ToString("0")} cm";
|
||||
lblGNSS_Progresso.Foreground = new SolidColorBrush(Math.Round(sldGNSS_LeverArm.Value * 10.0, 0) == Math.Round(dados.LeverArmLateral, 0) ? System.Windows.Media.Colors.Black : System.Windows.Media.Colors.Red);
|
||||
btnGNSS_FixarBase.Content = "Aplicar";
|
||||
}
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI GNSS: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void btnGNSS_FixarBase_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (VariaveisControleOperacao.BaseEmFoco)
|
||||
{
|
||||
if (!Variaveis.GpsService.BaseFix.FixLiberado)
|
||||
{
|
||||
if (Variaveis.GpsService.BaseFix.CorrecaoAbsoluta)
|
||||
{
|
||||
var res = MessageBox.Show("Mudar posição da base?", "Tem certeza que deseja fixar a posição da base novamente?", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (res == MessageBoxResult.Yes)
|
||||
{
|
||||
btnGNSS_FixarBase.Content = "Parar";
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = true;
|
||||
|
||||
Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
btnGNSS_FixarBase.Content = "Parar";
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
btnGNSS_FixarBase.Content = "Fixar";
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.Key == rover_id);
|
||||
if (rover.Value == null) return;
|
||||
|
||||
Variaveis.MostrarLog($"Atualizando dados da tela para o dispositivo {rover_id}");
|
||||
|
||||
AtualizarDadosTela_GNSS(rover.Value.Gps);
|
||||
AtualizarDadosTela_Heading(rover.Value.Gps.AnguloCarroDefinido, rover.Value.Modo == AgroBase.Models.Enums.ModoOperacao.Manual ? double.NaN : rover.Value.Trajetoria.AnguloCaminho);
|
||||
AtualizarDadosTela_IMU(rover.Value.IMU.InclinacaoLateral, rover.Value.IMU.InclinacaoFrontal);
|
||||
AtualizarDadostela_LIDAR(rover.Value.LivoxLidar.bboxes);
|
||||
VariaveisControleOperacao.EnviarComandoLeverArm(sldGNSS_LeverArm.Value * 10.0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMU
|
||||
|
||||
public void AtualizarDadosTela_IMU(double roll, double pitch)
|
||||
private void sldGNSS_LeverArm_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
|
||||
{
|
||||
IMU.RollDeg = roll;
|
||||
IMU.PitchDeg = pitch;
|
||||
lblGNSS_Progresso.Content = $"{(sldGNSS_LeverArm.Value * 10.0).ToString("0")} cm";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HEADING
|
||||
#region CONTROLE
|
||||
|
||||
public void AtualizarDadosTela_Heading(double headingRover, double headingCourse = double.NaN)
|
||||
public void AtualizarDadosTela_Controle(AgroBase.Models.OperacaoControleModel controle, double angulo, double velocidade, bool emergencia, bool pausa, bool refing)
|
||||
{
|
||||
HDG.Heading = headingRover;
|
||||
HDG.CourseHeading = headingCourse;
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
CTRL.AtualizarDadosControle(
|
||||
angSp: controle.Angulo,
|
||||
angCur: angulo,
|
||||
tipoMov: controle.TipoMovimento,
|
||||
velPct: controle.PercentualVelocidadeSP,
|
||||
velSp: controle.PercentualVelocidadeSPKmh,
|
||||
velKmh: velocidade,
|
||||
emg: emergencia,
|
||||
pause: pausa,
|
||||
refing: refing
|
||||
);
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI Controle: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PARAMETROS DA OPERACAO
|
||||
|
||||
public void AtualizarDadosTela_ParametrosOperacao(AgroBase.Models.Operacoes.OperacaoParametrosControleModel? controle)
|
||||
{
|
||||
if (controle == null) return;
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
txtParametros_VelCErvas.Text = controle.MovVelocidadeCErvasPercent.ToString();
|
||||
txtParametros_VelSErvas.Text = controle.MovVelocidadeSErvasPercent.ToString();
|
||||
txtParametros_AngMax.Text = controle.DirAnguloMaximo.ToString();
|
||||
txtParametros_RoiAtuacao.Text = controle.AtuPercentualInicioPulverizacao.ToString();
|
||||
txtParametros_AreaAtuacao.Text = controle.AtuAlturaAreaPulverizacao.ToString();
|
||||
txtParametros_PressaoLiha.Text = controle.AtuPressaoLinha.ToString();
|
||||
txtParametros_PctErvaOn.Text = controle.AtuPercentualErvasBicoOn.ToString();
|
||||
txtParametros_PctErvaOff.Text = controle.AtuPercentualErvasBicoOff.ToString();
|
||||
txtParametros_TempoOn.Text = controle.AtuDuracaoAtuacao.ToString();
|
||||
chbParametros_Pulverizador.IsChecked = controle.PulverizadorAutomatico;
|
||||
chbParametros_Frenagem.IsChecked = controle.FrenagemAutomatica;
|
||||
chbParametros_Sonar.IsChecked = controle.SonarAtivado;
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI Parametros da Operacao: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void btnParametros_Salvar_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var modo = (CTRL.TgManual.IsChecked ?? false) ? AgroBase.Models.Enums.ModoOperacao.Manual : AgroBase.Models.Enums.ModoOperacao.MapaGPS;
|
||||
|
||||
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
|
||||
{
|
||||
Modo = modo,
|
||||
Descricao = "Operacao da base",
|
||||
QtdCamerasSolo = 1,
|
||||
QtdBicos = 3,
|
||||
CapacidadeReservatorio = 45,
|
||||
|
||||
Controle = new AgroBase.Models.Operacoes.OperacaoParametrosControleModel()
|
||||
{
|
||||
MovimentoAutomatico = modo != AgroBase.Models.Enums.ModoOperacao.Manual,
|
||||
SonarAtivado = chbParametros_Sonar.IsChecked ?? false,
|
||||
FrenagemAutomatica = chbParametros_Frenagem.IsChecked ?? false,
|
||||
MovVelocidadeCErvasPercent = int.Parse(txtParametros_VelCErvas.Text),
|
||||
MovVelocidadeSErvasPercent = int.Parse(txtParametros_VelSErvas.Text),
|
||||
|
||||
DirAnguloMaximo = int.Parse(txtParametros_AngMax.Text),
|
||||
DirTipoMovimento = AgroBase.Models.Enums.TiposControladorDirecional.MPC,
|
||||
DirVelocidadeMovimento = 50,
|
||||
|
||||
PulverizadorAutomatico = chbParametros_Pulverizador.IsChecked ?? false,
|
||||
AtuPercentualErvasBicoOn = double.Parse(txtParametros_PctErvaOn.Text),
|
||||
AtuPercentualErvasBicoOff = double.Parse(txtParametros_PctErvaOff.Text),
|
||||
AtuDuracaoAtuacao = int.Parse(txtParametros_TempoOn.Text),
|
||||
AtuAlturaAreaPulverizacao = double.Parse(txtParametros_AreaAtuacao.Text),
|
||||
AtuPercentualInicioPulverizacao = double.Parse(txtParametros_RoiAtuacao.Text),
|
||||
AtuPressaoLinha = double.Parse(txtParametros_PressaoLiha.Text),
|
||||
},
|
||||
|
||||
ModulosMandatorios = new List<AgroBase.Models.OperacaoModulosMandatoriosModel>(),
|
||||
ParametrosMandatorios = new List<AgroBase.Models.OperacaoParametrosMandatoriosModel>(),
|
||||
|
||||
RuasPercorrer = MAP.RuasMapaCarregado.Where(x => x.Selected).Select(x => x.Id).ToList(),
|
||||
Mapa = MAP.CriarDadosMapa()
|
||||
});
|
||||
}
|
||||
|
||||
private void btnParametros_Atualizar_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AtualizarDadosTela_ParametrosOperacao(VariaveisControleOperacao.RoverEmFoco?.Controle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -254,15 +600,16 @@ namespace OperationControl.Windows
|
|||
|
||||
private void MAP_MarkerClicked(object? sender, MapMarkerManager.MarkerClickedEventArgs e)
|
||||
{
|
||||
Variaveis.MostrarLog($"Rover em foco: {e.MarkerId}");
|
||||
if (string.IsNullOrEmpty(e.MarkerId))
|
||||
{
|
||||
LimparDadosTela_Telemetria();
|
||||
Variaveis.MostrarLog($"Sem rover em foco");
|
||||
LimparDadosTela_Telemetria(e.MarkerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
VariaveisControleOperacao.SelectedRoverId = e.MarkerId;
|
||||
AtualizarDadosTela_Telemetria(e.MarkerId);
|
||||
Variaveis.MostrarLog($"Rover em foco: {e.MarkerId}");
|
||||
int idx = cmbDispositivo.Items.IndexOf(e.MarkerId);
|
||||
cmbDispositivo.SelectedIndex = idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,6 +618,156 @@ namespace OperationControl.Windows
|
|||
Variaveis.MostrarLog($"Rua clicada: {e.StreetId}. Ruas selecionadas: {string.Join(",", e.SelectedStreetsIds)}");
|
||||
}
|
||||
|
||||
private void AtualizarDadosTela_Mapa(AgroBase.Models.OperacaoSensoriamentoLogTrajetoriaModel Trajetoria)
|
||||
{
|
||||
lblMapaInfo_Debug.Content = $"" +
|
||||
$"Próximo Ponto: {Trajetoria.ProximoPonto.idxPonto} | " +
|
||||
(Trajetoria.ProximoPonto.Aproximando ? "Aproximando" : "Afastando") + " | " +
|
||||
$"Distância próximo ponto: {Trajetoria.ProximoPonto.DistanciaAtual.ToString("0.00")} m | " +
|
||||
$"Distância ponto anterior: {Trajetoria.PontoAtual.DistanciaAtual.ToString("0.00")} m | " +
|
||||
$"Corredor: " + (Trajetoria.CorredorAtual.Dentro ? "Dentro" : "Fora") + " | " +
|
||||
$"Margem: " + (Trajetoria.NaMargemDoCorredor ? "Sim" : "Não") + " | " +
|
||||
$"Disância Esquerda: {(Trajetoria.DistanciaEsquerda * 100.0).ToString("0.00")} cm | " +
|
||||
$"Distância Direita: {(Trajetoria.DistanciaDireita * 100.0).ToString("0.00")} cm | " +
|
||||
$"Status: {Trajetoria.StatusCarro}";
|
||||
|
||||
double erroLateral = (Trajetoria.DistanciaEsquerda - Trajetoria.DistanciaDireita) / 2.0 * 100.0;
|
||||
AtualizarDadosTela_IMU(erro_lateral: erroLateral);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HEADING
|
||||
|
||||
public void AtualizarDadosTela_Heading(double headingRover, double headingCourse = double.NaN)
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
HDG.Heading = headingRover;
|
||||
HDG.CourseHeading = headingCourse;
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI Heading: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMU
|
||||
|
||||
public void AtualizarDadosTela_IMU(double? roll = null, double? pitch = null, double? erro_lateral = null)
|
||||
{
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (roll != null) IMU.RollDeg = (double)roll;
|
||||
if (pitch != null) IMU.PitchDeg = (double)pitch;
|
||||
if (erro_lateral != null) IMU.LateralError = (double)erro_lateral;
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI IMU: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CAMERA FRONTAL
|
||||
|
||||
private void IniciarStreamCameraFrontal()
|
||||
{
|
||||
var path = @"streams\camera_frontal.sdp";
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
string stream =
|
||||
"v=0\r\n" +
|
||||
"o=- 0 0 IN IP4 0.0.0.0\r\n" +
|
||||
"s=OAK H264\r\n" +
|
||||
"c=IN IP4 0.0.0.0\r\n" +
|
||||
"t=0 0\r\n" +
|
||||
"m=video 5000 RTP/AVP 96\r\n" +
|
||||
"a=rtpmap:96 H264/90000\r\n" +
|
||||
"a=fmtp:96 packetization-mode=1\r\n";
|
||||
File.WriteAllText(path, stream);
|
||||
}
|
||||
|
||||
_mediaFront?.Dispose(); // limpa antigo, se existir
|
||||
_mediaFront = new Media(_libVLC, path, FromType.FromPath);
|
||||
// _mediaFront.AddOption(":network-caching=150"); // se quiser por arquivo
|
||||
|
||||
_playerFront.Play(_mediaFront);
|
||||
|
||||
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, true);
|
||||
}
|
||||
|
||||
private void PararStreamCameraFrontal(bool finalizar = false)
|
||||
{
|
||||
_playerFront?.Stop();
|
||||
|
||||
if (finalizar)
|
||||
{
|
||||
_mediaFront?.Dispose();
|
||||
_mediaFront = null;
|
||||
_playerFront?.Dispose();
|
||||
_playerFront = null;
|
||||
}
|
||||
|
||||
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CAMERA ERVAS
|
||||
|
||||
private void IniciarStreamCameraErvas()
|
||||
{
|
||||
var path = @"streams\camera_ervas.sdp";
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
string stream =
|
||||
"v=0\r\n" +
|
||||
"o=- 0 0 IN IP4 0.0.0.0\r\n" +
|
||||
"s=OAK H264\r\n" +
|
||||
"c=IN IP4 0.0.0.0\r\n" +
|
||||
"t=0 0\r\n" +
|
||||
"m=video 5002 RTP/AVP 96\r\n" + // <- porta 5001
|
||||
"a=rtpmap:96 H264/90000\r\n" +
|
||||
"a=fmtp:96 packetization-mode=1\r\n";
|
||||
File.WriteAllText(path, stream);
|
||||
}
|
||||
|
||||
_mediaWeed?.Dispose();
|
||||
_mediaWeed = new Media(_libVLC, path, FromType.FromPath);
|
||||
// _mediaWeed.AddOption(":network-caching=150");
|
||||
|
||||
_playerWeed.Play(_mediaWeed);
|
||||
|
||||
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, true);
|
||||
}
|
||||
|
||||
private void PararStreamCameraErvas(bool finalizar = false)
|
||||
{
|
||||
_playerWeed?.Stop();
|
||||
|
||||
if (finalizar)
|
||||
{
|
||||
_mediaWeed?.Dispose();
|
||||
_mediaWeed = null;
|
||||
_playerWeed?.Dispose();
|
||||
_playerWeed = null;
|
||||
}
|
||||
|
||||
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PULVERIZADOR
|
||||
|
|
@ -282,85 +779,26 @@ namespace OperationControl.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
#region POSICAO
|
||||
|
||||
public void AtualizarDadosTela_GNSS(AgroBase.Models.GPSModel dados, string marker_id = null, double progresso = double.NaN)
|
||||
{
|
||||
lblGNSS_Posicao.Foreground = dados.Inicializado ? new SolidColorBrush(System.Windows.Media.Colors.Green) : new SolidColorBrush(System.Windows.Media.Colors.Red);
|
||||
lblGNSS_Correcao.Content = $"Correção {dados.QualidadeFix} " +
|
||||
(dados.QualidadeFix == AgroBase.Models.Enums.TiposCorrecaoGPS.BaseFix ?
|
||||
(dados.OrientacaoReal.ToString("0.00") + "°") :
|
||||
((dados.Ntrip_ativado ? "N" : "B") + $" {dados.IdadeCorrecao.ToString("0.0")} s"));
|
||||
lblGNSS_Satelites.Content = $"Satélites {dados.NumeroSatelites} ({dados.PrecisaoCm.ToString("0.00")} cm)";
|
||||
lblGNSS_Altitude.Content = $"Altitude {dados.Altitude.ToString("0.00")} m";
|
||||
|
||||
if (double.IsNaN(progresso))
|
||||
{
|
||||
lblGNSS_Progresso.Visibility = Visibility.Hidden;
|
||||
btnGNSS_FixarBase.Visibility = Visibility.Hidden;
|
||||
}
|
||||
else
|
||||
{
|
||||
lblGNSS_Progresso.Visibility = Visibility.Visible;
|
||||
btnGNSS_FixarBase.Visibility = Visibility.Visible;
|
||||
|
||||
lblGNSS_Progresso.Content = $"{progresso.ToString("0.00")}%";
|
||||
if ((Variaveis.GpsService?.BaseFix?.CorrecaoAbsoluta ?? false) && Variaveis.GpsService.BaseFix.FixLiberado && btnGNSS_FixarBase.Content.ToString() == "Parar")
|
||||
{
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = false;
|
||||
btnGNSS_FixarBase.Content = "Fixar";
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(marker_id))
|
||||
MAP.markers.UpdateMarkerPosition(marker_id, dados.Latitude, dados.Longitude, dados.OrientacaoReal);
|
||||
}
|
||||
|
||||
|
||||
private void btnGNSS_FixarBase_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!Variaveis.GpsService.BaseFix.FixLiberado)
|
||||
{
|
||||
if (Variaveis.GpsService.BaseFix.CorrecaoAbsoluta)
|
||||
{
|
||||
var res = MessageBox.Show("Mudar posição da base?", "Tem certeza que deseja fixar a posição da base novamente?", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
if (res == MessageBoxResult.Yes)
|
||||
{
|
||||
btnGNSS_FixarBase.Content = "Parar";
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = true;
|
||||
|
||||
Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
btnGNSS_FixarBase.Content = "Parar";
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
btnGNSS_FixarBase.Content = "Fixar";
|
||||
Variaveis.GpsService.BaseFix.FixLiberado = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LIDAR
|
||||
|
||||
public void AtualizarDadostela_LIDAR(List<AgroBase.Models.LivoxBboxModel> bboxes)
|
||||
{
|
||||
BBoxes3D.SetBboxes(bboxes);
|
||||
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
BBoxes3D.SetBboxes(bboxes);
|
||||
}
|
||||
catch (Exception exUi)
|
||||
{
|
||||
Variaveis.MostrarLog($"Erro ao atualizar UI Lidar: {exUi.Message}");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/FFmpeg.AutoGen.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/FFmpeg.AutoGen.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GLib-2.0.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GLib-2.0.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GObject-2.0.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GObject-2.0.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/Gst-1.0.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/Gst-1.0.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GstBase-1.0.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GstBase-1.0.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GstVideo-1.0.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/GstVideo-1.0.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/LibVLCSharp.WPF.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/LibVLCSharp.WPF.dll (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/LibVLCSharp.dll (Stored with Git LFS)
Normal file
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/LibVLCSharp.dll (Stored with Git LFS)
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/OperationControl.dll (Stored with Git LFS)
BIN
AgroBase/OperationControl/bin/Debug/net8.0-windows7.0/OperationControl.dll (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
from .modeling import *
|
||||
from ._deeplab import convert_to_separable_conv
|
||||
|
|
@ -1,178 +0,0 @@
|
|||
import torch
|
||||
from torch import nn
|
||||
from torch.nn import functional as F
|
||||
|
||||
from .utils import _SimpleSegmentationModel
|
||||
|
||||
|
||||
__all__ = ["DeepLabV3"]
|
||||
|
||||
|
||||
class DeepLabV3(_SimpleSegmentationModel):
|
||||
"""
|
||||
Implements DeepLabV3 model from
|
||||
`"Rethinking Atrous Convolution for Semantic Image Segmentation"
|
||||
<https://arxiv.org/abs/1706.05587>`_.
|
||||
|
||||
Arguments:
|
||||
backbone (nn.Module): the network used to compute the features for the model.
|
||||
The backbone should return an OrderedDict[Tensor], with the key being
|
||||
"out" for the last feature map used, and "aux" if an auxiliary classifier
|
||||
is used.
|
||||
classifier (nn.Module): module that takes the "out" element returned from
|
||||
the backbone and returns a dense prediction.
|
||||
aux_classifier (nn.Module, optional): auxiliary classifier used during training
|
||||
"""
|
||||
pass
|
||||
|
||||
class DeepLabHeadV3Plus(nn.Module):
|
||||
def __init__(self, in_channels, low_level_channels, num_classes, aspp_dilate=[12, 24, 36]):
|
||||
super(DeepLabHeadV3Plus, self).__init__()
|
||||
self.project = nn.Sequential(
|
||||
nn.Conv2d(low_level_channels, 48, 1, bias=False),
|
||||
nn.BatchNorm2d(48),
|
||||
nn.ReLU(inplace=True),
|
||||
)
|
||||
|
||||
self.aspp = ASPP(in_channels, aspp_dilate)
|
||||
|
||||
self.classifier = nn.Sequential(
|
||||
nn.Conv2d(304, 256, 3, padding=1, bias=False),
|
||||
nn.BatchNorm2d(256),
|
||||
nn.ReLU(inplace=True),
|
||||
nn.Conv2d(256, num_classes, 1)
|
||||
)
|
||||
self._init_weight()
|
||||
|
||||
def forward(self, feature):
|
||||
low_level_feature = self.project( feature['low_level'] )
|
||||
output_feature = self.aspp(feature['out'])
|
||||
output_feature = F.interpolate(output_feature, size=low_level_feature.shape[2:], mode='bilinear', align_corners=False)
|
||||
return self.classifier( torch.cat( [ low_level_feature, output_feature ], dim=1 ) )
|
||||
|
||||
def _init_weight(self):
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight)
|
||||
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
|
||||
nn.init.constant_(m.weight, 1)
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
class DeepLabHead(nn.Module):
|
||||
def __init__(self, in_channels, num_classes, aspp_dilate=[12, 24, 36]):
|
||||
super(DeepLabHead, self).__init__()
|
||||
|
||||
self.classifier = nn.Sequential(
|
||||
ASPP(in_channels, aspp_dilate),
|
||||
nn.Conv2d(256, 256, 3, padding=1, bias=False),
|
||||
nn.BatchNorm2d(256),
|
||||
nn.ReLU(inplace=True),
|
||||
nn.Conv2d(256, num_classes, 1)
|
||||
)
|
||||
self._init_weight()
|
||||
|
||||
def forward(self, feature):
|
||||
return self.classifier( feature['out'] )
|
||||
|
||||
def _init_weight(self):
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight)
|
||||
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
|
||||
nn.init.constant_(m.weight, 1)
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
class AtrousSeparableConvolution(nn.Module):
|
||||
""" Atrous Separable Convolution
|
||||
"""
|
||||
def __init__(self, in_channels, out_channels, kernel_size,
|
||||
stride=1, padding=0, dilation=1, bias=True):
|
||||
super(AtrousSeparableConvolution, self).__init__()
|
||||
self.body = nn.Sequential(
|
||||
# Separable Conv
|
||||
nn.Conv2d( in_channels, in_channels, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, bias=bias, groups=in_channels ),
|
||||
# PointWise Conv
|
||||
nn.Conv2d( in_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=bias),
|
||||
)
|
||||
|
||||
self._init_weight()
|
||||
|
||||
def forward(self, x):
|
||||
return self.body(x)
|
||||
|
||||
def _init_weight(self):
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight)
|
||||
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
|
||||
nn.init.constant_(m.weight, 1)
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
class ASPPConv(nn.Sequential):
|
||||
def __init__(self, in_channels, out_channels, dilation):
|
||||
modules = [
|
||||
nn.Conv2d(in_channels, out_channels, 3, padding=dilation, dilation=dilation, bias=False),
|
||||
nn.BatchNorm2d(out_channels),
|
||||
nn.ReLU(inplace=True)
|
||||
]
|
||||
super(ASPPConv, self).__init__(*modules)
|
||||
|
||||
class ASPPPooling(nn.Sequential):
|
||||
def __init__(self, in_channels, out_channels):
|
||||
super(ASPPPooling, self).__init__(
|
||||
nn.AdaptiveAvgPool2d(1),
|
||||
nn.Conv2d(in_channels, out_channels, 1, bias=False),
|
||||
nn.BatchNorm2d(out_channels),
|
||||
nn.ReLU(inplace=True))
|
||||
|
||||
def forward(self, x):
|
||||
size = x.shape[-2:]
|
||||
x = super(ASPPPooling, self).forward(x)
|
||||
return F.interpolate(x, size=size, mode='bilinear', align_corners=False)
|
||||
|
||||
class ASPP(nn.Module):
|
||||
def __init__(self, in_channels, atrous_rates):
|
||||
super(ASPP, self).__init__()
|
||||
out_channels = 256
|
||||
modules = []
|
||||
modules.append(nn.Sequential(
|
||||
nn.Conv2d(in_channels, out_channels, 1, bias=False),
|
||||
nn.BatchNorm2d(out_channels),
|
||||
nn.ReLU(inplace=True)))
|
||||
|
||||
rate1, rate2, rate3 = tuple(atrous_rates)
|
||||
modules.append(ASPPConv(in_channels, out_channels, rate1))
|
||||
modules.append(ASPPConv(in_channels, out_channels, rate2))
|
||||
modules.append(ASPPConv(in_channels, out_channels, rate3))
|
||||
modules.append(ASPPPooling(in_channels, out_channels))
|
||||
|
||||
self.convs = nn.ModuleList(modules)
|
||||
|
||||
self.project = nn.Sequential(
|
||||
nn.Conv2d(5 * out_channels, out_channels, 1, bias=False),
|
||||
nn.BatchNorm2d(out_channels),
|
||||
nn.ReLU(inplace=True),
|
||||
nn.Dropout(0.1),)
|
||||
|
||||
def forward(self, x):
|
||||
res = []
|
||||
for conv in self.convs:
|
||||
res.append(conv(x))
|
||||
res = torch.cat(res, dim=1)
|
||||
return self.project(res)
|
||||
|
||||
|
||||
|
||||
def convert_to_separable_conv(module):
|
||||
new_module = module
|
||||
if isinstance(module, nn.Conv2d) and module.kernel_size[0]>1:
|
||||
new_module = AtrousSeparableConvolution(module.in_channels,
|
||||
module.out_channels,
|
||||
module.kernel_size,
|
||||
module.stride,
|
||||
module.padding,
|
||||
module.dilation,
|
||||
module.bias)
|
||||
for name, child in module.named_children():
|
||||
new_module.add_module(name, convert_to_separable_conv(child))
|
||||
return new_module
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
from . import resnet
|
||||
from . import mobilenetv2
|
||||
from . import hrnetv2
|
||||
from . import xception
|
||||
|
|
@ -1,345 +0,0 @@
|
|||
import torch
|
||||
from torch import nn
|
||||
import torch.nn.functional as F
|
||||
import os
|
||||
|
||||
__all__ = ['HRNet', 'hrnetv2_48', 'hrnetv2_32']
|
||||
|
||||
# Checkpoint path of pre-trained backbone (edit to your path). Download backbone pretrained model hrnetv2-32 @
|
||||
# https://drive.google.com/file/d/1NxCK7Zgn5PmeS7W1jYLt5J9E0RRZ2oyF/view?usp=sharing .Personally, I added the backbone
|
||||
# weights to the folder /checkpoints
|
||||
|
||||
model_urls = {
|
||||
'hrnetv2_32': './checkpoints/model_best_epoch96_edit.pth',
|
||||
'hrnetv2_48': None
|
||||
}
|
||||
|
||||
|
||||
def check_pth(arch):
|
||||
CKPT_PATH = model_urls[arch]
|
||||
if os.path.exists(CKPT_PATH):
|
||||
print(f"Backbone HRNet Pretrained weights at: {CKPT_PATH}, only usable for HRNetv2-32")
|
||||
else:
|
||||
print("No backbone checkpoint found for HRNetv2, please set pretrained=False when calling model")
|
||||
return CKPT_PATH
|
||||
# HRNetv2-48 not available yet, but you can train the whole model from scratch.
|
||||
|
||||
|
||||
class Bottleneck(nn.Module):
|
||||
expansion = 4
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None):
|
||||
super(Bottleneck, self).__init__()
|
||||
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(planes)
|
||||
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(planes)
|
||||
self.conv3 = nn.Conv2d(planes, planes * self.expansion, kernel_size=1, bias=False)
|
||||
self.bn3 = nn.BatchNorm2d(planes * self.expansion)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.downsample = downsample
|
||||
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
out = self.relu(out)
|
||||
out = self.conv3(out)
|
||||
out = self.bn3(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class BasicBlock(nn.Module):
|
||||
expansion = 1
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None):
|
||||
super(BasicBlock, self).__init__()
|
||||
self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(planes)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.conv2 = nn.Conv2d(inplanes, planes, kernel_size=3, stride=1, padding=1, bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(planes)
|
||||
self.downsample = downsample
|
||||
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class StageModule(nn.Module):
|
||||
def __init__(self, stage, output_branches, c):
|
||||
super(StageModule, self).__init__()
|
||||
|
||||
self.number_of_branches = stage # number of branches is equivalent to the stage configuration.
|
||||
self.output_branches = output_branches
|
||||
|
||||
self.branches = nn.ModuleList()
|
||||
|
||||
# Note: Resolution + Number of channels maintains the same throughout respective branch.
|
||||
for i in range(self.number_of_branches): # Stage scales with the number of branches. Ex: Stage 2 -> 2 branch
|
||||
channels = c * (2 ** i) # Scale channels by 2x for branch with lower resolution,
|
||||
|
||||
# Paper does x4 basic block for each forward sequence in each branch (x4 basic block considered as a block)
|
||||
branch = nn.Sequential(*[BasicBlock(channels, channels) for _ in range(4)])
|
||||
|
||||
self.branches.append(branch) # list containing all forward sequence of individual branches.
|
||||
|
||||
# For each branch requires repeated fusion with all other branches after passing through x4 basic blocks.
|
||||
self.fuse_layers = nn.ModuleList()
|
||||
|
||||
for branch_output_number in range(self.output_branches):
|
||||
|
||||
self.fuse_layers.append(nn.ModuleList())
|
||||
|
||||
for branch_number in range(self.number_of_branches):
|
||||
if branch_number == branch_output_number:
|
||||
self.fuse_layers[-1].append(nn.Sequential()) # Used in place of "None" because it is callable
|
||||
elif branch_number > branch_output_number:
|
||||
self.fuse_layers[-1].append(nn.Sequential(
|
||||
nn.Conv2d(c * (2 ** branch_number), c * (2 ** branch_output_number), kernel_size=1, stride=1,
|
||||
bias=False),
|
||||
nn.BatchNorm2d(c * (2 ** branch_output_number), eps=1e-05, momentum=0.1, affine=True,
|
||||
track_running_stats=True),
|
||||
nn.Upsample(scale_factor=(2.0 ** (branch_number - branch_output_number)), mode='nearest'),
|
||||
))
|
||||
elif branch_number < branch_output_number:
|
||||
downsampling_fusion = []
|
||||
for _ in range(branch_output_number - branch_number - 1):
|
||||
downsampling_fusion.append(nn.Sequential(
|
||||
nn.Conv2d(c * (2 ** branch_number), c * (2 ** branch_number), kernel_size=3, stride=2,
|
||||
padding=1,
|
||||
bias=False),
|
||||
nn.BatchNorm2d(c * (2 ** branch_number), eps=1e-05, momentum=0.1, affine=True,
|
||||
track_running_stats=True),
|
||||
nn.ReLU(inplace=True),
|
||||
))
|
||||
downsampling_fusion.append(nn.Sequential(
|
||||
nn.Conv2d(c * (2 ** branch_number), c * (2 ** branch_output_number), kernel_size=3,
|
||||
stride=2, padding=1,
|
||||
bias=False),
|
||||
nn.BatchNorm2d(c * (2 ** branch_output_number), eps=1e-05, momentum=0.1, affine=True,
|
||||
track_running_stats=True),
|
||||
))
|
||||
self.fuse_layers[-1].append(nn.Sequential(*downsampling_fusion))
|
||||
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
|
||||
def forward(self, x):
|
||||
|
||||
# input to each stage is a list of inputs for each branch
|
||||
x = [branch(branch_input) for branch, branch_input in zip(self.branches, x)]
|
||||
|
||||
x_fused = []
|
||||
for branch_output_index in range(
|
||||
self.output_branches): # Amount of output branches == total length of fusion layers
|
||||
for input_index in range(self.number_of_branches): # The inputs of other branches to be fused.
|
||||
if input_index == 0:
|
||||
x_fused.append(self.fuse_layers[branch_output_index][input_index](x[input_index]))
|
||||
else:
|
||||
x_fused[branch_output_index] = x_fused[branch_output_index] + self.fuse_layers[branch_output_index][
|
||||
input_index](x[input_index])
|
||||
|
||||
# After fusing all streams together, you will need to pass the fused layers
|
||||
for i in range(self.output_branches):
|
||||
x_fused[i] = self.relu(x_fused[i])
|
||||
|
||||
return x_fused # returning a list of fused outputs
|
||||
|
||||
|
||||
class HRNet(nn.Module):
|
||||
def __init__(self, c=48, num_blocks=[1, 4, 3], num_classes=1000):
|
||||
super(HRNet, self).__init__()
|
||||
|
||||
# Stem:
|
||||
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=2, padding=1, bias=False)
|
||||
self.bn1 = nn.BatchNorm2d(64, eps=1e-05, affine=True, track_running_stats=True)
|
||||
self.conv2 = nn.Conv2d(64, 64, kernel_size=3, stride=2, padding=1, bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(64, eps=1e-05, affine=True, track_running_stats=True)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
|
||||
# Stage 1:
|
||||
downsample = nn.Sequential(
|
||||
nn.Conv2d(64, 256, kernel_size=1, stride=1, bias=False),
|
||||
nn.BatchNorm2d(256, eps=1e-05, affine=True, track_running_stats=True),
|
||||
)
|
||||
# Note that bottleneck module will expand the output channels according to the output channels*block.expansion
|
||||
bn_expansion = Bottleneck.expansion # The channel expansion is set in the bottleneck class.
|
||||
self.layer1 = nn.Sequential(
|
||||
Bottleneck(64, 64, downsample=downsample), # Input is 64 for first module connection
|
||||
Bottleneck(bn_expansion * 64, 64),
|
||||
Bottleneck(bn_expansion * 64, 64),
|
||||
Bottleneck(bn_expansion * 64, 64),
|
||||
)
|
||||
|
||||
# Transition 1 - Creation of the first two branches (one full and one half resolution)
|
||||
# Need to transition into high resolution stream and mid resolution stream
|
||||
self.transition1 = nn.ModuleList([
|
||||
nn.Sequential(
|
||||
nn.Conv2d(256, c, kernel_size=3, stride=1, padding=1, bias=False),
|
||||
nn.BatchNorm2d(c, eps=1e-05, affine=True, track_running_stats=True),
|
||||
nn.ReLU(inplace=True),
|
||||
),
|
||||
nn.Sequential(nn.Sequential( # Double Sequential to fit with official pretrained weights
|
||||
nn.Conv2d(256, c * 2, kernel_size=3, stride=2, padding=1, bias=False),
|
||||
nn.BatchNorm2d(c * 2, eps=1e-05, affine=True, track_running_stats=True),
|
||||
nn.ReLU(inplace=True),
|
||||
)),
|
||||
])
|
||||
|
||||
# Stage 2:
|
||||
number_blocks_stage2 = num_blocks[0]
|
||||
self.stage2 = nn.Sequential(
|
||||
*[StageModule(stage=2, output_branches=2, c=c) for _ in range(number_blocks_stage2)])
|
||||
|
||||
# Transition 2 - Creation of the third branch (1/4 resolution)
|
||||
self.transition2 = self._make_transition_layers(c, transition_number=2)
|
||||
|
||||
# Stage 3:
|
||||
number_blocks_stage3 = num_blocks[1] # number blocks you want to create before fusion
|
||||
self.stage3 = nn.Sequential(
|
||||
*[StageModule(stage=3, output_branches=3, c=c) for _ in range(number_blocks_stage3)])
|
||||
|
||||
# Transition - Creation of the fourth branch (1/8 resolution)
|
||||
self.transition3 = self._make_transition_layers(c, transition_number=3)
|
||||
|
||||
# Stage 4:
|
||||
number_blocks_stage4 = num_blocks[2] # number blocks you want to create before fusion
|
||||
self.stage4 = nn.Sequential(
|
||||
*[StageModule(stage=4, output_branches=4, c=c) for _ in range(number_blocks_stage4)])
|
||||
|
||||
# Classifier (extra module if want to use for classification):
|
||||
# pool, reduce dimensionality, flatten, connect to linear layer for classification:
|
||||
out_channels = sum([c * 2 ** i for i in range(len(num_blocks)+1)]) # total output channels of HRNetV2
|
||||
pool_feature_map = 8
|
||||
self.bn_classifier = nn.Sequential(
|
||||
nn.Conv2d(out_channels, out_channels // 4, kernel_size=1, bias=False),
|
||||
nn.BatchNorm2d(out_channels // 4, eps=1e-05, affine=True, track_running_stats=True),
|
||||
nn.ReLU(inplace=True),
|
||||
nn.AdaptiveAvgPool2d(pool_feature_map),
|
||||
nn.Flatten(),
|
||||
nn.Linear(pool_feature_map * pool_feature_map * (out_channels // 4), num_classes),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _make_transition_layers(c, transition_number):
|
||||
return nn.Sequential(
|
||||
nn.Conv2d(c * (2 ** (transition_number - 1)), c * (2 ** transition_number), kernel_size=3, stride=2,
|
||||
padding=1, bias=False),
|
||||
nn.BatchNorm2d(c * (2 ** transition_number), eps=1e-05, affine=True,
|
||||
track_running_stats=True),
|
||||
nn.ReLU(inplace=True),
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
# Stem:
|
||||
x = self.conv1(x)
|
||||
x = self.bn1(x)
|
||||
x = self.relu(x)
|
||||
x = self.conv2(x)
|
||||
x = self.bn2(x)
|
||||
x = self.relu(x)
|
||||
|
||||
# Stage 1
|
||||
x = self.layer1(x)
|
||||
x = [trans(x) for trans in self.transition1] # split to 2 branches, form a list.
|
||||
|
||||
# Stage 2
|
||||
x = self.stage2(x)
|
||||
x.append(self.transition2(x[-1]))
|
||||
|
||||
# Stage 3
|
||||
x = self.stage3(x)
|
||||
x.append(self.transition3(x[-1]))
|
||||
|
||||
# Stage 4
|
||||
x = self.stage4(x)
|
||||
|
||||
# HRNetV2 Example: (follow paper, upsample via bilinear interpolation and to highest resolution size)
|
||||
output_h, output_w = x[0].size(2), x[0].size(3) # Upsample to size of highest resolution stream
|
||||
x1 = F.interpolate(x[1], size=(output_h, output_w), mode='bilinear', align_corners=False)
|
||||
x2 = F.interpolate(x[2], size=(output_h, output_w), mode='bilinear', align_corners=False)
|
||||
x3 = F.interpolate(x[3], size=(output_h, output_w), mode='bilinear', align_corners=False)
|
||||
|
||||
# Upsampling all the other resolution streams and then concatenate all (rather than adding/fusing like HRNetV1)
|
||||
x = torch.cat([x[0], x1, x2, x3], dim=1)
|
||||
x = self.bn_classifier(x)
|
||||
return x
|
||||
|
||||
|
||||
def _hrnet(arch, channels, num_blocks, pretrained, progress, **kwargs):
|
||||
model = HRNet(channels, num_blocks, **kwargs)
|
||||
if pretrained:
|
||||
CKPT_PATH = check_pth(arch)
|
||||
checkpoint = torch.load(CKPT_PATH)
|
||||
model.load_state_dict(checkpoint['state_dict'])
|
||||
return model
|
||||
|
||||
|
||||
def hrnetv2_48(pretrained=False, progress=True, number_blocks=[1, 4, 3], **kwargs):
|
||||
w_channels = 48
|
||||
return _hrnet('hrnetv2_48', w_channels, number_blocks, pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def hrnetv2_32(pretrained=False, progress=True, number_blocks=[1, 4, 3], **kwargs):
|
||||
w_channels = 32
|
||||
return _hrnet('hrnetv2_32', w_channels, number_blocks, pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
try:
|
||||
CKPT_PATH = os.path.join(os.path.abspath("."), '../../checkpoints/hrnetv2_32_model_best_epoch96.pth')
|
||||
print("--- Running file as MAIN ---")
|
||||
print(f"Backbone HRNET Pretrained weights as __main__ at: {CKPT_PATH}")
|
||||
except:
|
||||
print("No backbone checkpoint found for HRNetv2, please set pretrained=False when calling model")
|
||||
|
||||
# Models
|
||||
model = hrnetv2_32(pretrained=True)
|
||||
#model = hrnetv2_48(pretrained=False)
|
||||
|
||||
if torch.cuda.is_available():
|
||||
torch.backends.cudnn.deterministic = True
|
||||
device = torch.device('cuda')
|
||||
else:
|
||||
device = torch.device('cpu')
|
||||
model.to(device)
|
||||
in_ = torch.ones(1, 3, 768, 768).to(device)
|
||||
y = model(in_)
|
||||
print(y.shape)
|
||||
|
||||
# Calculate total number of parameters:
|
||||
# pytorch_total_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
|
||||
# print(pytorch_total_params)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
from torch import nn
|
||||
try: # for torchvision<0.4
|
||||
from torchvision.models.utils import load_state_dict_from_url
|
||||
except: # for torchvision>=0.4
|
||||
from torch.hub import load_state_dict_from_url
|
||||
import torch.nn.functional as F
|
||||
|
||||
__all__ = ['MobileNetV2', 'mobilenet_v2']
|
||||
|
||||
|
||||
model_urls = {
|
||||
'mobilenet_v2': 'https://download.pytorch.org/models/mobilenet_v2-b0353104.pth',
|
||||
}
|
||||
|
||||
|
||||
def _make_divisible(v, divisor, min_value=None):
|
||||
"""
|
||||
This function is taken from the original tf repo.
|
||||
It ensures that all layers have a channel number that is divisible by 8
|
||||
It can be seen here:
|
||||
https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
|
||||
:param v:
|
||||
:param divisor:
|
||||
:param min_value:
|
||||
:return:
|
||||
"""
|
||||
if min_value is None:
|
||||
min_value = divisor
|
||||
new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
|
||||
# Make sure that round down does not go down by more than 10%.
|
||||
if new_v < 0.9 * v:
|
||||
new_v += divisor
|
||||
return new_v
|
||||
|
||||
|
||||
class ConvBNReLU(nn.Sequential):
|
||||
def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, dilation=1, groups=1):
|
||||
#padding = (kernel_size - 1) // 2
|
||||
super(ConvBNReLU, self).__init__(
|
||||
nn.Conv2d(in_planes, out_planes, kernel_size, stride, 0, dilation=dilation, groups=groups, bias=False),
|
||||
nn.BatchNorm2d(out_planes),
|
||||
nn.ReLU6(inplace=True)
|
||||
)
|
||||
|
||||
def fixed_padding(kernel_size, dilation):
|
||||
kernel_size_effective = kernel_size + (kernel_size - 1) * (dilation - 1)
|
||||
pad_total = kernel_size_effective - 1
|
||||
pad_beg = pad_total // 2
|
||||
pad_end = pad_total - pad_beg
|
||||
return (pad_beg, pad_end, pad_beg, pad_end)
|
||||
|
||||
class InvertedResidual(nn.Module):
|
||||
def __init__(self, inp, oup, stride, dilation, expand_ratio):
|
||||
super(InvertedResidual, self).__init__()
|
||||
self.stride = stride
|
||||
assert stride in [1, 2]
|
||||
|
||||
hidden_dim = int(round(inp * expand_ratio))
|
||||
self.use_res_connect = self.stride == 1 and inp == oup
|
||||
|
||||
layers = []
|
||||
if expand_ratio != 1:
|
||||
# pw
|
||||
layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1))
|
||||
|
||||
layers.extend([
|
||||
# dw
|
||||
ConvBNReLU(hidden_dim, hidden_dim, stride=stride, dilation=dilation, groups=hidden_dim),
|
||||
# pw-linear
|
||||
nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
|
||||
nn.BatchNorm2d(oup),
|
||||
])
|
||||
self.conv = nn.Sequential(*layers)
|
||||
|
||||
self.input_padding = fixed_padding( 3, dilation )
|
||||
|
||||
def forward(self, x):
|
||||
x_pad = F.pad(x, self.input_padding)
|
||||
if self.use_res_connect:
|
||||
return x + self.conv(x_pad)
|
||||
else:
|
||||
return self.conv(x_pad)
|
||||
|
||||
class MobileNetV2(nn.Module):
|
||||
def __init__(self, num_classes=1000, output_stride=8, width_mult=1.0, inverted_residual_setting=None, round_nearest=8):
|
||||
"""
|
||||
MobileNet V2 main class
|
||||
|
||||
Args:
|
||||
num_classes (int): Number of classes
|
||||
width_mult (float): Width multiplier - adjusts number of channels in each layer by this amount
|
||||
inverted_residual_setting: Network structure
|
||||
round_nearest (int): Round the number of channels in each layer to be a multiple of this number
|
||||
Set to 1 to turn off rounding
|
||||
"""
|
||||
super(MobileNetV2, self).__init__()
|
||||
block = InvertedResidual
|
||||
input_channel = 32
|
||||
last_channel = 1280
|
||||
self.output_stride = output_stride
|
||||
current_stride = 1
|
||||
if inverted_residual_setting is None:
|
||||
inverted_residual_setting = [
|
||||
# t, c, n, s
|
||||
[1, 16, 1, 1],
|
||||
[6, 24, 2, 2],
|
||||
[6, 32, 3, 2],
|
||||
[6, 64, 4, 2],
|
||||
[6, 96, 3, 1],
|
||||
[6, 160, 3, 2],
|
||||
[6, 320, 1, 1],
|
||||
]
|
||||
|
||||
# only check the first element, assuming user knows t,c,n,s are required
|
||||
if len(inverted_residual_setting) == 0 or len(inverted_residual_setting[0]) != 4:
|
||||
raise ValueError("inverted_residual_setting should be non-empty "
|
||||
"or a 4-element list, got {}".format(inverted_residual_setting))
|
||||
|
||||
# building first layer
|
||||
input_channel = _make_divisible(input_channel * width_mult, round_nearest)
|
||||
self.last_channel = _make_divisible(last_channel * max(1.0, width_mult), round_nearest)
|
||||
features = [ConvBNReLU(3, input_channel, stride=2)]
|
||||
current_stride *= 2
|
||||
dilation=1
|
||||
previous_dilation = 1
|
||||
|
||||
# building inverted residual blocks
|
||||
for t, c, n, s in inverted_residual_setting:
|
||||
output_channel = _make_divisible(c * width_mult, round_nearest)
|
||||
previous_dilation = dilation
|
||||
if current_stride == output_stride:
|
||||
stride = 1
|
||||
dilation *= s
|
||||
else:
|
||||
stride = s
|
||||
current_stride *= s
|
||||
output_channel = int(c * width_mult)
|
||||
|
||||
for i in range(n):
|
||||
if i==0:
|
||||
features.append(block(input_channel, output_channel, stride, previous_dilation, expand_ratio=t))
|
||||
else:
|
||||
features.append(block(input_channel, output_channel, 1, dilation, expand_ratio=t))
|
||||
input_channel = output_channel
|
||||
# building last several layers
|
||||
features.append(ConvBNReLU(input_channel, self.last_channel, kernel_size=1))
|
||||
# make it nn.Sequential
|
||||
self.features = nn.Sequential(*features)
|
||||
|
||||
# building classifier
|
||||
self.classifier = nn.Sequential(
|
||||
nn.Dropout(0.2),
|
||||
nn.Linear(self.last_channel, num_classes),
|
||||
)
|
||||
|
||||
# weight initialization
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight, mode='fan_out')
|
||||
if m.bias is not None:
|
||||
nn.init.zeros_(m.bias)
|
||||
elif isinstance(m, nn.BatchNorm2d):
|
||||
nn.init.ones_(m.weight)
|
||||
nn.init.zeros_(m.bias)
|
||||
elif isinstance(m, nn.Linear):
|
||||
nn.init.normal_(m.weight, 0, 0.01)
|
||||
nn.init.zeros_(m.bias)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.features(x)
|
||||
x = x.mean([2, 3])
|
||||
x = self.classifier(x)
|
||||
return x
|
||||
|
||||
|
||||
def mobilenet_v2(pretrained=False, progress=True, **kwargs):
|
||||
"""
|
||||
Constructs a MobileNetV2 architecture from
|
||||
`"MobileNetV2: Inverted Residuals and Linear Bottlenecks" <https://arxiv.org/abs/1801.04381>`_.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
model = MobileNetV2(**kwargs)
|
||||
if pretrained:
|
||||
state_dict = load_state_dict_from_url(model_urls['mobilenet_v2'],
|
||||
progress=progress)
|
||||
model.load_state_dict(state_dict)
|
||||
return model
|
||||
|
|
@ -1,346 +0,0 @@
|
|||
import torch
|
||||
import torch.nn as nn
|
||||
try: # for torchvision<0.4
|
||||
from torchvision.models.utils import load_state_dict_from_url
|
||||
except: # for torchvision>=0.4
|
||||
from torch.hub import load_state_dict_from_url
|
||||
|
||||
|
||||
__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',
|
||||
'resnet152', 'resnext50_32x4d', 'resnext101_32x8d',
|
||||
'wide_resnet50_2', 'wide_resnet101_2']
|
||||
|
||||
|
||||
model_urls = {
|
||||
'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
|
||||
'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
|
||||
'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
|
||||
'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
|
||||
'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
|
||||
'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',
|
||||
'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',
|
||||
'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth',
|
||||
'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth',
|
||||
}
|
||||
|
||||
|
||||
def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
|
||||
"""3x3 convolution with padding"""
|
||||
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
|
||||
padding=dilation, groups=groups, bias=False, dilation=dilation)
|
||||
|
||||
|
||||
def conv1x1(in_planes, out_planes, stride=1):
|
||||
"""1x1 convolution"""
|
||||
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
|
||||
|
||||
|
||||
class BasicBlock(nn.Module):
|
||||
expansion = 1
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
|
||||
base_width=64, dilation=1, norm_layer=None):
|
||||
super(BasicBlock, self).__init__()
|
||||
if norm_layer is None:
|
||||
norm_layer = nn.BatchNorm2d
|
||||
if groups != 1 or base_width != 64:
|
||||
raise ValueError('BasicBlock only supports groups=1 and base_width=64')
|
||||
if dilation > 1:
|
||||
raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
|
||||
# Both self.conv1 and self.downsample layers downsample the input when stride != 1
|
||||
self.conv1 = conv3x3(inplanes, planes, stride)
|
||||
self.bn1 = norm_layer(planes)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.conv2 = conv3x3(planes, planes)
|
||||
self.bn2 = norm_layer(planes)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class Bottleneck(nn.Module):
|
||||
expansion = 4
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
|
||||
base_width=64, dilation=1, norm_layer=None):
|
||||
super(Bottleneck, self).__init__()
|
||||
if norm_layer is None:
|
||||
norm_layer = nn.BatchNorm2d
|
||||
width = int(planes * (base_width / 64.)) * groups
|
||||
# Both self.conv2 and self.downsample layers downsample the input when stride != 1
|
||||
self.conv1 = conv1x1(inplanes, width)
|
||||
self.bn1 = norm_layer(width)
|
||||
self.conv2 = conv3x3(width, width, stride, groups, dilation)
|
||||
self.bn2 = norm_layer(width)
|
||||
self.conv3 = conv1x1(width, planes * self.expansion)
|
||||
self.bn3 = norm_layer(planes * self.expansion)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv3(out)
|
||||
out = self.bn3(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class ResNet(nn.Module):
|
||||
|
||||
def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,
|
||||
groups=1, width_per_group=64, replace_stride_with_dilation=None,
|
||||
norm_layer=None):
|
||||
super(ResNet, self).__init__()
|
||||
if norm_layer is None:
|
||||
norm_layer = nn.BatchNorm2d
|
||||
self._norm_layer = norm_layer
|
||||
|
||||
self.inplanes = 64
|
||||
self.dilation = 1
|
||||
if replace_stride_with_dilation is None:
|
||||
# each element in the tuple indicates if we should replace
|
||||
# the 2x2 stride with a dilated convolution instead
|
||||
replace_stride_with_dilation = [False, False, False]
|
||||
if len(replace_stride_with_dilation) != 3:
|
||||
raise ValueError("replace_stride_with_dilation should be None "
|
||||
"or a 3-element tuple, got {}".format(replace_stride_with_dilation))
|
||||
self.groups = groups
|
||||
self.base_width = width_per_group
|
||||
self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
|
||||
bias=False)
|
||||
self.bn1 = norm_layer(self.inplanes)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
||||
self.layer1 = self._make_layer(block, 64, layers[0])
|
||||
self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
|
||||
dilate=replace_stride_with_dilation[0])
|
||||
self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
|
||||
dilate=replace_stride_with_dilation[1])
|
||||
self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
|
||||
dilate=replace_stride_with_dilation[2])
|
||||
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
|
||||
self.fc = nn.Linear(512 * block.expansion, num_classes)
|
||||
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
|
||||
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
|
||||
nn.init.constant_(m.weight, 1)
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
# Zero-initialize the last BN in each residual branch,
|
||||
# so that the residual branch starts with zeros, and each residual block behaves like an identity.
|
||||
# This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
|
||||
if zero_init_residual:
|
||||
for m in self.modules():
|
||||
if isinstance(m, Bottleneck):
|
||||
nn.init.constant_(m.bn3.weight, 0)
|
||||
elif isinstance(m, BasicBlock):
|
||||
nn.init.constant_(m.bn2.weight, 0)
|
||||
|
||||
def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
|
||||
norm_layer = self._norm_layer
|
||||
downsample = None
|
||||
previous_dilation = self.dilation
|
||||
if dilate:
|
||||
self.dilation *= stride
|
||||
stride = 1
|
||||
if stride != 1 or self.inplanes != planes * block.expansion:
|
||||
downsample = nn.Sequential(
|
||||
conv1x1(self.inplanes, planes * block.expansion, stride),
|
||||
norm_layer(planes * block.expansion),
|
||||
)
|
||||
|
||||
layers = []
|
||||
layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
|
||||
self.base_width, previous_dilation, norm_layer))
|
||||
self.inplanes = planes * block.expansion
|
||||
for _ in range(1, blocks):
|
||||
layers.append(block(self.inplanes, planes, groups=self.groups,
|
||||
base_width=self.base_width, dilation=self.dilation,
|
||||
norm_layer=norm_layer))
|
||||
|
||||
return nn.Sequential(*layers)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.conv1(x)
|
||||
x = self.bn1(x)
|
||||
x = self.relu(x)
|
||||
x = self.maxpool(x)
|
||||
|
||||
x = self.layer1(x)
|
||||
x = self.layer2(x)
|
||||
x = self.layer3(x)
|
||||
x = self.layer4(x)
|
||||
|
||||
x = self.avgpool(x)
|
||||
x = torch.flatten(x, 1)
|
||||
x = self.fc(x)
|
||||
|
||||
return x
|
||||
|
||||
|
||||
def _resnet(arch, block, layers, pretrained, progress, **kwargs):
|
||||
model = ResNet(block, layers, **kwargs)
|
||||
if pretrained:
|
||||
state_dict = load_state_dict_from_url(model_urls[arch],
|
||||
progress=progress)
|
||||
model.load_state_dict(state_dict)
|
||||
return model
|
||||
|
||||
|
||||
def resnet18(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-18 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet34(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-34 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet50(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-50 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet101(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-101 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet152(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-152 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnext50_32x4d(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNeXt-50 32x4d model from
|
||||
`"Aggregated Residual Transformation for Deep Neural Networks" <https://arxiv.org/pdf/1611.05431.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['groups'] = 32
|
||||
kwargs['width_per_group'] = 4
|
||||
return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
||||
|
||||
def resnext101_32x8d(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNeXt-101 32x8d model from
|
||||
`"Aggregated Residual Transformation for Deep Neural Networks" <https://arxiv.org/pdf/1611.05431.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['groups'] = 32
|
||||
kwargs['width_per_group'] = 8
|
||||
return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
||||
|
||||
def wide_resnet50_2(pretrained=False, progress=True, **kwargs):
|
||||
r"""Wide ResNet-50-2 model from
|
||||
`"Wide Residual Networks" <https://arxiv.org/pdf/1605.07146.pdf>`_
|
||||
|
||||
The model is the same as ResNet except for the bottleneck number of channels
|
||||
which is twice larger in every block. The number of channels in outer 1x1
|
||||
convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048
|
||||
channels, and in Wide ResNet-50-2 has 2048-1024-2048.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['width_per_group'] = 64 * 2
|
||||
return _resnet('wide_resnet50_2', Bottleneck, [3, 4, 6, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
||||
|
||||
def wide_resnet101_2(pretrained=False, progress=True, **kwargs):
|
||||
r"""Wide ResNet-101-2 model from
|
||||
`"Wide Residual Networks" <https://arxiv.org/pdf/1605.07146.pdf>`_
|
||||
|
||||
The model is the same as ResNet except for the bottleneck number of channels
|
||||
which is twice larger in every block. The number of channels in outer 1x1
|
||||
convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048
|
||||
channels, and in Wide ResNet-50-2 has 2048-1024-2048.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['width_per_group'] = 64 * 2
|
||||
return _resnet('wide_resnet101_2', Bottleneck, [3, 4, 23, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
|
||||
"""
|
||||
Xception is adapted from https://github.com/Cadene/pretrained-models.pytorch/blob/master/pretrainedmodels/models/xception.py
|
||||
|
||||
Ported to pytorch thanks to [tstandley](https://github.com/tstandley/Xception-PyTorch)
|
||||
@author: tstandley
|
||||
Adapted by cadene
|
||||
Creates an Xception Model as defined in:
|
||||
Francois Chollet
|
||||
Xception: Deep Learning with Depthwise Separable Convolutions
|
||||
https://arxiv.org/pdf/1610.02357.pdf
|
||||
This weights ported from the Keras implementation. Achieves the following performance on the validation set:
|
||||
Loss:0.9173 Prec@1:78.892 Prec@5:94.292
|
||||
REMEMBER to set your image size to 3x299x299 for both test and validation
|
||||
normalize = transforms.Normalize(mean=[0.5, 0.5, 0.5],
|
||||
std=[0.5, 0.5, 0.5])
|
||||
The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299
|
||||
"""
|
||||
from __future__ import print_function, division, absolute_import
|
||||
import math
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
import torch.utils.model_zoo as model_zoo
|
||||
from torch.nn import init
|
||||
|
||||
__all__ = ['xception']
|
||||
|
||||
pretrained_settings = {
|
||||
'xception': {
|
||||
'imagenet': {
|
||||
'url': 'http://data.lip6.fr/cadene/pretrainedmodels/xception-43020ad28.pth',
|
||||
'input_space': 'RGB',
|
||||
'input_size': [3, 299, 299],
|
||||
'input_range': [0, 1],
|
||||
'mean': [0.5, 0.5, 0.5],
|
||||
'std': [0.5, 0.5, 0.5],
|
||||
'num_classes': 1000,
|
||||
'scale': 0.8975 # The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SeparableConv2d(nn.Module):
|
||||
def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False):
|
||||
super(SeparableConv2d,self).__init__()
|
||||
|
||||
self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias)
|
||||
self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias)
|
||||
|
||||
def forward(self,x):
|
||||
x = self.conv1(x)
|
||||
x = self.pointwise(x)
|
||||
return x
|
||||
|
||||
|
||||
class Block(nn.Module):
|
||||
def __init__(self,in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True, dilation=1):
|
||||
super(Block, self).__init__()
|
||||
|
||||
if out_filters != in_filters or strides!=1:
|
||||
self.skip = nn.Conv2d(in_filters,out_filters,1,stride=strides, bias=False)
|
||||
self.skipbn = nn.BatchNorm2d(out_filters)
|
||||
else:
|
||||
self.skip=None
|
||||
|
||||
rep=[]
|
||||
|
||||
filters=in_filters
|
||||
if grow_first:
|
||||
rep.append(nn.ReLU(inplace=True))
|
||||
rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=dilation, dilation=dilation, bias=False))
|
||||
rep.append(nn.BatchNorm2d(out_filters))
|
||||
filters = out_filters
|
||||
|
||||
for i in range(reps-1):
|
||||
rep.append(nn.ReLU(inplace=True))
|
||||
rep.append(SeparableConv2d(filters,filters,3,stride=1,padding=dilation,dilation=dilation,bias=False))
|
||||
rep.append(nn.BatchNorm2d(filters))
|
||||
|
||||
if not grow_first:
|
||||
rep.append(nn.ReLU(inplace=True))
|
||||
rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=dilation,dilation=dilation,bias=False))
|
||||
rep.append(nn.BatchNorm2d(out_filters))
|
||||
|
||||
if not start_with_relu:
|
||||
rep = rep[1:]
|
||||
else:
|
||||
rep[0] = nn.ReLU(inplace=False)
|
||||
|
||||
if strides != 1:
|
||||
rep.append(nn.MaxPool2d(3,strides,1))
|
||||
self.rep = nn.Sequential(*rep)
|
||||
|
||||
def forward(self,inp):
|
||||
x = self.rep(inp)
|
||||
|
||||
if self.skip is not None:
|
||||
skip = self.skip(inp)
|
||||
skip = self.skipbn(skip)
|
||||
else:
|
||||
skip = inp
|
||||
x+=skip
|
||||
return x
|
||||
|
||||
|
||||
class Xception(nn.Module):
|
||||
"""
|
||||
Xception optimized for the ImageNet dataset, as specified in
|
||||
https://arxiv.org/pdf/1610.02357.pdf
|
||||
"""
|
||||
def __init__(self, num_classes=1000, replace_stride_with_dilation=None):
|
||||
""" Constructor
|
||||
Args:
|
||||
num_classes: number of classes
|
||||
"""
|
||||
super(Xception, self).__init__()
|
||||
|
||||
self.num_classes = num_classes
|
||||
self.dilation = 1
|
||||
if replace_stride_with_dilation is None:
|
||||
# each element in the tuple indicates if we should replace
|
||||
# the 2x2 stride with a dilated convolution instead
|
||||
replace_stride_with_dilation = [False, False, False, False]
|
||||
if len(replace_stride_with_dilation) != 4:
|
||||
raise ValueError("replace_stride_with_dilation should be None "
|
||||
"or a 4-element tuple, got {}".format(replace_stride_with_dilation))
|
||||
|
||||
self.conv1 = nn.Conv2d(3, 32, 3,2, 0, bias=False) # 1 / 2
|
||||
self.bn1 = nn.BatchNorm2d(32)
|
||||
self.relu1 = nn.ReLU(inplace=True)
|
||||
|
||||
self.conv2 = nn.Conv2d(32,64,3,bias=False)
|
||||
self.bn2 = nn.BatchNorm2d(64)
|
||||
self.relu2 = nn.ReLU(inplace=True)
|
||||
#do relu here
|
||||
|
||||
self.block1=self._make_block(64,128,2,2,start_with_relu=False,grow_first=True, dilate=replace_stride_with_dilation[0]) # 1 / 4
|
||||
self.block2=self._make_block(128,256,2,2,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[1]) # 1 / 8
|
||||
self.block3=self._make_block(256,728,2,2,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2]) # 1 / 16
|
||||
|
||||
self.block4=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
self.block5=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
self.block6=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
self.block7=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
|
||||
self.block8=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
self.block9=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
self.block10=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
self.block11=self._make_block(728,728,3,1,start_with_relu=True,grow_first=True, dilate=replace_stride_with_dilation[2])
|
||||
|
||||
self.block12=self._make_block(728,1024,2,2,start_with_relu=True,grow_first=False, dilate=replace_stride_with_dilation[3]) # 1 / 32
|
||||
|
||||
self.conv3 = SeparableConv2d(1024,1536,3,1,1, dilation=self.dilation)
|
||||
self.bn3 = nn.BatchNorm2d(1536)
|
||||
self.relu3 = nn.ReLU(inplace=True)
|
||||
|
||||
#do relu here
|
||||
self.conv4 = SeparableConv2d(1536,2048,3,1,1, dilation=self.dilation)
|
||||
self.bn4 = nn.BatchNorm2d(2048)
|
||||
|
||||
self.fc = nn.Linear(2048, num_classes)
|
||||
|
||||
# #------- init weights --------
|
||||
# for m in self.modules():
|
||||
# if isinstance(m, nn.Conv2d):
|
||||
# n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
|
||||
# m.weight.data.normal_(0, math.sqrt(2. / n))
|
||||
# elif isinstance(m, nn.BatchNorm2d):
|
||||
# m.weight.data.fill_(1)
|
||||
# m.bias.data.zero_()
|
||||
# #-----------------------------
|
||||
|
||||
def _make_block(self, in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True, dilate=False):
|
||||
if dilate:
|
||||
self.dilation *= strides
|
||||
strides = 1
|
||||
return Block(in_filters,out_filters,reps,strides,start_with_relu=start_with_relu,grow_first=grow_first, dilation=self.dilation)
|
||||
|
||||
def features(self, input):
|
||||
x = self.conv1(input)
|
||||
x = self.bn1(x)
|
||||
x = self.relu1(x)
|
||||
|
||||
x = self.conv2(x)
|
||||
x = self.bn2(x)
|
||||
x = self.relu2(x)
|
||||
|
||||
x = self.block1(x)
|
||||
x = self.block2(x)
|
||||
x = self.block3(x)
|
||||
x = self.block4(x)
|
||||
x = self.block5(x)
|
||||
x = self.block6(x)
|
||||
x = self.block7(x)
|
||||
x = self.block8(x)
|
||||
x = self.block9(x)
|
||||
x = self.block10(x)
|
||||
x = self.block11(x)
|
||||
x = self.block12(x)
|
||||
|
||||
x = self.conv3(x)
|
||||
x = self.bn3(x)
|
||||
x = self.relu3(x)
|
||||
|
||||
x = self.conv4(x)
|
||||
x = self.bn4(x)
|
||||
return x
|
||||
|
||||
def logits(self, features):
|
||||
x = nn.ReLU(inplace=True)(features)
|
||||
|
||||
x = F.adaptive_avg_pool2d(x, (1, 1))
|
||||
x = x.view(x.size(0), -1)
|
||||
x = self.last_linear(x)
|
||||
return x
|
||||
|
||||
def forward(self, input):
|
||||
x = self.features(input)
|
||||
x = self.logits(x)
|
||||
return x
|
||||
|
||||
|
||||
def xception(num_classes=1000, pretrained='imagenet', replace_stride_with_dilation=None):
|
||||
model = Xception(num_classes=num_classes, replace_stride_with_dilation=replace_stride_with_dilation)
|
||||
if pretrained:
|
||||
settings = pretrained_settings['xception'][pretrained]
|
||||
assert num_classes == settings['num_classes'], \
|
||||
"num_classes should be {}, but is {}".format(settings['num_classes'], num_classes)
|
||||
|
||||
model = Xception(num_classes=num_classes, replace_stride_with_dilation=replace_stride_with_dilation)
|
||||
model.load_state_dict(model_zoo.load_url(settings['url']))
|
||||
|
||||
# TODO: ugly
|
||||
model.last_linear = model.fc
|
||||
del model.fc
|
||||
return model
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
from .utils import IntermediateLayerGetter
|
||||
from ._deeplab import DeepLabHead, DeepLabHeadV3Plus, DeepLabV3
|
||||
from .backbone import (
|
||||
resnet,
|
||||
mobilenetv2,
|
||||
hrnetv2,
|
||||
xception
|
||||
)
|
||||
|
||||
def _segm_hrnet(name, backbone_name, num_classes, pretrained_backbone):
|
||||
|
||||
backbone = hrnetv2.__dict__[backbone_name](pretrained_backbone)
|
||||
# HRNetV2 config:
|
||||
# the final output channels is dependent on highest resolution channel config (c).
|
||||
# output of backbone will be the inplanes to assp:
|
||||
hrnet_channels = int(backbone_name.split('_')[-1])
|
||||
inplanes = sum([hrnet_channels * 2 ** i for i in range(4)])
|
||||
low_level_planes = 256 # all hrnet version channel output from bottleneck is the same
|
||||
aspp_dilate = [12, 24, 36] # If follow paper trend, can put [24, 48, 72].
|
||||
|
||||
if name=='deeplabv3plus':
|
||||
return_layers = {'stage4': 'out', 'layer1': 'low_level'}
|
||||
classifier = DeepLabHeadV3Plus(inplanes, low_level_planes, num_classes, aspp_dilate)
|
||||
elif name=='deeplabv3':
|
||||
return_layers = {'stage4': 'out'}
|
||||
classifier = DeepLabHead(inplanes, num_classes, aspp_dilate)
|
||||
|
||||
backbone = IntermediateLayerGetter(backbone, return_layers=return_layers, hrnet_flag=True)
|
||||
model = DeepLabV3(backbone, classifier)
|
||||
return model
|
||||
|
||||
def _segm_resnet(name, backbone_name, num_classes, output_stride, pretrained_backbone):
|
||||
|
||||
if output_stride==8:
|
||||
replace_stride_with_dilation=[False, True, True]
|
||||
aspp_dilate = [12, 24, 36]
|
||||
else:
|
||||
replace_stride_with_dilation=[False, False, True]
|
||||
aspp_dilate = [6, 12, 18]
|
||||
|
||||
backbone = resnet.__dict__[backbone_name](
|
||||
pretrained=pretrained_backbone,
|
||||
replace_stride_with_dilation=replace_stride_with_dilation)
|
||||
|
||||
inplanes = 2048
|
||||
low_level_planes = 256
|
||||
|
||||
if name=='deeplabv3plus':
|
||||
return_layers = {'layer4': 'out', 'layer1': 'low_level'}
|
||||
classifier = DeepLabHeadV3Plus(inplanes, low_level_planes, num_classes, aspp_dilate)
|
||||
elif name=='deeplabv3':
|
||||
return_layers = {'layer4': 'out'}
|
||||
classifier = DeepLabHead(inplanes , num_classes, aspp_dilate)
|
||||
backbone = IntermediateLayerGetter(backbone, return_layers=return_layers)
|
||||
|
||||
model = DeepLabV3(backbone, classifier)
|
||||
return model
|
||||
|
||||
|
||||
def _segm_xception(name, backbone_name, num_classes, output_stride, pretrained_backbone):
|
||||
if output_stride==8:
|
||||
replace_stride_with_dilation=[False, False, True, True]
|
||||
aspp_dilate = [12, 24, 36]
|
||||
else:
|
||||
replace_stride_with_dilation=[False, False, False, True]
|
||||
aspp_dilate = [6, 12, 18]
|
||||
|
||||
backbone = xception.xception(pretrained= 'imagenet' if pretrained_backbone else False, replace_stride_with_dilation=replace_stride_with_dilation)
|
||||
|
||||
inplanes = 2048
|
||||
low_level_planes = 128
|
||||
|
||||
if name=='deeplabv3plus':
|
||||
return_layers = {'conv4': 'out', 'block1': 'low_level'}
|
||||
classifier = DeepLabHeadV3Plus(inplanes, low_level_planes, num_classes, aspp_dilate)
|
||||
elif name=='deeplabv3':
|
||||
return_layers = {'conv4': 'out'}
|
||||
classifier = DeepLabHead(inplanes , num_classes, aspp_dilate)
|
||||
backbone = IntermediateLayerGetter(backbone, return_layers=return_layers)
|
||||
model = DeepLabV3(backbone, classifier)
|
||||
return model
|
||||
|
||||
|
||||
def _segm_mobilenet(name, backbone_name, num_classes, output_stride, pretrained_backbone):
|
||||
if output_stride==8:
|
||||
aspp_dilate = [12, 24, 36]
|
||||
else:
|
||||
aspp_dilate = [6, 12, 18]
|
||||
|
||||
backbone = mobilenetv2.mobilenet_v2(pretrained=pretrained_backbone, output_stride=output_stride)
|
||||
|
||||
# rename layers
|
||||
backbone.low_level_features = backbone.features[0:4]
|
||||
backbone.high_level_features = backbone.features[4:-1]
|
||||
backbone.features = None
|
||||
backbone.classifier = None
|
||||
|
||||
inplanes = 320
|
||||
low_level_planes = 24
|
||||
|
||||
if name=='deeplabv3plus':
|
||||
return_layers = {'high_level_features': 'out', 'low_level_features': 'low_level'}
|
||||
classifier = DeepLabHeadV3Plus(inplanes, low_level_planes, num_classes, aspp_dilate)
|
||||
elif name=='deeplabv3':
|
||||
return_layers = {'high_level_features': 'out'}
|
||||
classifier = DeepLabHead(inplanes , num_classes, aspp_dilate)
|
||||
backbone = IntermediateLayerGetter(backbone, return_layers=return_layers)
|
||||
|
||||
model = DeepLabV3(backbone, classifier)
|
||||
return model
|
||||
|
||||
def _load_model(arch_type, backbone, num_classes, output_stride, pretrained_backbone):
|
||||
|
||||
if backbone=='mobilenetv2':
|
||||
model = _segm_mobilenet(arch_type, backbone, num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
elif backbone.startswith('resnet'):
|
||||
model = _segm_resnet(arch_type, backbone, num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
elif backbone.startswith('hrnetv2'):
|
||||
model = _segm_hrnet(arch_type, backbone, num_classes, pretrained_backbone=pretrained_backbone)
|
||||
elif backbone=='xception':
|
||||
model = _segm_xception(arch_type, backbone, num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
return model
|
||||
|
||||
|
||||
# Deeplab v3
|
||||
def deeplabv3_hrnetv2_48(num_classes=21, output_stride=4, pretrained_backbone=False): # no pretrained backbone yet
|
||||
return _load_model('deeplabv3', 'hrnetv2_48', output_stride, num_classes, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3_hrnetv2_32(num_classes=21, output_stride=4, pretrained_backbone=True):
|
||||
return _load_model('deeplabv3', 'hrnetv2_32', output_stride, num_classes, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3_resnet50(num_classes=21, output_stride=8, pretrained_backbone=True):
|
||||
"""Constructs a DeepLabV3 model with a ResNet-50 backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3', 'resnet50', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3_resnet101(num_classes=21, output_stride=8, pretrained_backbone=True):
|
||||
"""Constructs a DeepLabV3 model with a ResNet-101 backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3', 'resnet101', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3_mobilenet(num_classes=21, output_stride=8, pretrained_backbone=True, **kwargs):
|
||||
"""Constructs a DeepLabV3 model with a MobileNetv2 backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3', 'mobilenetv2', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3_xception(num_classes=21, output_stride=8, pretrained_backbone=True, **kwargs):
|
||||
"""Constructs a DeepLabV3 model with a Xception backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3', 'xception', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
|
||||
# Deeplab v3+
|
||||
def deeplabv3plus_hrnetv2_48(num_classes=21, output_stride=4, pretrained_backbone=False): # no pretrained backbone yet
|
||||
return _load_model('deeplabv3plus', 'hrnetv2_48', num_classes, output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3plus_hrnetv2_32(num_classes=21, output_stride=4, pretrained_backbone=True):
|
||||
return _load_model('deeplabv3plus', 'hrnetv2_32', num_classes, output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3plus_resnet50(num_classes=21, output_stride=8, pretrained_backbone=True):
|
||||
"""Constructs a DeepLabV3 model with a ResNet-50 backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3plus', 'resnet50', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
|
||||
def deeplabv3plus_resnet101(num_classes=21, output_stride=8, pretrained_backbone=True):
|
||||
"""Constructs a DeepLabV3+ model with a ResNet-101 backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3plus', 'resnet101', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
|
||||
def deeplabv3plus_mobilenet(num_classes=21, output_stride=8, pretrained_backbone=True):
|
||||
"""Constructs a DeepLabV3+ model with a MobileNetv2 backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3plus', 'mobilenetv2', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
||||
def deeplabv3plus_xception(num_classes=21, output_stride=8, pretrained_backbone=True):
|
||||
"""Constructs a DeepLabV3+ model with a Xception backbone.
|
||||
|
||||
Args:
|
||||
num_classes (int): number of classes.
|
||||
output_stride (int): output stride for deeplab.
|
||||
pretrained_backbone (bool): If True, use the pretrained backbone.
|
||||
"""
|
||||
return _load_model('deeplabv3plus', 'xception', num_classes, output_stride=output_stride, pretrained_backbone=pretrained_backbone)
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
import torch
|
||||
import torch.nn as nn
|
||||
import numpy as np
|
||||
import torch.nn.functional as F
|
||||
from collections import OrderedDict
|
||||
|
||||
class _SimpleSegmentationModel(nn.Module):
|
||||
def __init__(self, backbone, classifier):
|
||||
super(_SimpleSegmentationModel, self).__init__()
|
||||
self.backbone = backbone
|
||||
self.classifier = classifier
|
||||
|
||||
def forward(self, x):
|
||||
input_shape = x.shape[-2:]
|
||||
features = self.backbone(x)
|
||||
x = self.classifier(features)
|
||||
x = F.interpolate(x, size=input_shape, mode='bilinear', align_corners=False)
|
||||
return x
|
||||
|
||||
|
||||
class IntermediateLayerGetter(nn.ModuleDict):
|
||||
"""
|
||||
Module wrapper that returns intermediate layers from a model
|
||||
|
||||
It has a strong assumption that the modules have been registered
|
||||
into the model in the same order as they are used.
|
||||
This means that one should **not** reuse the same nn.Module
|
||||
twice in the forward if you want this to work.
|
||||
|
||||
Additionally, it is only able to query submodules that are directly
|
||||
assigned to the model. So if `model` is passed, `model.feature1` can
|
||||
be returned, but not `model.feature1.layer2`.
|
||||
|
||||
Arguments:
|
||||
model (nn.Module): model on which we will extract the features
|
||||
return_layers (Dict[name, new_name]): a dict containing the names
|
||||
of the modules for which the activations will be returned as
|
||||
the key of the dict, and the value of the dict is the name
|
||||
of the returned activation (which the user can specify).
|
||||
|
||||
Examples::
|
||||
|
||||
>>> m = torchvision.models.resnet18(pretrained=True)
|
||||
>>> # extract layer1 and layer3, giving as names `feat1` and feat2`
|
||||
>>> new_m = torchvision.models._utils.IntermediateLayerGetter(m,
|
||||
>>> {'layer1': 'feat1', 'layer3': 'feat2'})
|
||||
>>> out = new_m(torch.rand(1, 3, 224, 224))
|
||||
>>> print([(k, v.shape) for k, v in out.items()])
|
||||
>>> [('feat1', torch.Size([1, 64, 56, 56])),
|
||||
>>> ('feat2', torch.Size([1, 256, 14, 14]))]
|
||||
"""
|
||||
def __init__(self, model, return_layers, hrnet_flag=False):
|
||||
if not set(return_layers).issubset([name for name, _ in model.named_children()]):
|
||||
raise ValueError("return_layers are not present in model")
|
||||
|
||||
self.hrnet_flag = hrnet_flag
|
||||
|
||||
orig_return_layers = return_layers
|
||||
return_layers = {k: v for k, v in return_layers.items()}
|
||||
layers = OrderedDict()
|
||||
for name, module in model.named_children():
|
||||
layers[name] = module
|
||||
if name in return_layers:
|
||||
del return_layers[name]
|
||||
if not return_layers:
|
||||
break
|
||||
|
||||
super(IntermediateLayerGetter, self).__init__(layers)
|
||||
self.return_layers = orig_return_layers
|
||||
|
||||
def forward(self, x):
|
||||
out = OrderedDict()
|
||||
for name, module in self.named_children():
|
||||
if self.hrnet_flag and name.startswith('transition'): # if using hrnet, you need to take care of transition
|
||||
if name == 'transition1': # in transition1, you need to split the module to two streams first
|
||||
x = [trans(x) for trans in module]
|
||||
else: # all other transition is just an extra one stream split
|
||||
x.append(module(x[-1]))
|
||||
else: # other models (ex:resnet,mobilenet) are convolutions in series.
|
||||
x = module(x)
|
||||
|
||||
if name in self.return_layers:
|
||||
out_name = self.return_layers[name]
|
||||
if name == 'stage4' and self.hrnet_flag: # In HRNetV2, we upsample and concat all outputs streams together
|
||||
output_h, output_w = x[0].size(2), x[0].size(3) # Upsample to size of highest resolution stream
|
||||
x1 = F.interpolate(x[1], size=(output_h, output_w), mode='bilinear', align_corners=False)
|
||||
x2 = F.interpolate(x[2], size=(output_h, output_w), mode='bilinear', align_corners=False)
|
||||
x3 = F.interpolate(x[3], size=(output_h, output_w), mode='bilinear', align_corners=False)
|
||||
x = torch.cat([x[0], x1, x2, x3], dim=1)
|
||||
out[out_name] = x
|
||||
else:
|
||||
out[out_name] = x
|
||||
return out
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue