Sistemas Especialistas Difusos (Fuzzy Expert Systems) :
FuzzyClips
1.
O programa Truck.exe da HyperLogic
•
O programa TRUCK.EXE da Hyperlogic é um simulador de rotas de
estacionamento de um caminhão, em marcha-ré, com velocidade
constante, utilizando lógica fuzzy (lógica nebulosa).
Objetivo do programa Truck.exe
•
Estacionar um caminhão:
Movendo-se em marcha-ré,
Com velocidade constante,
Num determinado local de um pátio de área 100 x 100 unidades (por
exemplo 100 x 100 m) onde se encontra.
•
O local do estacionamento deve situar-se no ponto X = 50 com o
caminhão parado perpendicularmente ao eixo dos X (ou seja,
ϕϕϕϕ
= 90
o)
Fig. 2 – Desenho esquemático da situação final desejada para o caminhão...
1.1 Como funciona a execução do programa ?
•
Indicar, inicialmente
A posição (X,Y) do caminhão
ângulo
ϕϕϕϕ
do caminhão com o eixo dos X
A velocidade constante de marcha-ré do caminhão ( 1, 2, 3, 4 ou 5)
•
No programa Truck.exe escolha a opção Run
→
→
→
→
Situation e configure as
opções
X position e Y position (posição (X,Y) do caminhão)
Azimuth angle (ângulo
ϕϕϕϕ
do caminhão com o eixo dos X)
Fig. 3 – Configurando a situação inicial através da opção Run
→
→
→
→
Situation do programa Truck.exe.
•
Para executar o programa Truck.exe com as opções apresentadas na Figura 3 [ X
Position = 20, Y Position = 30, Azimuth angle (
ϕϕϕϕ
) = 235
oe Truck Speed (velocidade
constante de marcha-ré) = 2 ] escolha a opção Run
→
→
→
→
Situation.
Fig. 4 – Resultado da execução do programa Truck.exe (situação inicial: X = 20, Y = 30,
ϕϕϕϕ
= 235
oe
1.2 Execute o programa para algumas situações iniciais...
•
Para maior familiaridade com o programa, execute-o algumas vezes.
Abaixo, uma tabela de situações iniciais para teste (e o resultado da
execução).
Teste N
oX
Y
ϕ
Velocidade
Resultado
1
20
30
0
o2
Ok
2
20
30
180
o2
Ok
3
70
25
90
o1
Ok
4
70
10
270
o3
Ok
5
70
10
350
o1
Ok
6
10
10
270
o2
?
7
10
10
270
o1
Ok
8
90
50
270
o1
Ok
9
90
50
270
o2
?
10
22
76
100
o5
Ok
11
22
76
100
o1
Ok
12
22
76
280
o5
Ok
13
22
76
280
o1
Ok
1) Porquê os testes 6 e 9 não funcionaram ?
2) Porquê o teste 11 apresentou “melhor” resultado que o teste 10 ? Idem
para o teste 13 com relação ao teste 12.
1.3 Entendendo o “controle difuso” do caminhão...
•
Após executar o programa Truck.exe foi possível perceber que as
variáveis de entrada: (1) X, (2) Y, (3)
ϕϕϕϕ
e (4) velocidade constante de
marcha-ré do caminhão “iniciam” o processo de controle de
estacionamento do caminhão.
•
Mas afinal, o que ocorre a cada “instante” do processo de estacionamento?
Vamos tentar entender...
O programa inicialmente analisa:
A coordenada X em que se encontra o caminhão
o ângulo
ϕϕϕϕ
do caminhão com o eixo dos X
e calcula
o ângulo
θθθθ
da roda do caminhão com seu eixo
•
Assim, o primeiro valor de saída a cada “instante” é o ângulo
θθθθ
.
1.3.1 – O processo básico de fuzificação
•
O processo de fuzificação se baseia na avaliação da seguinte estrutura de
regra:
SE
Distância X = ... E
Ângulo
ϕϕϕϕ
= ...
ENTÃO
Ângulo
θθθθ
= ...
•
Foi proposto pelos autores do programa Truck.exe a seguinte fuzificação:
1.3.1.1 – Variável Distância (X)
Variável Linguística:
DISTÂNCIA (X)
Termo Linguístico
Significado
LE
Left
LC
Left-Center
CE
Center
RC
Right-Center
RI
Right
1.3.1.2 – Variável ângulo
ϕϕϕϕ
do caminhão com o eixo dos X
Variável Linguística:
Ângulo
ϕϕϕϕ
Termo Linguístico
Significado
RB
Right-Below
RU
Right-Up
RV
Right-Vertical
VE
Vertical
LV
Left-Vertical
LU
Left-Up
LB
Left-Below
Fig. 6 – Orientação do ângulo
ϕϕϕϕ
do caminhão com o eixo dos X
1.3.1.3 – Variável ângulo
θθθθ
da roda do caminhão com seu eixo
Variável Linguística:
Ângulo
θθθθ
Termo Linguístico
Significado
NB
Negative
NM
Negative-Medium
NS
Negative-Small
ZE
Zero
PS
Positive-Small
PM
Positive-Medium
PB
Positive
1.3.2 – As regras do Sistema Especialista
•
O programa Truck.exe utiliza 35 regras para controlar o valor da variável
de saída (ângulo
θθθθ
) a cada “instante”: como temos a variável X
apresentando 5 termos linguísticos e a variável
ϕϕϕϕ
apresentando 7 termos
linguísticos, teremos 35 combinações:
Fig. 7 – A “combinação” de 5 valores de distância X e 7 valores de
ϕ
“produz” 35 regras.
•
O programa Truck.exe apresenta uma proposta de modelagem para as 35
regras, com a qual ele executa o processo de estacionamento:
•
Na Figura 8 podemos ver as 35 regras inicialmente propostas pelos
projetistas do programa Truck.exe. Por exemplo:
SE
Distância X = LE E
Ângulo
ϕϕϕϕ
= RB
ENTÃO
Ângulo
θθθθ
= PS
SE
Distância X = LC E
Ângulo
ϕϕϕϕ
= RB
ENTÃO
Ângulo
θθθθ
= PM
SE
Distância X = LC E
Ângulo
ϕϕϕϕ
= RU
ENTÃO
Ângulo
θθθθ
= PS
SE
Distância X = CE E
Ângulo
ϕϕϕϕ
= VE
ENTÃO
Ângulo
θθθθ
= ZE
SE
Distância X = RC E
Ângulo
ϕϕϕϕ
= LU
ENTÃO
Ângulo
θθθθ
= NS
•
É possível alterar o resultado (a parte “ENTÃO”) de qualquer uma das 35
regras. Basta utilizar a opção Project
→
→ Rules e “navegar” com as setas
→
→
do teclado para apontar o resultante que se deseja alterar (na “janela”
Rules: X vs. Chi) e, ao teclar <enter> escolher o novo valor.
1.3.3 – O disparo de uma regra do Sistema Especialista
•
O que acontece quando uma regra do sistema é disparada ?
Podemos dizer, neste caso, que os fatos referentes à distância X e ao
ângulo
ϕϕϕϕ
casaram com seus respectivos antecedentes na regra
disparada. Assim a regra disparada apresentou como resultado de saída
o ângulo
θθθθ
.
Porém,
θθθθ
não é o único resultado naquele “instante”. Uma vez
calculado não podemos esquecer que o propósito do sistema é
“movimentar” o caminhão para o local de estacionamento desejado.
Assim, com o ângulo
θθθθ
recém calculado, é calculado o novo ângulo
ϕϕϕϕ
’
do caminhão com o eixo dos X.
Em seguida, com o ângulo
ϕϕϕϕ
’ recém calculado, a posição atual (X,Y)
do caminhão e a velocidade constante de marcha-ré do caminhão,
calcula-se a nova posição (X’,Y’) do caminhão.
•
Vejamos a seguir como calcular
ϕϕϕϕ
’ e (X’,Y’).
1.3.3.1 – O cálculo de novo ângulo
ϕϕϕϕ
’ do caminhão com o eixo dos X.
•
O valor de
ϕϕϕϕ
’ é assim calculado:
ϕϕϕϕ
’ =
ϕϕϕϕ
+
θθθθ
•
Para entender esta fórmula vejamos uma situação-exemplo:
O caminhão encontra-se, em determinado instante, na posição (X,Y) =
(60,30) e
ϕ
= 315
o= - 45
o(Ver Figura 9).
Fig. 9 – (A) O caminhão encontra-se, em determinado instante, na posição (X,Y) = (60,30) com
ϕϕϕϕ
= - 45
º. (B) A orientação do ângulo
ϕϕϕϕ
.
Nestas condições temos que:
Considerando a definição dos conjuntos difusos para a variável
Distância X apresentada no item 1.3.1.1, X = 60 é considerado apenas
um valor RC (Right-Center) com grau de pertinência 1 (
µ
RC(60) = 1).
Para os demais valores (LE, LC, CE, RI) X = 60 apresenta grau de
pertinência zero.
Considerando a definição dos conjuntos difusos para a variável Ângulo
ϕϕϕϕ
do caminhão com o eixo dos X apresentada no item 1.3.1.2,
ϕϕϕϕ
= -45
oé considerado apenas uma valor RB (Right-Below). Como em 1.3.1.2 o
conjunto difuso RB não está definido numericamente (apenas sabemos
que –90 tem grau de pertinência zero), suponha que
µ
RB(-45) = .7 !!!
SE
Distância X = RC E
Ângulo
ϕϕϕϕ
= RB
ENTÃO
Ângulo
θθθθ
= PB
Como
µ
RC(60) = 1 e
µ
RB(-45) = .7, a regra acima será disparada com
potência de disparo min(1 , .7) = .7 !!!
Assim, o resultado é
θθθθ
= PB com potência de disparo da regra de .7 !!!
O conjunto difuso resultante, que corresponde ao ângulo
θθθθ
será o seguinte:
O valor de
θθθθ
após a defuzificação pelo método do centróide é 26,44
o,
conforme pode ser observado na figura abaixo:
Foi dito que
ϕ
’ =
ϕ
+
θ
. Observe a Figura 10 abaixo para entender
porquê :
Fig. 10 – Novo ângulo
ϕϕϕϕ
’ é resultante da soma de
ϕϕϕϕ
com
θθθθ
.
Assim o novo valor
ϕϕϕϕ
’ =
ϕϕϕϕ
+
θθθθ
= -45
o+ 26.44
o= -18.56
o.
1.3.3.2 – O cálculo da nova posição (X’,Y’) do caminhão
•
Continuando a situação-exemplo da seção anterior, o que se deseja é
calcular a nova posição (X’,Y’) do caminhão.
•
O deslocamento “instantâneo” ocorre a determinada velocidade constante
de marcha-ré do caminhão ( 1, 2, 3, 4 ou 5)
Fig. 11 – Cálculo da nova posição (X’ , Y’).
•
Observe que na Figura 11 também é apresentado o cálculo de (X’ , Y’)
•
Na situação-exemplo, supondo V = 2 temos então:
X’ = X + V cos(
ϕϕϕϕ
’) = 60 + 2 cos(-18,56
o) = 60 + (2 * 0,948) = 61,896
Y’ = Y + V sen(
ϕϕϕϕ
’) = 30 + 2 sen(-18,56
o) = 30 + (2 * -0,318) = 29,364
Obs.: Note que
cos(-18,56
o) = -0,948 e não +0,948. Deve-se inverter o sinal
porquê o programa Truck.exe adotou como convenção 360
o= 0
oo semi-eixo
oposto ao que é normalmente apresentado quando se usa o círculo
Fig. 12 – Orientação do ângulo
ϕϕϕϕ
do caminhão com o eixo dos X e Círculo trigonométrico
“convencional”
1.3.3.3 – RESUMO: cálculo da nova posição (X’,Y’) do caminhão
1) Variáveis de entrada: X e
ϕϕϕϕ
2) Avaliar, entre as 35 regras, quais serão acionadas e dispará-las.
3) O resultado das regras disparadas é a variável
θθθθ
4) Calcular:
4.1)
ϕϕϕϕ
’ =
ϕϕϕϕ
+
θθθθ
4.2) X’ = X + V cos(
ϕϕϕϕ
’)
4.3) Y’ = Y + V sen(
ϕϕϕϕ
’)
1.3.4 – O funcionamento completo do sistema especialista para
estacionar o caminhão
•
O programa TRUCK.exe se propõe a executar o estacionamento do
caminhão na parte “inferior” do pátio (veja na Figura 2)
•
Um esqueleto básico para este algoritmo poderia ser o abaixo apresentado:
Y´ = - 999
Ler Variáveis de entrada: X e
ϕϕϕϕ
Enquanto Y’ <> 100 faça:
1) avaliar, entre as 35 regras, quais serão acionadas e
dispará-las
2) defuzificar a variável
θθθθ
3) calcular
ϕϕϕϕ
’ =
ϕϕϕϕ
+
θθθθ
Questão 1
Objetivo: Construir um arquivo GIF animado mostrando a movimentação do caminhão
em marcha à ré para cada uma das situações (testes) abaixo:
Teste N
oX
Y
ϕ
Velocidade
inicial
1
20
30
0
o2
2
20
30
180
o2
3
70
25
90
o1
4
70
10
270
o3
5
70
10
350
o1
6
70
25
300
o4
7
10
10
270
o1
8
90
50
270
o1
9
70
25
300
o2
10
22
76
100
o5
11
22
76
100
o1
12
76
27
220
o3
13
22
76
280
o1
14
33
44
220
o3
15
10
15
320
o4
16
12
85
210
o1
17
12
60
210
o2
18
12
60
277
o4
19
90
30
200
o5
20
5
20
300
o3
21
50
40
279
o4
22
80
80
230
o2
23
90
20
30
o4
24
50
40
333
o3
25
27
33
333
o3
26
20
30
0
o2
27
20
30
180
o2
29
70
10
270
o3
30
70
10
350
o1
31
70
25
300
o4
32
10
10
270
o1
33
90
50
270
o1
34
70
25
300
o2
35
76
22
100
o5
36
50
45
233
o1
37
76
47
280
o3
38
76
22
280
o1
39
33
44
220
o3
40
10
15
320
o4
41
85
12
210
o1
42
12
60
210
o2
43
12
22
277
o4
44
15
42
260
o5
45
5
33
300
o3
46
50
10
279
o4
47
80
12
230
o2
48
90
12
30
o4
49
50
40
333
o3
50
27
33
333
o3
Material a ser elaborado e apresentado ao professor:
Código do fuzzy clips para cálculo de TETA pronto para ser executado
Planilha eletrónica mostrando localizações do caminhão (ver modelo de planilha
abaixo, no exemplo)
Procedimento:
1)
Codifique no FuzzyClips as variáveis linguísticas X,
ϕϕϕϕ
e
θθθθ
conforme as
definições dadas acima para o programa Truck.exe
2)
Codifique no FuzzyClips as regras de processamento conforme as definições
dadas acima para o programa Truck.exe
3)
Faça o valor do fato referente à variável linguística ser um conjunto difuso triangular
centrado no valor da variável com grau de pertinência 1 com amplitude de 0,1 a mais
e a menos deste valor da variável.
3.1) Exemplo: Se X = 84 metros, então, supondo que DISTX seja a variável linguística
X no FuzzyClips e se
ϕϕϕϕ
= 133.7
o, então, supondo que PHI seja a variável
linguística
ϕϕϕϕ
no FuzzyClips temos os fatos codificados conforme abaixo:
4)
Para cada MOVIMENTAÇÃO do caminhão registre, em planilha,
(1)
a sua posição (X, Y),
(2)
o ângulo
ϕϕϕϕ
,
(3)
a velocidade V de marcha a ré,
(4)
o ângulo
θθθθ
(que é resultante do movimento do caminhão) e
(5)
o novo valor (X’, Y’) da nova posição do caminhão
(6) Use obrigatoriamente para as 3 (três) primeiras movimentações a
Velocidade inicial indicada no teste. Depois, escolha livremente a melhor
velocidade para movimentação
ACOMPANHE O EXEMPLO ABAIXO
♦
Suponha que, inicialmente, o caminhão está na posição X = 84 metros e Y = 30
metros, com ângulo
ϕϕϕϕ
= 133.7
oe velocidade de marcha à ré V = 4
♦
Então na planilha fica assim:
♦
Então o ângulo TETA defuzificado pelo processo do centroide vale
θθθθ
= 13,0485
≈
13,05
♦
Agora calculamos o novo valor de PHI:
ϕϕϕϕ
’ =
ϕϕϕϕ
+
θθθθ
ϕϕϕϕ
’ = 133.7 - 13,05 = 120.65
o(veja que aqui subtraiu ao invés de somar TETA. Porquê ?)
♦
Agora calculamos o novo ponto (X’;Y’) do caminhão:
X’ = X + V cos(
ϕ
’)
X’ = 84 + 4 * cos(120.65
o)
X’ = 84 + 4 * -0.50979
X’ = 81.96
Y’ = Y + V sen(
ϕϕϕϕ
’)
Y’ = 30 + 4 * sen(120.65
o)
Y’ = 30 + 4 * 0.860297
Y’ = 33.44
♦
Pronto !!! Agora temos a segunda localização do caminhão. Registre na planilha e
repita a operação para achar a 3
a, 4
a, 5
a, .... localização do caminhão...
♦
Então, para a 3
alocalização do caminhão temos que X = 81.96 e
ϕϕϕϕ
= 120.65
o♦
Aí execute o fuzzyclips com estes fatos para ver qual o ângulo TETA
♦
Então, para a 3
alocalização, o ângulo TETA defuzificado pelo processo do centroide
vale
♦
Agora calculamos o novo valor de PHI:
ϕϕϕϕ
’ =
ϕϕϕϕ
+
θθθθ
ϕϕϕϕ
’ = 120.65 - 16,41 = 104,24
o(veja que aqui subtraiu ao invés de somar TETA. Porquê ?)
♦
Agora calculamos o novo ponto (X’;Y’) do caminhão:
X’ = X + V cos(
ϕ
’)
X’ = 81.96 + 4 * cos(104,24
o)
X’ = 81.96 + 4 * -0.24598
X’ = 80.99
Y’ = Y + V sen(
ϕϕϕϕ
’)
Y’ = 33.44 + 4 * sen(104,24
o)
Y’ = 33.44 + 4 * 0.969274
Y’ = 37.32
♦
Pronto !!! Agora temos a terceira localização do caminhão. Registre na planilha e
repita a operação para achar a 4
a, 5
a, .... localização do caminhão... até ele estacionar
ATENÇÃO !!! Após 3 (três localizações) registradas na planilha, para
acelerar o trabalho de estacionamento do seu caminhão, se você quiser
começe a utilizar, A PARTIR DA 4
aLOCALIZAÇÃO, a velocidade que
melhor convier
♦
Suponha que a planilha abaixo seja o resultado final:
♦
Salve a planilha em formato .txt ou .csv. Veja o exemplo abaixo
♦
No exemplo acima, é importante criar, no arquivo .txt ou .csv um cabeçalho contendo
as seguintes colunas (separadas por ponto-e-vírgula):
LOCALIZACAO;X;Y;PHI;TETA;XLINHA;YLINHA
♦
E vai interessar apenas as colunas LOCALIZACAO, X e Y.
ANEXO
Arquivo patio_caminhao.htm
<html><head>
<script language="JavaScript" type="text/JavaScript" src="jsPatioCaminhao.js"> </script>
</head>
<body onload="f_IniciarTela();">
<center><h2>Exercício do estacionamento do caminhão</h2></center> <hr>
<div id='divMsg' style="display:block; position:relative; background-color:#eeeeee;"> </div>
<hr>
<div id='divArqTrilhaCaminhao' style="display:none; position:relative; background-color:#eeeeee;"> <Table align='Center' border>
<TR><TD> <table border=1> <tr>
<td align='center'>
<font color="#000000"><b>Arquivo com a trilha do caminhão</b></font> </td>
</tr> <tr>
<td align='center'>
Nome do arquivo com a trilha do caminhão:
<input type="file" id="vArqTrilhaCaminhao" name="vArqTrilhaCaminhao[]" multiple maxlength="100" /> </td>
</tr> <tr>
<td align='center'>
Obs.: o arquivo DEVE estar em formato .txt ou .csv e a primeira linha será a linha contendo cabeçalho das colunas </td> </tr> </table> </TD></TR> </Table> </div>
<div id='divArquivoLido' style="display:none; position:relative; background-color:#eeeeee;"> </div>
Arquivo jsPatioCaminhao.js
//--- Variáveis globais ---var gDados = "" var gNomeArq = ""; var gX_Ponto0_noCanvas = -1; var gY_Ponto0_noCanvas = -1; var g_X_ImgRect = -1; var g_Y_ImgRect = -1; var g_Width_ImgRect = -1; var g_Height_ImgRect = -1;var gRaio, gMoldura, gPixelsXporMetro, gPixelsYporMetro;
//---function f_IniciarTela() {
// Check for the various File API support.
// Obs.: é possível testar para apenas um tipo (File, FileREader, FileList, Blob) if (window.File && window.FileReader && window.FileList && window.Blob) { f_Prosseguir(); // Para poder carregar listener do objeto input type=file... }
else {
alert("Este browser não permite ler arquivos da máquina local"); }
}
//---function f_Prosseguir() {
var vTexto, vDiv;
vDiv = document.getElementById('divMsg');
vTexto = "<A href='javascript: f_Prosseguir_2()'> (1) Clique aqui para iniciar...</A>"; vDiv.innerHTML = vTexto;
}
//---function f_Prosseguir_2() {
var vTexto, vDiv;
vDiv = document.getElementById('divMsg');
vTexto = "<A href='javascript: f_LerArquivoComTrilha()'> (2) Clique aqui para abrir o arquivo com a trilha do caminhão...</A>";
vDiv.innerHTML = vTexto; }
}
//---function f_AddListenerParaObjFile() {
var vDiv
document.getElementById('vArqTrilhaCaminhao').addEventListener('change', f_ManipularArqTrilhaCaminhao, false); vDiv = document.getElementById('divArqTrilhaCaminhao'); document.getElementById('divArquivoLido').style.display = 'none'; document.getElementById('divArqTrilhaCaminhao').style.display = 'block'; } //---function f_ManipularArqTrilhaCaminhao(evt) {
//Retrieve the first (and only!) File from the FileList object var vFile, vFileReader, vTexto, vDiv, vAux;
var vConteudoArquivo, vLen, vProximaFuncao; var vTipoArq; vFile = evt.target.files[0]; if (vFile) { gNomeArq = evt.target.files[0].name; vTipoArq = evt.target.files[0].name; if (vTipoArq.length >= 4) { vTipoArq = vTipoArq.substring(vTipoArq.length-4,vTipoArq.length); }
if ( (!vFile.type.match('text.*')) && (vTipoArq !== '.csv') && (vTipoArq !== '.CSV') ) { alert("Arquivo não apresenta formato txt ou csv");
} else {
gNomeArq = vFile.name;
vDiv = document.getElementById('divArquivoLido'); vTexto = "Nome do arquivo: <b>" + gNomeArq + "</b>"; vTexto += "<p>";
vDiv.innerHTML = vTexto;
document.getElementById('divArqTrilhaCaminhao').style.display = 'none'; document.getElementById('divArquivoLido').style.display = 'block';
//---//---> Criar um objeto reader de arquivo... vFileReader = new FileReader();
//---> Declara apenas a função que diz o que fazer ao terminar a leitura.... vFileReader.onload = function(e) { vConteudoArquivo = e.target.result; vLen = parseInt(vConteudoArquivo.length,10); gDados = vConteudoArquivo.substring(0,vLen); vProximaFuncao = 'f_ManipularArqTrilhaCaminhao_A()'; eval(vProximaFuncao); }
//---> Aqui aciona efetivamente a leitura... vFileReader.readAsText(vFile); }
}
//---function f_ManipularArqTrilhaCaminhao_A() {
//---> Em gDados está o conteúdo do arquivo lido como texto //---> Forçamos o modo síncrono...
var vTexto, vDiv;
vDiv = document.getElementById('divArquivoLido'); vTexto = "<table border=1 id='tbArqTrilha'>"; vTexto += "<tr id='row1'>";
vTexto += "<td valign='top'>";
vTexto += "Nome do arquivo: <b>" + gNomeArq + "</b>"; vTexto += "<br>";
vTexto += "<p>";
vTexto += "<textarea rows='4' cols='50'>"; vTexto += gDados; vTexto += "</textarea>"; vTexto += "</td>" vTexto += "<td width='5%'> </td>"; vTexto += "<td> </td>"; vTexto += "</tr>"; vTexto += "</table>"; vDiv.innerHTML = vTexto; document.getElementById('divArqTrilhaCaminhao').style.display = 'none'; document.getElementById('divArquivoLido').style.display = 'block'; clearTimeout();
setTimeout(f_ManipularArqTrilhaCaminhao_B(), 500); // dispara a função após 500 milisegundos }
//---function f_ManipularArqTrilhaCaminhao_B() {
//---> Em gDados está o arquivo lido com a trilha do caminhao var k, vLinha, vLen, vTexto, vDados;
var vRow, vCells;
vDados = gDados;
k = vDados.indexOf("\n"); // pegar primeira linha (deve ser X;Y) ... if (k >= 0) {
vLinha = vDados.substring(0,k-1); // \n tem dois bytes... descontar um byte... vLinha = f_TransformaLinhaEmCsv(vLinha); vLen = vDados.length; vDados = vDados.substring(k+1,vLen); } else { vLinha = "???"; } if (vLinha === "LOCALIZACAO;X;Y;PHI;TETA;XLINHA;YLINHA") { f_ManipularArqTrilhaCaminhao_C(); }
vTexto += "<p><p><b>LOCALIZACAO;X;Y;PHI;TETA;XLINHA;YLINHA<b>"; vRow = document.getElementById("row1"); vCells = vRow.getElementsByTagName("td"); vCells[2].innerHTML = vTexto; } } //---function f_ManipularArqTrilhaCaminhao_C() {
//---> Em gDados está o arquivo lido com a trilha do caminhao var vTexto;
var vRow, vCells;
vTexto = "<canvas id='cCanvas_Patio' width='500' height='500' style='border:1px solid #000000;'>"; vTexto += "</canvas>"; vRow = document.getElementById("row1"); vCells = vRow.getElementsByTagName("td"); vCells[2].innerHTML = vTexto; vTexto = "<p>"; vTexto += "<center>";
vTexto += "Temporizador de movimento: "
vTexto += "<input type='text' id='txtMilissegundos' size='4' maxlength='4' value='1000'> milissegundos"; vTexto += "<p>";
vTexto += "<A href='javascript: f_ManipularArqTrilhaCaminhao_D()'> MOSTRAR TRILHA DO CAMINHÃO</A>"; vTexto += "</center>";
vRow = document.getElementById("row1"); vCells = vRow.getElementsByTagName("td");
vCells[0].innerHTML = vCells[0].innerHTML + vTexto; }
//---function f_ManipularArqTrilhaCaminhao_D() {
//---> Em gDados está o arquivo lido com a trilha do caminhao var vDados, vLinha, vLen, k, vAux, vCanvas, vContexto; var vLocalizacao, vX, vY, vPhi, vTeta, vXlinha, vYlinha; //---> Limpar área do canvas...
vCanvas = document.getElementById("cCanvas_Patio"); vContexto = vCanvas.getContext("2d");
vContexto.clearRect(0,0,vCanvas.width,vCanvas.height); // limpar a área canvas... //---> "zerar" última posição do caminhão
g_X_ImgRect = -1; g_Y_ImgRect = -1; g_Width_ImgRect = -1; g_Height_ImgRect = -1; //---> desenhar o pátio...
gPixelsYporMetro = (vCanvas.height - (2*gMoldura)) / 100; // 100 m = largura do pátio vContexto.beginPath(); vPosX = gX_Ponto0_noCanvas; vPosY = gY_Ponto0_noCanvas; vContexto.moveTo(vPosX,vPosY); vPosX = gX_Ponto0_noCanvas; vPosY = gMoldura; vContexto.lineTo(vPosX,vPosY); vContexto.stroke(); vPosX = gX_Ponto0_noCanvas; vPosY = gY_Ponto0_noCanvas; vContexto.moveTo(vPosX,vPosY);
vPosX = vCanvas.width - gX_Ponto0_noCanvas; vPosY = gY_Ponto0_noCanvas;
vContexto.lineTo(vPosX,vPosY); vContexto.stroke();
//---> Marcar ponto de estacionamento
vPosX = gX_Ponto0_noCanvas + ((vCanvas.width - gX_Ponto0_noCanvas) / 2); vPosY = gY_Ponto0_noCanvas
vContexto.moveTo(vPosX,vPosY);
vPosX = gX_Ponto0_noCanvas + ((vCanvas.width - gX_Ponto0_noCanvas) / 2); vPosY = gY_Ponto0_noCanvas + (gMoldura/2);
vContexto.lineTo(vPosX,vPosY); vContexto.stroke();
vPosX = gX_Ponto0_noCanvas + ((vCanvas.width - gX_Ponto0_noCanvas) / 2); vPosY = gY_Ponto0_noCanvas
vContexto.moveTo(vPosX,vPosY);
vPosX = gX_Ponto0_noCanvas + ((vCanvas.width - gX_Ponto0_noCanvas) / 2); vPosY = gY_Ponto0_noCanvas - (gMoldura/2);
vContexto.lineTo(vPosX,vPosY); vContexto.stroke();
//---> 0 mm...
vPosX = gX_Ponto0_noCanvas - 5;
vPosY = gY_Ponto0_noCanvas + (1.5* (gMoldura/2)); vTexto = "0 m";
vContexto.beginPath(); // começa outra configuração (cor, espessura, etc...) vContexto.fillStyle = 'blue';
vContexto.fillText(vTexto, vPosX, vPosY); //---> 50 mm...
vPosX = gX_Ponto0_noCanvas + ((vCanvas.width - gX_Ponto0_noCanvas) / 2) - 15; vPosY = gY_Ponto0_noCanvas + (1.5* (gMoldura/2));
vTexto = "50 m";
vContexto.beginPath(); // começa outra configuração (cor, espessura, etc...) vContexto.fillStyle = 'blue';
vContexto.fillText(vTexto, vPosX, vPosY); //---> 100 mm...
vPosX = (vCanvas.width - gX_Ponto0_noCanvas) - 5; vPosY = gY_Ponto0_noCanvas + (1.5* (gMoldura/2)); vTexto = "100 m";
vContexto.beginPath(); // começa outra configuração (cor, espessura, etc...) vContexto.fillStyle = 'blue';
vContexto.fillText(vTexto, vPosX, vPosY); //---> Desenhar aPosicao-ésima do caminhão... f_DesenharCaminhaoNaLocalizacao(1);
//---function f_DesenharCaminhaoNaLocalizacao(aLocalizacao) { //---> Em gDados está o arquivo lido com a trilha do caminhao var vDados, vLinha, vLen, k, vAux, vCanvas, vContexto; var vLocalizacao, vX, vY, vPhi, vTeta, vXlinha, vYlinha; var vAchouLocalizacao, vProximaLocalizacao;
var vTemporizador = document.getElementById("txtMilissegundos").value; //---> Acessar o canvas... vCanvas = document.getElementById("cCanvas_Patio"); vContexto = vCanvas.getContext("2d"); vAchouLocalizacao = "N"; vDados = gDados;
k = vDados.indexOf("\n"); // pegar linha
while ( (k >= 0) && (vAchouLocalizacao === "N") ){
vLinha = vDados.substring(0,k-1); // \n tem dois bytes... descontar um byte... vLinha = f_TransformaLinhaEmCsv(vLinha);
fg_TrimLeft(fg_TrimRight(vLinha)); vLen = vDados.length;
//---> Pegar coluna LOCALIZACAO... m = vLinha.indexOf(";"); vLocalizacao = vLinha.substring(0,m); vLinha = vLinha.substring(m+1,vLen); vLen = vLinha.length; if (parseInt(vLocalizacao) === parseInt(aLocalizacao)) { vAchouLocalizacao = "S"; } //---> Pegar coluna X... m = vLinha.indexOf(";"); vX = vLinha.substring(0,m); vX = parseFloat(vX,10); vLinha = vLinha.substring(m+1,vLen); vLen = vLinha.length;
//---> Pegar coluna Y...
m = vLinha.indexOf(";"); vY = vLinha.substring(0,m); vY = parseFloat(vY,10);
vLinha = vLinha.substring(m+1,vLen); vLen = vLinha.length;
//---> Pegar coluna PHI... m = vLinha.indexOf(";"); vPhi = vLinha.substring(0,m); vLinha = vLinha.substring(m+1,vLen); vLen = vLinha.length;
//---> Pegar coluna TETA... m = vLinha.indexOf(";"); vTeta = vLinha.substring(0,m); vLinha = vLinha.substring(m+1,vLen);
//---> Pegar coluna YLINHA... vYlinha = vLinha;
//---> Próxima linha (proxima localizacao)... vLen = vDados.length;
vDados = vDados.substring(k+1,vLen);
k = vDados.indexOf("\n"); // pegar proxima linha } // end-while
//--->
//---> Tem retângulo imagem anterior ? Então restaura... if ( (g_X_ImgRect >= 0) && (g_Y_ImgRect >= 0) ) {
vContexto.clearRect(g_X_ImgRect,g_Y_ImgRect,g_Width_ImgRect,g_Height_ImgRect); vContexto.putImageData(g_ImgRect,g_X_ImgRect,g_Y_ImgRect);
}
//---> Salvar área onde está o caminhão em vX, vY com vRaio... g_X_ImgRect = vX - gRaio - 1; if (g_X_ImgRect < 0) { g_X_ImgRect = 0; } g_Y_ImgRect = vY - gRaio - 1; if (g_Y_ImgRect < 0) { g_Y_ImgRect = 0; } g_Width_ImgRect = (gRaio * 2) + 2; g_Height_ImgRect = (gRaio * 2) + 2;
g_ImgRect = vContexto.getImageData(g_X_ImgRect, g_Y_ImgRect, g_Width_ImgRect, g_Height_ImgRect); if (vAchouLocalizacao === "S") {
vContexto.beginPath(); // começa outra configuração (cor, espessura, etc...) vX = (vX * gPixelsXporMetro) + gX_Ponto0_noCanvas;
vY = (vY * gPixelsYporMetro) + gMoldura; vContexto.arc(vX, vY, gRaio, 0, 2 * Math.PI, false); vContexto.fillStyle = 'green'; vContexto.fill(); vContexto.lineWidth = 1; vContexto.strokeStyle = '#003300'; vContexto.stroke(); //---> Proxima localização... vProximaLocalizacao = parseInt(aLocalizacao) + 1; vAux = "f_DesenharCaminhaoNaLocalizacao("; vAux += "'" + vProximaLocalizacao + "'"; vAux += ")";
setTimeout(vAux,vTemporizador); // daqui a vTemporizador milissegundos desenha no canvas... }
else {
//---> Caso queira informar final do processo... faça aqui... }
}
//---function f_TransformaLinhaEmCsv(aLinha) {
var vLinha, vLinhaAux, k, vTemPontoVirgula, vChar; vTemPontoVirgula = "N";
for (k = 0; k < vLinhaAux.length; k++) { vChar = vLinhaAux.substring(k,k+1); if (vChar === ";") {
vLinha = vLinha + vChar; vTemPontoVirgula = "S"; } else if (vChar === " ") { if (vTemPontoVirgula === "N") { vLinha = vLinha + ";"; vTemPontoVirgula = "S"; } }
// else if (vChar === chr(9)) { codificar chr(9) tab 31/12/2012 // if (vTemPontoVirgula === "N") { // vLinha = vLinha + ";"; // vTemPontoVirgula = "S"; // } // } else {
vLinha = vLinha + vChar; } } return vLinha; } //---function fg_TrimLeft( str ) { var resultStr = ""; var i = len = 0;
// Return immediately if an invalid value was passed in if (str+"" === "undefined" || str === null)
return null;
// Make sure the argument is a string str += "";
if (str.length === 0) resultStr = ""; else {
// Loop through string starting at the beginning as long as there // are spaces.
// len = str.length - 1; len = str.length;
while ((i <= len) && (str.charAt(i) === " ")) i++;
// When the loop is done, we're sitting at the first non-space char, // so return that char plus the remaining chars of the string. resultStr = str.substring(i, len);
}
return resultStr; }
if (str+"" === "undefined" || str === null) return null;
// Make sure the argument is a string str += "";
if (str.length === 0) resultStr = ""; else {
// Loop through string starting at the end as long as there // are spaces.
i = str.length - 1;
while ((i >= 0) && (str.charAt(i) === " ")) i--;
// When the loop is done, we're sitting at the last non-space char, // so return that char plus all previous chars of the string. resultStr = str.substring(0, i + 1);
}
return resultStr; }