Estacionamento do Caminhão
Transcrição
Estacionamento do Caminhão
Sistemas Especialistas Difusos (Fuzzy Expert Systems) : FuzzyClips Exercício: Estacionamento do Caminhão 1 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, ϕ = 90o) Fig. 1 – Desenho esquemático do pátio de manobras do caminhão 2 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) Truck speed (velocidade constante de marcha-ré do caminhão) 3 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 (ϕ ϕ) = 235o e 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, ϕ = 235o e velocidade = 2) 4 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 No 1 2 3 4 5 6 7 8 9 10 11 12 13 X 20 20 70 70 70 10 10 90 90 22 22 22 22 Y 30 30 25 10 10 10 10 50 50 76 76 76 76 ϕ 0o 180o 90o 270o 350o 270o 270o 270o 270o 100o 100o 280o 280o Velocidade 2 2 1 3 1 2 1 1 2 5 1 5 1 Resultado Ok Ok Ok Ok Ok ? Ok Ok ? Ok Ok Ok 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. 3) Teste outras situações iniciais... 5 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 θ. Fig. 5 – Variáveis de entrada (X e ϕ) e variável de saída (θ θ) 6 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 7 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 8 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 9 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: Fig. 8 – As 35 regras de controle do programa Truck.exe 10 • Na Figura 8 podemos ver as 35 regras inicialmente propostas pelos projetistas do programa Truck.exe. Por exemplo: SE Distância X = LE Ângulo ϕ = RB ENTÃO Ângulo θ = PS SE Distância X = LC Ângulo ϕ = RB ENTÃO Ângulo θ = PM SE Distância X = LC Ângulo ϕ = RU ENTÃO Ângulo θ = PS SE Distância X = CE Ângulo ϕ = VE ENTÃO Ângulo θ = ZE SE Distância X = RC Ângulo ϕ = LU ENTÃO Ângulo θ = NS E E E E E • É 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. 11 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 ϕ = 315o = - 45o (Ver Figura 9). 12 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, ϕ = -45o é 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 !!! Da Figura 8, que apresenta o conjunto de 35 regras de controle de cálculo do ângulo θ temos que: 13 SE Distância X = RC Ângulo ϕ = RB ENTÃO Ângulo θ = PB E 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,44o , conforme pode ser observado na figura abaixo: 14 Foi dito que ϕ’ = ϕ + θ. Observe a Figura 10 abaixo para entender porquê : 15 Fig. 10 – Novo ângulo ϕ’ é resultante da soma de ϕ com θ . Assim o novo valor ϕ’ = ϕ + θ = -45o + 26.44o = -18.56o. 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) • Esta velocidade nada mais é do que a hipotenusa do triângulo retângulo apresentado abaixo na Figura 11: 16 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 ) = 60 + (2 * 0,948) = 61,896 o Y’ = Y + V sen(ϕ’) = 30 + 2 sen(-18,56 ) = 30 + (2 * -0,318) = 29,364 o o Obs.: Note que cos(-18,56 ) = -0,948 e não +0,948. Deve-se inverter o sinal porquê o programa Truck.exe adotou como convenção 360o = 0o o semi-eixo oposto ao que é normalmente apresentado quando se usa o círculo trigonométrico em Matemática (ver Figuras 6, 9 e 10). Veja a Figura 12 abaixo 17 Fig. 12 – Orientação do ângulo “convencional” 18 ϕ do caminhão com o eixo dos X e Círculo trigonométrico 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 ϕ’ = ϕ + θ 4) calcular X’ = X + V cos(ϕ ϕ’) 5) calcular Y’ = Y + V sen(ϕ ϕ’) Fim-Enquanto 19 Questão 1 Objetivo: Apresentar a movimentação do caminhão em marcha à ré usando o código javascript em anexo para cada uma das situações (testes) abaixo: 20 Teste No X Y ϕ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 20 20 70 70 70 70 10 90 70 22 22 86 22 33 10 12 12 12 90 5 50 80 90 50 27 20 20 70 30 30 25 10 10 25 10 50 25 76 76 27 76 44 15 85 60 60 30 20 40 37 20 40 33 30 30 25 0o 180o 90o 270o 350o 300o 270o 270o 300o 100o 100o 220o 280o 220o 320o 210o 210o 277o 200o 300o 279o 230o 30o 333o 333o 0o 180o 90o Velocidade inicial 2 2 1 3 1 4 1 1 2 5 1 3 1 2 4 1 2 4 5 3 4 2 4 3 3 2 2 1 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 70 70 70 10 90 70 76 50 76 76 81 10 85 12 12 15 5 50 80 90 50 27 10 10 25 10 50 25 22 45 47 22 35 15 12 60 22 42 39 10 12 12 40 33 270o 350o 300o 270o 270o 300o 100o 233o 280o 280o 220o 320o 210o 210o 277o 260o 300o 279o 230o 30o 333o 333o 3 1 4 1 1 2 5 1 3 1 3 4 1 2 4 5 3 4 2 4 3 3 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) Execução do deslocamento do caminhão usando a página html e o código javascript apresentados abaixo no ANEXO 1 21 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 o X no FuzzyClips e se ϕ = 133.7 , 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) (2) (3) (4) (5) a sua posição (X, Y), o ângulo ϕ, a velocidade V de marcha a ré, o ângulo θ (que é resultante do movimento do caminhão) e o novo valor (X’, Y’) da nova posição do caminhão (6) Use obrigatoriamente para as 2 (duas) primeiras movimentações a Velocidade inicial indicada no teste. Depois, escolha livremente a melhor velocidade para movimentação 22 ACOMPANHE O EXEMPLO ABAIXO ♦ Suponha que, inicialmente, o caminhão está na posição X = 84 metros e Y = 30 o metros, com ângulo ϕ = 133.7 e velocidade de marcha à ré V = 4 ♦ Então na planilha fica assim: ♦ Vamos executar o FuzzyClips para calcular TETA, com as condições acima: 23 ♦ 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.65o (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(ϕ’) Y’ = Y + V sen(ϕ ϕ’) X’ = 84 + 4 * cos(120.65o) Y’ = 30 + 4 * sen(120.65o) X’ = 84 + 4 * -0.50979 Y’ = 30 + 4 * 0.860297 X’ = 81.96 Y’ = 33.44 ♦ Pronto !!! Agora temos a segunda localização do caminhão. Registre na planilha e repita a operação para achar a 3a, 4a, 5a, .... localização do caminhão... ♦ Então, para a 3a localização do caminhão temos que X = 81.96 e ϕ = 120.65o ♦ Codifique estes fatos no FuzzyClips assim: 24 ♦ Aí execute o fuzzyclips com estes fatos para ver qual o ângulo TETA ♦ Então, para a 3a localização, o ângulo TETA defuzificado pelo processo do centroide vale θ = 16,40762 ≈ 16,41 25 ♦ Agora calculamos o novo valor de PHI: ϕ’ = ϕ + θ ϕ’ = 120.65 - 16,41 = 104,24o (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(ϕ’) Y’ = Y + V sen(ϕ ϕ’) X’ = 81.96 + 4 * cos(104,24o) Y’ = 33.44 + 4 * sen(104,24o) X’ = 81.96 + 4 * -0.24598 Y’ = 33.44 + 4 * 0.969274 X’ = 80.99 Y’ = 37.32 ♦ Pronto !!! Agora temos a terceira localização do caminhão. Registre na planilha e repita a operação para achar a 4a, 5a, .... localização do caminhão... até ele estacionar ATENÇÃO !!! Após 2 (duas 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 3a LOCALIZAÇÃO, a velocidade que melhor convier ♦ Finalmente, após ter registrado na planilha todos os pontos (X,Y) mostre-os na página html (com javascript) apresentada no anexo 26 ♦ 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. ♦ Execute a página html (está em anexo) e abra o arquivo .txt (ou .csv) que você salvou). O resultado será algo parecido com a seguinte imagem: 27 *** FIM DO EXERCÍCIO *** 28 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> <hr> </body> </html> 29 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_LerArquivoComTrilha() { f_AddListenerParaObjFile(); 30 //-------------------------------------------------------------}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); } } else { gNomeArq = ""; vTexto = "<LI><img src='../ppmbimg/subitem01.gif' border=0> " + "Não conseguiu ler o arquivo" + "</LI>"; fpmb01_MensagensCliente(vTexto,'divMsg','f002_MostrarDiv','',''); } 31 //-------------------------------------------------------------}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(); } else { vTexto = "<p><b>A primeira linha do arquivo não contém o cabeçalho esperado</b>"; vTexto += "<p> O cabeçalho esperado é o seguinte:"; 32 vRow = document.getElementById("row1"); vCells = vRow.getElementsByTagName("td"); vTexto += "<p><p><b>LOCALIZACAO;X;Y;PHI;TETA;XLINHA;YLINHA<b>"; 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... gRaio = 8; gMoldura = 30; gX_Ponto0_noCanvas = gMoldura; gY_Ponto0_noCanvas = vCanvas.height - gMoldura; gPixelsXporMetro = (vCanvas.width - (2*gMoldura)) / 100; // 100 m = comprimento do pátio 33 vContexto.beginPath(); gPixelsYporMetro = (vCanvas.height - (2*gMoldura)) / 100; // 100 m = largura do pátio 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); } 34 //-------------------------------------------------------------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); vLen = vLinha.length; //---> Pegar coluna XLINHA... m = vLinha.indexOf(";"); vXlinha = vLinha.substring(0,m); vLinha = vLinha.substring(m+1,vLen); vLen = vLinha.length; 35 vYlinha = vLinha; //---> Próxima linha (proxima localizacao)... //--->vLen Pegar coluna=YLINHA... 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"; vLinha = ""; vLinhaAux = aLinha; vLinhaAux = fg_TrimLeft(fg_TrimRight(vLinhaAux)); 36 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; } //-------------------------------------------------------------------------------function fg_TrimRight( str ) { var resultStr = ""; var i = 0; // Return immediately if an invalid value was passed in 37 return null; // Make sure the argument is a string if str(str+"" += ""; === "undefined" || str === null) 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; } 38