IMPLEMENTAÇÃO DE SENSORES NO MUNDO DOS ATORES · objetos, fazendo parte do sistema. ......
Transcript of IMPLEMENTAÇÃO DE SENSORES NO MUNDO DOS ATORES · objetos, fazendo parte do sistema. ......
1
UNIVERSIDADE FEDERAL DE SANTA CATARINA
IMPLEMENTAÇÃO DE SENSORES NO MUNDO DOS ATORES
AUTOR: Fabrício Barcellos Aguirre
2003-2 ¦¦ Implementação de Sensores no Mundo dos Atores ¦¦ UFSC
2
UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA
CURSO DE CIÊNCIAS DA COMPUTAÇÃO
TÍTULO: IMPLEMENTAÇÃO DE SENSORES NO MUNDO DOS ATORES
AUTOR: Fabrício Barcellos Aguirre ORIENTADOR: Antônio Carlos Mariani BANCA EXAMINADORA: Edla Maria Faust Ramos Raul Sidnei Wazlawick PALAVRAS-CHAVE: Sensores, Informática na Educação, Mundo dos Atores, Smalltalk
Florianópolis, Fevereiro de 2003
3
SUMÁRIO
LISTA DE FIGURAS........................................................................................................VII
RESUMO............................................................................................................................VIII
INTRODUÇÃO .................................................................................................................9
1 LEVANTAMENTO PRELIMINAR .......................................................................11
1.1 MUNDO DOS ATORES ..............................................................................11
1.1.1 O que é o Mundo dos Atores e seus objetivos................................11
1.1.2 Como Funciona ..............................................................................13
1.1.3 Palco da Caneta ..............................................................................15
1.1.4 Palco de Sinuca...............................................................................17
1.1.5 Dificuldades....................................................................................18
1.2 A LINGUAGEM SMALLTALK..................................................................19
1.2.1 Histórico .........................................................................................19
1.3 DESCRIÇÃO DE ALGUNS PALCOS.........................................................20
1.3.1 PalcoMeioAmbiente .......................................................................21
1.3.2 PalcoDeTransito .............................................................................21
2 SENSORES NO MUNDO..........................................................................................22
2.1 SENSORES X ATUADORES ......................................................................22
2.1.1 Sensores ..........................................................................................22
2.1.2 Atuadores .......................................................................................24
2.2 TIPOS DE SENSORES NA ROBÓTICA ...................................................26
2.2.1 Sensores de Contato ......................................................................26
2.2.2 Sensores sem Contato ....................................................................27
2.3 TIPOS ESPECIAIS DE SENSORES ...........................................................28
2.3.1 Sensores de Contraste (detectores de marcas) ...............................28
2.3.2 Sensores tipo Forquilha (garfo) .....................................................28
4
2.3.3 Sensores de Distância ....................................................................28
2.3.4 Sensores de Luminescência ...........................................................29
2.3.5 Sensores de Cor .............................................................................29
2.3.6 Sensores de Visão ..........................................................................29
2.3.7 Sensores de Infravermelho ............................................................29
2.3.8 Sensores de Posição .......................................................................29
2.4 SENSORES EM VRML ...............................................................................30
2.4.1 Sensor de Passagem do Tempo .....................................................30
2.4.2 Sensor de Final de Curso ...............................................................30
2.4.3 Sensor de Movimentação em Cilindro ..........................................30
2.4.4 Sensor de Visão de Planos .............................................................30
2.4.5 Sensor de Visão de Esferas ............................................................31
2.4.6 Sensor de Proximidade ..................................................................31
2.4.7 Sensor de Colisão ..........................................................................31
2.4.8 Sensor de Visibilidade ...................................................................31
3 – DESCRIÇÃO DE PAPÉIS COM SENSORES ........................................................32
3.1 SENSORES – DESCRIÇÃO E COMENTÁRIOS ......................................32
3.2 SENSORES ATIVOS E SENSORES PASSIVOS ......................................32
3.2.1 Sensores Passivos ..........................................................................33
3.2.2 Sensores Ativos .............................................................................33
3.3 PRINCÍPIOS DO SENSORIAMENTO DISCRETO ..................................34
3.4 ENCAPSULAMENTO ................................................................................35
3.5 HIERARQUIA DE SENSORES ..................................................................37
3.6 ANÁLISE DE ALGUNS PALCOS .............................................................38
3.6.1 PalcoMeioAmbiente ......................................................................38
3.6.2 PalcoDeTransito ............................................................................39
3.7 SENSORES IMPLEMENTADOS ...............................................................39
3.7.1 Classe Sensor .................................................................................39
3.7.1.1 Descrição dos Atributos .................................................40
3.7.1.1.1 ator ...................................................................40
3.7.1.1.2 acao ..................................................................40
5
3.7.1.1.3 acaoDeFalha ....................................................40
3.7.1.1.4 nome ................................................................40
3.7.1.2 DESCRIÇÃO DOS MÉTODOS ........................................41
3.7.1.2.1 acao: umSimbolo .............................................41
3.7.1.2.2 ativado .............................................................41
3.7.1.2.3 ator: umAtor ....................................................41
3.7.1.2.4 executa .............................................................41
3.7.1.2.5 initialize ...........................................................41
3.7.1.2.6 isSensor ............................................................41
3.7.1.2.7 nome ................................................................41
3.7.1.2.8 nome: umString ...............................................41
3.7.2 CLASSES DE SENSORES ...............................................................42
3.7.2.1 Classe Sensor De Área ...................................................42
3.7.2.2 Classe Sensor De Borda .................................................42
3.7.2.3 Classe Sensor De Atores ................................................42
3.7.2.4 Classe Sensor De Proximidade .......................................43
3.7.2.5 Classe Sensor De Toque .................................................44
3.7.2.6 Classe Sensor De Visão ..................................................44
3.8 USO DOS SENSORES ....................................................................................45
3.8.1 Dicionário de Sensores ..................................................................45
3.8.2 Métodos de Verificação .................................................................46
3.8.3 Inserção no Schedule do ator .........................................................47
3.8.3.1 Descrição dos métodos ...................................................48
3.8.3.2 Mudanças no Schedule ...................................................49
3.8.3.2.1 Métodos Principais ..........................................49
3.8.3.2.2 Implementação ................................................50
3.8.4 Sensores com Interrupções ............................................................53
3.9 DEFINIÇÃO DE PAPÉIS EM ATORES COM SENSORES .....................54
3.9.1 PalcoMeioAmbiente ......................................................................54
3.9.2 PalcoDeTransito ............................................................................62
3.9.3 Comentários ...................................................................................66
4 CONSIDERAÇÕES FINAIS ....................................................................................67
6
4.1 CONCLUSÃO ..............................................................................................67
4.2 TRABALHOS FUTUROS ...........................................................................69
4.2.1 Utilização Prática – Validação ......................................................69
4.2.2 Adição de novas classes ................................................................69
4.2.3 Adição de novos métodos ..............................................................70
4.2.4 Verificação com outros modelos de paralelismo ...........................71
4.3 REFERÊNCIAS BIBLIOGRÁFICAS .........................................................72
4.4 BIBLIOGRAFIA ..........................................................................................74
ANEXO 1 - ARTIGO .......................................................................................................75
ANEXO 2 – CÓDIGO FONTE PRODUZIDO...............................................................90
LISTA DE FIGURAS
7
Figura 1- Mundo dos Atores – Palco...................................................................10
Figura 2- Palco da Caneta....................................................................................14
Figura 3- Palco de Sinuca....................................................................................15
Figura 4- Tela do Smalltalk V/Win .....................................................................18
Figura 5- Sensor de contato de forma esquemática.............................................21
Figura 6- Atuador garra com sensores nas extremidades ....................................22
Figura 7- Sensor de força.....................................................................................25
Figura 8- Sensor de luz........................................................................................26
Figura 9 - Sensores Reativos e Sensores Pró-Ativos...........................................32
Figura 10 – Encapsulamento ...............................................................................34
Figura 11 - Hierarquia de Sensores .....................................................................35
RESUMO
8
Esse trabalho descreve a implementação de sensores na ferramenta didática Mundo dos
Atores. Os sensores são inseridos na ferramenta de maneira natural, como uma hierarquia de
objetos, fazendo parte do sistema.
Os comportamentos dos atores são definidos no papel dos mesmos. Essa descrição dos
comportamentos é algo relativamente complexo, sendo um problema para a aprendizagem.
Uma alternativa para diminuir a complexidade na descrição dos papéis dos atores é a
implementação de sensores no Mundo dos Atores. Com essa alternativa, espera-se facilitar a
descrição dos papéis, diminuindo uma dificuldade na aprendizagem de Orientação a Objetos
utilizando essa ferramenta.
PALAVRAS CHAVE: Sensores, informática na educação, orientação a objetos,
SmallTalk
ABSTRACT
This work describes the implementation of sensors in the didactic tool Mundo dos
Atores. The sensors are inserted in the tool in natural way, as an object hierarchy, being part of
the system.
The behaviors of the actors are defined in the schedule of the them. This description of
the behaviors is something relatively complex, being a problem for the learning. An alternative
to diminish the complexity in the description of the schedules of the actors is the
implementation of sensors in the World of the Actors. With this alternative, is expected to
facilitate the description of the schedules, diminishing the difficulty in the learning of
Orientation the Objects using this tool.
KEYWORDS: Sensors, computer science in the education, object orientation,
SmallTalk
INTRODUÇÃO
9
A Programação Orientada a Objetos (POO) é a mais usual forma de programação,
atualmente. A POO, com características como hierarquia, heranças, atributos, métodos e seus
vários conceitos, trás inúmeras vantagens para os programadores, como possibilidade de
reutilização de código e modularização da programação. Devido a esse conjunto de qualidades
e a grande utilização desta programação no mercado de trabalho, a POO é muito explorada nos
cursos da área de computação, onde muitas vezes esse tipo de programação é ensinado aos
alunos desde as fases iniciais destes cursos.
O grande número de conceitos, assim como a interligação entre eles, acaba fazendo
com que a aprendizagem da Orientação a Objetos seja algo difícil para alguns alunos,
principalmente por aqueles que estão tendo seus primeiros contatos com a computação e a
programação.
Visando diminuir essa dificuldade, foi desenvolvido o Mundo dos Atores. O Mundo
dos Atores é uma ferramenta pensada para auxiliar o processo de aprendizado de Programação
Orientada a Objetos. Com essa ferramenta, procura-se diminuir as dificuldades que possam
surgir no aprendizado, tornando o conteúdo algo acessível para todos os alunos.
A ferramenta Mundo dos Atores é construída e integrada ao ambiente de programação
Smalltalk, permitindo que se explorem desde os conceitos mais básicos aos mais avançados de
POO. O Mundo dos Atores se baseia na programação por atores, em que os objetos não são
simplesmente objetos estáticos, reativos, mas sim objetos dinâmicos, proativos, capazes de agir
conforme forem programados para fazê-lo. Ele se baseia na metáfora palco/ator, na qual os
objetos, que são os atores, estão presentes em um palco (também um objeto), e dentro deste,
realizam as suas ações, trocando mensagens e interagindo entre si e com o próprio palco.
Alguns palcos se apresentam de maneira estática, porém outros, onde há a interação
entre os atores, são baseados num modelo de computação por eventos discretos. Neste modelo,
todos os atores são regidos por um tempo discreto, e realizam suas ações através de um
escalonamento do tempo, realizando troca de mensagens.
As ações que os atores devem realizar, quando estão no palco, seus comportamentos,
são definidas em seus papéis. Essa descrição dos comportamentos é algo que por vezes se
apresenta de maneira relativamente complexa, dificultando muitas vezes o propósito do
ambiente, sendo essa complexidade um problema para a aprendizagem.
Uma alternativa para diminuir a complexidade na descrição dos papéis dos atores,
ponto central a ser aprimorado neste trabalho, é a implementação de sensores no Mundo dos
10
Atores. Com essa alternativa, espera-se facilitar a descrição dos papéis, diminuindo uma
dificuldade na aprendizagem de Orientação a Objetos utilizando essa ferramenta.
Neste trabalho foram implementados sensores, de maneira que a descrição dos papéis
desempenhados pelos atores fosse descrita de uma maneira menos complexa. A noção de
sensores é baseada nos sensores mecânicos existentes na área de engenharia mecânica e
também nos sentidos dos seres vivos, especialmente os humanos.
Os sensores implementados podem ser usados segundo duas alternativas, seguindo a
idéia de sensores passivos (reativos), com os dados sob demanda ou os sensores pró-ativos, com
o sensor sendo capaz de disparar ações nos atores.
CAPÍTULO 1 – LEVANTAMENTO PRELIMINAR
11
1.1 MUNDO DOS ATORES
1.1.1 O que é o Mundo dos Atores e seus objetivos
O Mundo dos Atores (Figura 1) é uma ferramenta pensada para auxiliar o processo de
aprendizado de Programação Orientada a Objetos (POO), com facilidades de maneira a ensinar
de maneira paralela à modelagem e a implementação de sistemas. Por ser implementado e
completamente integrado no ambiente Smalltalk, o Mundo dos Atores oferece uma forma bem
didática de exploração dos conceitos relacionados com a programação orientada a objetos,
partindo dos conceitos mais básicos até os mais avançados. Do primeiro ao último contato com
ele, o aprendiz estará se expressando e se familiarizando de acordo com o paradigma de
orientação a objetos.
Não é necessário nenhum conhecimento prévio sobre técnicas de programação de
computadores para poder interagir com o Mundo dos Atores. Ele necessita, apenas, uma certa
"alfabetização tecnológica" do usuário que desejar utilizá-lo, no que se refere à operação com
um ambiente computacional (saber usar os dispositivos de entrada, como mouse e teclado, ou o
ambiente operacional, devem ser técnicas bem dominadas).
É baseado numa metáfora de palco e atores, de maneira que o aprendiz trabalhe com
elementos virtuais atores e o palco, manipulando objetos, mesmo que não tenha recebido a
explicação formal sobre os objetos. Os atores se encontram dentro do palco, e realizam as suas
ações, trocando mensagens e interagindo entre si e com o próprio palco.
O Mundo dos atores é aberto e expansível. Apresenta um palco mais simples, o Palco
da Caneta, onde existe apenas uma área gráfica (o palco) e um ator (a caneta), e está estruturado
de forma a permitir que o aprendiz também possa definir outros atores e pô-los para interagir,
assim como criar outros palcos particulares, conforme a necessidade. Esta possibilidade de
construção progressiva de modelos cada vez mais complexos é o ponto base para exploração
sistemática dos conceitos da POO.
A ferramenta está implementada na linguagem/ambiente Smalltalk-V/Win, estando em
completa integração com esse ambiente de POO. Com isso o Mundo dos Atores pode ser
12
facilmente integrado com qualquer outra aplicação disponível. Isto significa que o aprendiz não
está restrito aos recursos oferecidos pelo Mundo dos Atores, mas sim livre para utilizar todos os
recursos oferecidos por Smalltalk. Ele é, em realidade, uma aplicação que faz uso dos recursos
do ambiente Smalltalk, inclusive de sua linguagem de programação a qual é utilizada para
descrever o comportamento dos atores e para definir novos palcos. Segundo [Mariani 1998],
esta característica é desejável, pois permite uma passagem gradativa e incremental para o
desenvolvimento de sistemas computacionais completamente independentes do Mundo dos
Atores, a exemplo de aplicações comerciais.
Figura 1: Mundo dos Atores - Palco
Com as características, o Mundo dos Atores é particularmente indicado para utilização
em disciplinas introdutórias de computação ou informática em qualquer nível, assim como
disciplinas de modelagem, programação orientada a objetos ou programação de forma paralela.
Por também apresentar como um de seus componentes internos um ambiente similar ao
oferecido pela linguagem LOGO (Seymour Papert), ele também pode ser utilizado para
explorar vários conceitos matemáticos, assim como exercitar aspectos como desenvolvimento
da criatividade e habilidade estética entre os usuários do sistema.
13
1.1.2 Como Funciona
Alguns palcos se apresentam de maneira estática, onde os atores são inseridos pelo
aprendiz, e respondem a comandos passados a eles na forma de mensagens. Outros palcos, onde
há a interação entre os atores, são baseados num modelo de computação por eventos discretos.
Neste modelo, todos os atores são regidos por um tempo discreto, e realizam suas ações através
de um escalonamento do tempo, realizando troca de mensagens entre si. As ações dos atores,
neste caso, estão descritas num roteiro, que indica seus papéis no palco. A definição desses
papéis possibilita o estabelecimento de comportamentos para os atores. O
PalcoComEventosDiscretos é que responsável por implementar o processo de animação
chamado de modelo de eventos discretos.
Cada objeto que for criado pelo usuário do Mundo dos Atores deve ser uma subclasse da
classe Ator. Nos palcos com eventos discretos, tem-se a classe AtorComEventosDiscretos, que
implementa as operações básicas do tipo de atores que implementam uma forma de paralelismo,
com o uso de papéis para cada ator, tendo um comportamento associado à sua existência no
ambiente. Atores com eventos discretos, associados a um papel, deixam de ser apenas objetos
estáticos (reativos), passando a ser objetos dinâmicos (pró-ativos), pois não apenas reagem a
comandos passados pelo aprendiz, mas sim, desempenham seu comportamento conforme
descrito na descrição do papel.
O método "definePapel" deve ser implementado em todos os atores com eventos
discretos dos quais se deseja a realização de alguma atividade no tempo discreto. Esse método,
o "definePapel" estabelece o 'schedule' de um ator, ou seja, um conjunto de ações que compõem
o seu papel, que ele executará em determinados momentos nos quais estão especificados no seu
papel.
O 'schedule' de um ator consiste em uma tabela em que as linhas contêm uma
condição, seguida de uma ação. Todas as linhas desta tabela são verificadas a cada passo de
interação do tempo discreto. Se a condição for verdadeira, então a ação é executada. Entretanto,
alguns comandos pré-definidos tornam a definição do 'schedule' mais intuitiva. Estes principais
comandos são basicamente: "sempreFaca:", "sempreQue:faca:", "cada:faca" e
"comProbabilidadeDe:faca:", embora outras variações também existam e possam ser
14
implementadas pelo usuário conforme a necessidade de uso num determinado momento.
Seguem alguns exemplos da utilização destes comandos:
self sempreFaca: [self anda: 1;gira: 1].
self sempreQue: [self foraDoPalco] faca: [self invisivel].
self cada: 60 faca: [self apontaPara: self palco centro].
self comProbabilidadeDe: 0.01 faca: [self pulaPara: self palco centro].
Na primeira linha desta tabela, estabelece-se que o ator (representado por 'self') vai, a
cada instante de tempo, mover-se um passo para frente e girar um grau para a direita da direção
onde se encontra.
Na segunda linha, estabelece-se que o ator ficará invisível sempre que perceber que
está fora da área do seu palco.
Na terceira linha da tabela, estabelece-se que a cada 60 instantes de tempo (pode ser
simulado como segundos, minutos, horas, dependendo do modelo) o ator vai se direcionar para
o centro do seu palco, sem sair da posição onde atualmente se encontra.
Na quarta linha, estabelece-se que com probabilidade de 1% o ator poderá a cada passo
pular diretamente para a posição de centro do palco. [Wazlawick 1999].
Uma das características importantes de orientação a objetos que é pouco explorada
hoje em dia, especialmente nos cursos de introdução à computação, é o paralelismo.
Normalmente o aluno aprende a pensar e a modelar os problemas de uma forma seqüencial,
mesmo vivendo em um mundo em que os objetos são todos de existência paralela. O
paralelismo é visto somente em fases avançadas como uma forma de implementação (e
modelagem) alternativa. Nessa visão, o paralelismo é aplicado para processos que envolvem
principalmente o estudo de técnicas de concorrência a recursos, em termos de hardware e
programas básicos como os sistemas operacionais. Este tipo de curso, normalmente no contexto
de sistemas operacionais, não incentivam o aluno a produzir modelos que tenham paralelo com
a realidade. Assim, a maioria dos programas continuam sendo concebidos de forma seqüencial,
com um pensamento adquirido e treinado apenas a isso, programar seqüencialmente, mesmo
quando uma abordagem de modelagem e programação de maneira paralela seria a mais
indicada.
Um controlador de execução faz com que a cada instante cada um dos atores tenha
oportunidade de executar o que está definido em seu papel (seus comandos). Desta maneira,
15
evitam-se os problemas relacionados com a concorrência real, onde os atores poderiam acessar
um recurso simultaneamente (disputa de recursos), e todos os mecanismos de controle
associados a esse problema. Com o modelo de eventos discretos, pode-se trabalhar o conceito
de paralelismo de uma forma bastante simples para o aprendiz, mantendo uma boa
característica didática para, como já foi dito, que não se descuide de atingir os objetivos de
aprendizagem com os alunos.
Segundo [Wazlawick 1999] , seria mais interessante iniciar os estudos de modelagem e
programação com os estudantes utilizando-se diretamente uma abordagem que lhes permita
modelar um problema paralelo da forma mais real possível, de forma paralela. Esta introdução,
entretanto, não pode ser feita de uma forma muito complexa, para que não se descuide de
atingir os objetivos de aprendizagem com os alunos.
Um modelo considerado adequado para ser utilizado na introdução à programação de
forma a ensinar o modelo de paralelismo aos estudantes é o modelo de eventos discretos,
presente no Mundo dos Atores. De uma maneira resumida, pode-se dizer que: “Do primeiro ao
último contato com ele o aprendiz estará ‘falando’ segundo os preceitos da POO”. [Mariani
2001].
1.1.3 Palco da Caneta
O aprendiz inicia o seu trabalho com o Mundo dos Atores num ambiente similar ao
oferecido pela linguagem LOGO (Seymour Papert). O aprendiz pode controlar uma caneta
fazendo-a traçar diferentes desenhos no "palco", a área gráfica onde ela está inserida. Esse
controle é exercido através de mensagens passadas à caneta, representando ações a serem
tomadas pela caneta, como o comando anda: 50 (visto na Figura 2).
16
Figura 2: Palco da Caneta
O ator caneta (objeto pertencente à classe Caneta) tem um conjunto de ações pré-
definidas, mas pode ter facilmente adicionado a si outras ações. Ao interagir com o ator caneta
o aprendiz estará exercitando todo um conjunto de noções básicas de programação de
computadores, assim como noções de algoritmo, variáveis, parâmetros, estruturas de controle
(seqüência, seleção, repetição, recursão), modularização/refinamento e reusabilidade [Mariani
1998]. Mesmo construções sintáticas simples como "caneta anda: 50" são relevantes pois
introduzem o mecanismo básico de comunicação por troca de mensagens inerente à POO. Neste
exemplo o aprendiz passou ao objeto a mensagem anda: tendo o valor 50 como parâmetro. O
objeto caneta, ao receber esta mensagem, realiza a ação passada pelo aprendiz, juntamente com
o parâmetro atrelado à mensagem.
17
1.1.4 Palco de Sinuca
O Palco de Sinuca (Figura 3) pode ser apresentado como um dos mais simples palcos
com eventos discretos. O palco representa uma mesa de sinuca, onde atores do tipo Bola de
Sinuca se movem, refletindo nas laterais da mesa. O comportamento dos atores que fazem parte
deste palco está descrito nos seus papéis.
Figura 3: Palco de Sinuca
O conjunto de ações presentes nos atores Bola de Sinuca permite que elas
desempenhem seus papéis no palco. A descrição dos papéis dos atores Bola de Sinuca faz com
que o comportamento dos atores ao ‘atuarem’ no palco seja o de andar sempre em linha reta,
com um pequeno desvio em uma unidade de tempo, e sempre refletir nas bordas da mesa.
18
1.1.5 Dificuldades
Neste modelo de eventos discretos, em que cada objeto possui um papel (por isso,
muitas vezes, se refere aos objetos como 'atores' do modelo) que define os comandos que
devem ser executados por ele a cada instante (fatia de tempo ou time slice). Esse papel é muitas
vezes denominado como o comportamento do objeto dinâmico.
Como visto na descrição detalhada (em 1.1.2), o 'schedule', ou plano, de cada ator deve
ser programado para que ele desempenhe seu papel no ambiente, definindo de forma que ele
faça, a cada instante desejado de tempo, uma checagem do ambiente, uma movimentação ou
uma alteração no sistema, ou seja, tudo aquilo em que se deseja que o ator faça em termos de
interação com o sistema.
Essa descrição dos comportamentos é algo que por vezes se apresenta de maneira
complexa, contribuindo para muitas vezes dificultar o processo de aprendizagem. Visto que o
propósito do ambiente é facilitar a aprendizagem, servindo como ferramenta prática para uma
disciplina de introdução a POO em cursos de computação/informática [Mariani 1998], essa
complexidade é algo que deve ser diminuído.
19
1.2 A LINGUAGEM SMALLTALK
A linguagem/ambiente de programação usada nesse trabalho é a linguagem Smalltalk-
V/Win (Figura 4), na qual foi desenvolvido o Mundo dos Atores e que tem sido utilizado para
ensino de Programação Orientada a Objetos, servindo como ferramenta prática para uma
disciplina de introdução a POO.
Segundo [Abdala 2002], a linguagem Smalltalk inventou o conceito de orientação a
objetos, sendo também a linguagem mais citada como exemplo de uma linguagem de
programação revolucionária, bem concebida e elegante, sendo ainda, a única linguagem de
programação comercialmente aplicada realmente orientada a objetos. Nada mais adequado,
então, do que se utilizar dessa linguagem para a apresentação de conceitos de orientação a
objetos. Nesse caso, considera-se o uso da linguagem Smalltalk, visto que nela está
implementada a ferramenta Mundo dos Atores.
Smalltalk foi projetado para ser fácil de aprender e usar. É uma linguagem expressiva
que usa um sub conjunto da linguagem humana, baseado em substantivos e verbos. Isso facilita
que se usem expressões claras, bem de acordo com o pensamento humano. Com isso, os
programas em Smalltalk acabam se apresentando bem menores do que programas semelhantes,
feitos em outras linguagens, fazendo mais trabalho com menor quantidade de código, e com
isso, menos custo de produção e manutenção de programas [Launt 2003].
1.2.1 Histórico
A primeira linguagem a incorporar facilidades para definir classes de objetos genéricos
na forma de uma hierarquia de classes e subclasses foi a linguagem denominada Simula. Simula
foi idealizada em 1966, na Noruega, como uma extensão da linguagem ALGOL 60. Como se
faz notar pelo nome, Simula é uma linguagem mais adequada à programação de Simulações de
sistemas.
As idéias de Simula serviram de base para as propostas de utilização de Tipos
Abstratos de Dados [Liskov e Ziller 74] e também para o surgimento do Smalltalk. O Smalltalk
foi desenvolvida no Centro de Pesquisas da empresa Xerox durante a década de 70 , e
incorporou, além das idéias de Simula, um outro conceito importante, o princípio de objetos
ativos. O pesquisador Alan Kay, um dos idealizadores do Smalltalk, deixou claro que uma idéia
20
importante seria o princípio de objetos ativos, prontos para reagir a mensagens recebidas, as
quais ativam os comportamentos específicos do objeto (descritos em sua classe). Ou seja, os
objetos em Smalltalk deixam de ser apenas dados manipulados por programas, e passam a
serem encarados como o que ele chamou de "processadores idealizados" individuais e
independentes uns dos outros, aos quais podem ser transmitidos comandos em forma de
mensagens [Jonathan 1994].
Figura 4: Tela do Smalltalk V/Win
1.3 DESCRIÇÃO DE ALGUNS PALCOS
A seguir tem-se em alguns palcos específicos, com uma descrição do comportamento
dos atores nestes palcos:
21
1.3.1 PalcoMeioAmbiente
Os atores deste palco consultam o palco quanto à proximidade de outros atores.
O Predador, no seu método caça, invoca o método presaMaisProxima para decidir atrás
de qual das presas ele irá partir em perseguição. Esse método é uma consulta ao palco pelo ator
do tipo presa que se apresenta mais próximo da posição do predador.
Os demais atores desse palco são os da classe Presa e suas subclasses, além dos atores
Grama. Eles detectam a comida (atores Grama) e o predador (atores Predador) que se
encontram mais próximos de si, através dos métodos comidaMaisProxima e
predadorMaisProximo. A maneira com que esses métodos agem é semelhante à usada pelo
predador para achar a sua presa a ser caçada. Uma consulta ao palco é feita, com a classe que se
quer a resposta, e o palco devolve uma resposta com o ator mais próximo da presa, pertencente
à classe que lhe foi pedida. Essas ações são tomadas em duas ocasiões distintas, no caso de
atores da classe Grama, no método comidaMaisProxima, utilizado quando a presa procura um
alimento próximo a si; e no outro método, predadorMaisProximo, o qual é sempre utilizado
para que a presa não se encontre muito próxima a um predador qualquer, de maneira a preservar
a sua integridade.
1.3.2 PalcoDeTransito
Os atores principais deste palco, os atores Carro, utilizam-se de verificações do
ambiente para detectar a presença de outro ator Carro, ou de um semáforo, presentes à sua
dianteira. Os carros andam em quatro direções, dos extremos da tela para seus opostos (para
cima, para baixo, para esquerda e para a direita). Para realizar as verificações necessárias há a
implementação de um retângulo na frente do ator, no qual se verificar a visão, consultando se
algum ator desejado encontra-se em contato com esse retângulo. A consulta de toques entre os
atores é realizada com consulta aos métodos presentes no PalcoDeTransito. Com isso se
verifica o toque dos carros entre si e com a área amarela do cruzamento.
22
CAPÍTULO 2 – SENSORES NO MUNDO
Os sensores são baseados nos cinco sentidos dos seres humanos, ou seja, visão, tato,
audição, olfato e paladar. Tem por função, transmitir informações acerca do ambiente para uma
central de controle, semelhante ao cérebro humano, que se encarrega de fazer uso dessas
informações.
O levantamento mostrou que estão presentes principalmente nas áreas de robótica
(engenharia mecânica) e na Realidade Virtual (RV). Os sensores mais variados são os de
robótica, pois essa área apresenta um vasto campo de aplicação. Estes sensores, de robótica são
os que oferecem mais idéias para a implementação deste mecanismo em um ambiente
computacional.
Os sensores que atualmente estão mais desenvolvidos são os sensores de visão, como
radar e sensor de cores e os sensores de tato, como sensores de toque e de força.
2.1 SENSORES X ATUADORES
Os sensores e os atuadores são mecanismos relacionados à robótica, uma área da
engenharia mecânica, assim como algumas outras áreas de estudo. Nos itens 2.1.1 e 2.1.2, vê-se
descrições detalhadas e exemplos destes mecanismos.
2.1.1 Sensores
O sensor (Figura 5) é um dispositivo capaz de monitorar a variação de uma grandeza
física e transmitir esta informação a um sistema de indicação que seja inteligível para o
elemento de controle do sistema. É um dispositivo de entrada que converte um sinal de
qualquer espécie em outro sinal que possa ser transmitido ao elemento indicador, para que este
mostre o valor da grandeza que está sendo medida [Franchin 1999].
Podem ser chamados de Transdutores ativos ou transdutores passivos, pois convertem
os sinais medidos em sinais de um medidor, por exemplo, como a pressão em um ponteiro ou
numa coluna de líquido.
23
Figura 5: Sensor de contato de forma esquemática
Primeiramente, ao se falar em sensores, lembram-se dos sentidos humanos, visão, tato,
audição, olfato e paladar. É através desses sentidos que o ser humano percebe como se encontra
o ambiente em que ele está inserido em um determinado momento, transformando as
informações físicas, recebidas por eles, em impulsos cerebrais nas áreas responsáveis pelo
processamento desses dados no cérebro. Os sentidos humanos são, portanto, transdutores
ativos.
Pensando-se na maneira com que esses 'sensores humanos' interagem com o ambiente
e o próprio ser, a robótica tem obtido avanços em adaptar esses sensores em suas tecnologias,
nas funções semelhantes às em que desempenham papéis nos seres humanos.
Dos cinco sentidos humanos - visão, tato, ouvido, olfato e paladar - aqueles cujo
paralelo artificial tem sido mais extensamente desenvolvidos são a visão e o tato (Figura 6). A
visão do homem é o principal método de entrada de dados. Muita pesquisa em desenvolvimento
industrial tem sido aplicada na tentativa de aumentar esta capacidade. Grandes esforços também
tem sido voltados ao desenvolvimento de sensores de toque. Alguns avanços têm sido obtidos
na área dos sensores de escuta, como por exemplo, a identificação de vozes humanas [Franchin
1999].
Neste presente trabalho, mostra-se que esses sensores são importantes para a robótica,
e de que maneira são aproveitados, formulando uma boa idéia de quais sensores serão mais
úteis e como implementá-los no Mundo dos Atores.
24
2.1.2 Atuadores
Muitas vezes, na bibliografia, sensores aparecem juntos aos atuadores. Assim como os
sensores têm o papel de 'sentir' o estado do ambiente, os atuadores são partes dos robôs que tem
a função de atuar sobre o ambiente, como motores e garras (Figura 6).
No caso da área de robótica, o atuador é todo um sistema montado na extremidade
mais distante da base do robô, cuja tarefa é agarrar objetos e ferramentas, podendo transferi-las
de um determinado lugar para um outro lugar diferente ou aplicar uma força para deformação.
São exemplos de atuadores a pistola de solda, garras e pulverizadores de tintas automotivas. A
operação do atuador é, muitas vezes, o objetivo final na operação de um robô, assim todos os
demais sistemas são projetados para habilitar e facilitar a sua operação.
Figura 6: Atuador garra com sensores nas extremidades
O atuador é de extrema importância na execução de uma tarefa, portanto é necessário
que o atuador seja adequadamente projetado e bem adaptado às condições do seu meio e à sua
área de trabalho. Existem dois tipos de atuadores: Garras e Ferramentas [Franchin 1999]. As
ferramentas são designadas para operações específicas, dependendo de cada situação em que
são aplicadas. Já as garras têm objetivos semelhantes à mão humana, pegar objetos, movê-los
25
de lugar, deformá-los ou realizar outra ação específica do caso em que está se tratando a sua
utilização. Alguns tipos existentes de garras que podem ser citados são os seguintes:
• Garra de dois dedos;
• Garra de três dedos;
• Garra para objetos cilíndricos;
• Garra para objetos frágeis;
• Garra articulada;
• Garra a vácuo e eletromagnética,
• Adaptador automático de garras [Franchin, 1999].
No caso da simulação computadorizada, o papel desempenhado pelos atuadores está
presente na programação das habilidades dos atores. No caso do Mundo dos Atores, os atores
mesmo têm implementado em si próprios (e definido em seu papel), mais especificamente em
seus métodos, a maneira com que eles devem atuar no ambiente, nas determinadas situações em
que se aplicam, alterando as condições do ambiente conforme necessário. Com isso, para a
implementação de sensores na ferramenta, não se torna necessário que seja também
implementado o mecanismo de atuadores, pois sua funcionalidade já está presente na
ferramenta.
26
2.2 TIPOS DE SENSORES NA ROBÓTICA
Os sensores atualmente podem ser classificados de acordo com os princípios físicos
sobre os quais eles estão baseados (ótico, acústico, e etc) ou de acordo com as quantidades
medidas (distância, força, e etc). Entretanto, segundo [Franchin, 1999], os sensores são
habitualmente classificados em dois principais tipos: sensores de contato e sensores sem
contato. Em robótica, existem também sensores que indicam as condições internas dos robôs
(como condições de voltagens e a carga da bateria, por exemplo) [Franchin, 1999].
2.2.1 Sensores de Contato
O primeiro grande grupo de sensores é o grupo dos chamados sensores de contato. Os
sensores de contato são sensores que necessitam de um contato físico com algum objeto, para
conseguirem desempenharem suas funções de sensoriamento. São sensores que tocam objetos
para sentirem as informações.
As principais informações obtidas por sensores de contato são:
• Presença ou não de um objeto em um lugar;
• Força de "agarre" de um dispositivo (Figura 7);
• Força de momento;
• Informação de pressão;
• Escorregamento entre a garra e a peça;
27
Figura 7: Sensor de força
2.2.2 Sensores sem Contato
O segundo grande grupo de sensores na robótica é o grupo dos chamados sensores sem
contato. Os sensores sem contato são sensores que não necessitam de um contato físico com
objetos para que consigam desempenhar as suas funções de sensoriamento. São sensores que
vêem os objetos, ou a ausência desses objetos, para fornecerem as informações de
sensoriamento.
As principais informações obtidas por sensores sem contato são:
• Presença ou não de um objeto em um lugar, sem haver toque do objeto com o sensor;
• Distâncias entre objetos e entre os sensores e objetos;
• Detecção de movimentos;
• Posição de objetos;
• Orientação de objetos num local;
• Temperatura em um determinado ambiente;
• Visão;
• Presença e características de luz (Figura 8);
28
Figura 8: Sensor de luz
2.3 TIPOS ESPECIAIS DE SENSORES
Segundo [Sick 2002], os seguintes sensores podem ser classificados como sensores
especiais, não sendo classificados como Sensores Com Contato (vistos em 2.2.1) e Sensores
Sem Contato (vistos em 2.2.2).
2.3.1 Sensores de Contraste (detectores de marcas)
Atuam pelo mesmo principio das fotocélulas de reflexão difusa (chaves de
proximidade) e são capazes de distinguir com precisão diferentes tonalidades de cor na escala
do preto ao branco.
2.3.2 Sensores tipo Forquilha (garfo)
Sistema unidirecional (Emissor e Receptor) montados em um mesmo módulo no
formato de forquilha.
2.3.3 Sensores de Distância
Equipamentos que atuam pelo princípio difuso ou retroreflexivo, avaliando o feixe de
luz refletido. Nesta operação, eles transformam o feixe de luz em distancia e fornecem uma
saída.
29
2.3.4 Sensores de Luminescência
Trabalham pelo mesmo princípio das fotocélulas de reflexão difusa, sendo capazes de
distinguir marcas impressas de baixo contraste e pigmentação fluorescente em materiais onde o
olho humano não pode detectar. Os sensores de luminescência emitem radiação ultravioleta e
recebem luz na mesma freqüência.
2.3.5 Sensores de Cor
Os sensores de cor operam pelo princípio tricromático. Emitem três cores básicas
(vermelho, azul e verde) sobre os objetos a serem analisados e calculam o percentual de cada
cor no raio refletido, comparando com os valores previamente memorizados.
2.3.6 Sensores de Visão
Fotocélulas compostas por emissor e receptor de luz, instalados em uma única caixa de
proteção que utilizam cabos de fibra óptica. Dependendo do tipo de cabo a ser utilizado podem
atuar com configuração unidirecional, retro-reflexiva ou reflexão difusa. São recomendadas
para instalações de difícil acesso e podem identificar objetos de tamanhos bastante reduzidos e
em alta temperatura, no estado atual da tecnologia.
2.3.7 Sensores de Infravermelho
Fotocélulas compostas por emissor e receptor de luzes especiais, como os presentes em
controles remotos de aparelhos eletro-eletrônicos.
2.3.8 Sensores de Posição
Os sensores de posição DMP são utilizados em aplicações com armazéns e
transportadores onde se necessitam de preciso posicionamento de componentes. [Sick 2002].
30
2.4 SENSORES EM VRML
Uma outra área em que os sensores são implementados e aproveitados é na realidade
virtual. A imersão em uma 'outra realidade' será mais completa quanto mais informações do
ambiente simulado puderem ser passadas à pessoa que está inserida nessa realidade, assim
como as informações relativas às ações da pessoa forem passadas ao sistema. Cabem aos
sensores, tanto da pessoa envolvida, quanto os do sistema, fazerem a mediação de trocas de
informações entre as ações de interação entre esse ambiente e o indivíduo que está imerso no
ambiente.
Virtual Reality Modeling Language (VRML) é uma linguagem que tem por objetivo
levar as características da realidade virtual inicialmente à Internet, estendendo-se a outros
ambientes, como simulações históricas e industriais. De forma semelhante ao HTML
(Hypertext Markup Language), pode-se usar o VRML para modelar diversos locais existentes
como locais em mundos de realidade virtual. Para que isso fosse possível, foi necessário que
houvesse dispositivos sensores nessa linguagem, para permitir a interação entre os objetos
desses mundos de realidade virtual e com as pessoas inseridas nestes ambientes [Matsui 2002].
Segue uma lista dos sensores existentes na linguagem VRML e a descrição de cada
função desempenhada por eles [Taylor 2002].
2.4.1 Sensor de Passagem do Tempo
Status do tempo, estando esse sensor relacionado ao disparo de alarmes pré-
configurados.
2.4.2 Sensor de Final de Curso
Status do tempo decorrido até o final de um curso e a posição de parada.
2.4.3 Sensor de Movimentação em Cilindro
Status da rotação, do tempo de movimentação e da posição de um cilindro.
2.4.4 Sensor de Visão de Planos
Status relativo à posição de um plano visto pelo usuário.
31
2.4.5 Sensor de Visão de Esferas
Status da rotação, do tempo de movimentação e da posição de uma esfera.
2.4.6 Sensor de Proximidade
Status da proximidade do usuário com relação a uma determinada posição no
ambiente.
2.4.7 Sensor de Colisão
Status de uma colisão com um ou mais objetos, fornecendo o tempo decorrido neste
acontecimento.
2.4.8 Sensor de Visibilidade
Sensor que permite fornecer a visibilidade a um sistema mecânico.
32
CAPÍTULO 3 – DESCRIÇÃO DE PAPÉIS COM SENSORES
3.1 SENSORES – DESCRIÇÃO E COMENTÁRIOS
A hierarquia de sensores pode sofrer modificações durante o seu uso, seja devido a
limitações inerentes aos tipos de sensores escolhidos ou à linguagem e também devido à
possível inexistência de sensores que se façam necessários nos seus diversos usos. Seguindo-se
a arquitetura, novos sensores podem ser inseridos de forma a fazerem parte da árvore
hierárquica de sensores já definida anteriormente. Isto ocorre, pois todo o trabalho foi feito
baseado no paradigma de Orientação a Objetos (OO).
Escolheu-se o paralelo dos sensores existentes em outras áreas de estudo (como visto
em 2.5) para facilitar a compreensão dos atributos e das funcionalidades de que cada sensor
dispõe em seu ambiente de trabalho, tornando o seu paralelo computacional mais adequado ao
uso em ambientes com as variáveis de condição sendo semelhantes às apresentadas nos
ambientes em que foram baseados.
3.2 SENSORES ATIVOS E SENSORES PASSIVOS
No Mundo dos Atores, quando um ator necessita informações sobre outros atores ele
consulta diretamente estes atores via mecanismo de troca de mensagens oferecido pela POO.
De forma similar, no caso dele necessitar informações sobre o ambiente, ele envia mensagens
diretamente para o palco (exemplar da classe Palco) onde ele está. Esta abordagem tem alguns
inconvenientes, conforme mencionado em 1.1.5. O uso de sensores visa precisamente
intermediar esta obtenção de dados e, desta forma, facilitar a descrição dos papéis dos atores ao
mesmo tempo em que busca reutilizar código.
No que se refere à forma de interação entre os atores e os sensores, há dois modelos
básicos: o de sensores passivos e o de sensores ativos.
33
3.2.1 Sensores Passivos
No caso de sensores passivos, a interação entre um ator e um sensor sempre é iniciada
pelo ator. Sob demanda, o sensor verifica os dados e fornece aos atores, no caso de uma
consulta. Esta alternativa segue o modelo clássico de troca de mensagens da POO. Desta
maneira, os sensores encontram-se inativos enquanto não são consultados.
Durante a realização de uma consulta por parte do ator ao sensor, o sensor que está
sendo consultado verifica o ambiente, naquele exato momento, obtendo uma informação e
fornecendo para o ator o resultado dessa verificação. Desta forma, os dados são obtidos pelo
ator sob demanda e quando não é consultado, o sensor permanece inativo.
Na Figura 9 pode-se ver uma forma esquemática de como é feita a verificação do palco
nesse caso:
1 - O Ator consulta o sensor pelas informações requeridas, quando essas informações se
fizerem necessárias.
2 - O sensor se encarrega de verificar as condições do palco no momento atual.
3 - O sensor fornece ao ator, então, as requeridas informações baseadas nas condições
verificadas no palco, naquele exato momento.
3.2.2 Sensores Ativos
No caso dos Sensores Ativos, têm-se os dados verificados pelos sensores de forma
autônoma, sem necessitar um consulta direta por parte do ator. Essas informações são
verificadas pelo sensor e podem disparar ações ao serem fornecidas ao ator. Desta maneira, os
sensores encontram-se sempre ativos e não são consultados, fornecendo as informações ao ator
a cada instante. As ações disparadas pelos sensores nos atores são como interrupções em
ambientes de execução paralelos.
O sensor que está sempre ativo, realizando uma verificação no ambiente e a cada
momento o sensor está obtendo as informações externas e fornecendo para o ator o resultado
dessas verificações.
34
Na Figura 9 tem-se também, de uma forma esquemática, como é realizada a
verificação do palco no caso dos sensores Ativos:
1 - O sensor fica constantemente verificando as condições do palco.
2 - O sensor fornece ao ator as informações que obteve no ambiente (palco) e baseadas
nessas informações, a realização de certas ações podem ser disparadas no ator.
Figura 9 - Sensores Passivos e Sensores Ativos
3.3 PRINCÍPIOS DO SENSORIAMENTO DISCRETO
O princípio de ação dos sensores é que eles tenham, presentes em si próprios as
informações pertinentes à sua função, que sejam capazes de descreverem estados do ambiente
em que se encontram. Essas informações estarão presentes internamente no objeto sensor, e
serão consultadas pelos objetos que agregaram a si um objeto de uma das classes de sensores.
Para que a informação fornecida seja confiável, se faz necessário que o sensor
encontre-se sempre atualizado, ou seja, que as informações sejam, sempre que solicitadas,
consistentes com aquilo que representa o estado do ambiente no momento em que é realizada a
verificação. Isso se faz necessário para a confiabilidade do sensor e dos sistemas que dependem
dos dados colhidos no ambiente. Essa confiabilidade dos dados de sensoriamento é um dos
fundamentos no uso de sensores, em todas as áreas de utilização dos mesmos. A forma
escolhida para que os sensores tenham as informações do ambiente de maneira consistente foi o
35
repasse da informação solicitada no exato momento em que ela for verificada, de forma
atômica.
A maneira de visualizar os dados do ambiente onde o sensores estão localizados, é
através da utilização dos diversos métodos presentes nos sensores, disparado com o objetivo de
se obterem os dados do sistema (do ambiente ou de outros atores), sempre que seja necessário
para o ator obter esses dados, sempre consistentes.
Como o ambiente em questão, em todos os casos de utilização dos sensores no Mundo
Dos Atores, será primordialmente um objeto da classe Palco, ou mais especificamente da classe
PalcoComEventosDiscretos, decidiu-se criar uma subclasse chamada PalcoComSensores, onde
estão os palcos nos quais seus atores fazem uso de sensores para interagir com o ambiente.
3.4 ENCAPSULAMENTO
Uma das diferenças de termos sensores implementados no Mundo dos Atores é ter uma
outra maneira de fazer com que os atores adquiram as informações referentes ao ambiente onde
se encontram, ou seja, o palco e os outros atores também presentes. Sendo o sistema
implementado sem a presença dos sensores, para poder saber qualquer informação no que se
refere ao ambiente, o ator deve, através de seus métodos, mandar mensagens para o palco, para
que possa receber essas informações. Após ter as informações em mãos, o ator toma as devidas
decisões.
No caso de atores com sensores, essa comunicação do ator diretamente com o palco
deixa de ser necessária. Com os sensores, os atores apenas mandam mensagens pedindo as
informações que necessitam para os sensores, de maneira que a comunicação com o palco seja
toda controlada unicamente pelo sensor. Após adquirir esses dados, comunicando-se com o
palco, o sensor transmite, de forma transparente para o ator, os dados requeridos. De posse
dessas informações, o ator pode tomar as suas decisões normalmente. Com essa maneira de ser
implementado, o ator não precisa saber como se comunicar com o palco, não precisando saber
os métodos usados, apenas precisa utilizar as funções equivalentes dos sensores. Desta forma, a
comunicação entre atores e o palco fica sempre a cargo dos sensores, que oferecem um canal de
comunicação, organizando a ligação entre palco e atores, facilitando a obtenção de informações
pertinentes por parte dos atores.
36
Na Figura 11 vê um resumo de como se dá essa comunicação. Nesta figura é possível
ver as ocorrências das duas situações, em palcos que tenham atores com sensores ou em palcos
com atores que não tenham sensores.
No primeiro caso, onde os atores não têm sensores, as ações se desenrolam da maneira
descrita na Figura 10.
Figura 10 – Encapsulamento
1 - O Ator busca informações diretamente no palco.
2 - O palco retorna as informações pedidas.
3 - O ator, então, toma as devidas decisões baseadas nas informações recebidas.
No segundo caso, onde os atores apresentam os sensores, a seqüência de ações é a
seguinte:
1 - O ator pede informações ao sensor.
2 - O sensor se encarrega de buscar as informações com o palco.
3 - O sensor obtém, diretamente do palco, as informações.
4 - O sensor, então, fornece as informações ao ator que solicitou.
5 - Assim, com essas informações fornecidas pelo sensor, o ator pode tomar as devidas
decisões.
Desta forma, a comunicação entre os atores e o palco fica mais clara e mais fácil de ser
implementada. Essa facilidade vem do fato de que, tendo os sensores uma maneira de obterem
informações do palco, os atores que utilizem esses sensores não precisam saber como interagir
37
diretamente com o palco, bastando apenas utilizar as capacidades dos sensores de obter essas
informações.
3.5 HIERARQUIA DE SENSORES
Os sensores a serem implementados no sistema foram escolhidos levando-se em conta
alguns fatores, como a existência de semelhantes em outras aplicações (aplicações vistas no
capítulo 2), como em simulações, sensores mecânicos e sensores em ambientes de realidade
virtual. Outro fator importante foi a organização de forma hierárquica dos mesmos, que faz com
que se aproveite as vantagens presentes na orientação a objetos, como especialização e
generalização na formação da árvore de sensores do sistema.
Os sensores podem ser divididos em dois tipos principais. Os sensores que obtém
informações relativas ao ambiente onde se encontram; os atores; e os sensores responsáveis por
informações que estão relacionadas a outros atores.
Os sensores implementados formaram hierarquia mostrada na Figura 10.
Figura 11 - Hierarquia de Sensores
38
3.6 ANÁLISE DE ALGUNS PALCOS
Vê-se a seguir, em alguns palcos específicos, quais são e como são feitas estas
alterações:
3.6.1 PalcoMeioAmbiente
Neste palco sim, vê-se uma grande mudança na interação entre os atores envolvidos na
ação no palco, pois os atores que tiveram a si agregados um sensor de Proximidade, deixam de
consultar o palco com relação à detecção de outros atores. Todas essas consultas eram feitas
anteriormente com métodos do palco, como visto em 1.3.2.
O Predador, no seu método caca, invoca o método presaMaisProxima para decidir atrás
de qual das presas ele irá partir em perseguição. Esse método, que era uma consulta ao palco,
foi modificado para fazer uso da funcionalidade provida pelo sensor de proximidade, que no
PredadorComSensores, invoca o método cacaComSensores, onde o método presaMaisProxima
tem a mesma função, mas devolvendo a resposta de uma consulta ao sensor de proximidade.
Desta maneira com que o PredadorComSensores usa o sensor de proximidade, ele não faz uso
dos métodos do palco, pois não há necessidade de ter em seus métodos nenhuma mensagem
direcionada ao palco em que se encontra.
Os demais atores desse palco que tiveram a adição de sensores foram os da classe Presa
e suas subclasses. Eles têm adicionados a si um sensor de proximidade, que é utilizado em dois
métodos, comidaMaisProxima e predadorMaisProximo. A maneira com que esses métodos
agiam anteriormente era semelhante à usada pelo predador para achar a sua presa a ser caçada.
Uma consulta ao palco era feita, como foi mostrado em 1.3.2. No caso das presas, o sensor de
proximidade utilizado é capaz de servir ao duplo propósito, pois ele pode verificar tanto objetos
da classe Grama como da classe Predador, quando a detecção for necessária para a
sobrevivência da PresaComSensores que o utiliza.
39
3.6.2 PalcoDeTransito
Os atores principais deste palco, os CarroComSensores, utilizam-se de sensores de visão
e sensores de toque para realizar as suas verificações do ambiente, enquanto estão presentes,
desempenhando o seu papel. Não é mais necessário à implementação de um retângulo na frente
do ator (para se verificar a visão), como era feito anteriormente (descrito em 1.3.4), pois a
mesma funcionalidade está implementada na classe sensorDeVisao. Já o sensor de toque
permite que seja feita uma verificação de toque com outros atores sem a necessidade de uma
consulta diretamente no palco. Desta maneira, o toque dos carros entre si, e com a área amarela
do cruzamento é detectado pelos sensores.
3.7 SENSORES IMPLEMENTADOS
3.7.1 Classe Sensor
Nesta classe, têm-se as implementações de alguns dos métodos que devem estar
presentes em todos os sensores das subclasses. Muitos deles só são implementados
definitivamente nas subclasses. Além disto, também atributos comuns a todos os sensores são
definidos nesta classe.
Os atributos desta classe são os seguintes:
- ator
- acao
- acaoDeFalha
- nome
40
Os métodos (com os argumentos) desta classe são os seguintes:
- acao: umSimbolo
- ativado
- ator: umAtor
- executa
- initialize
- isSensor
- nome
- nome: umString
3.7.1.1 Descrição dos Atributos
3.7.1.1.1 ator
O atributo ator refere-se ao ator a quem o sensor pertence. Todo sensor deve pertencer a
um ator, para que tenha acesso às informações do ator e do palco onde ele se encontra, para
desempenhar suas funções de ativação e detecção.
3.7.1.1.2 acao
O atributo acao refere-se à ação que deve ser disparada pelo sensor nos atores
detectados, caso seja detectada uma condição em que o sensor encontra-se ativado.
3.7.1.1.3 acaoDeFalha
O atributo acaoDeFalha refere-se à ação que deve ser disparada no ator, no caso em que
não seja detectada uma condição em que o sensor encontra-se ativado, ou seja, caso o sensor
esteja desativado, e ele tenha sido configurado para isso.
3.7.1.1.4 nome
O atributo nome é o atributo pelo qual o sensor pode ser chamado, dentre os sensores
presentes no ator.
41
3.7.1.2 DESCRIÇÃO DOS MÉTODOS
3.7.1.2.1 acao: umSimbolo
O método acao: refere-se ao atributo ação, definindo qual é a ação que deve ser
executada pelos atores detectados no caso do sensor estar ativado.
3.7.1.2.2 ativado
O método ativado retorna true em caso afirmativo quanto à condição de ativação do
sensor ter sido alcançada.
3.7.1.2.3 ator: umAtor
O método ator: serve para definir a qual ator o sensor está pertencendo.
3.7.1.2.4 executa
O método executa é o resposável por disparar as ações acao e a acaoEmSi, em caso do
sensor estar ativado.
3.7.1.2.5 initialize
O método initialize é usado para inicializar os dados dos sensores.
3.7.1.2.6 - isSensor
O método isSensor retorna true, para que se identifique se um determinado objeto é um
sensor.
3.7.1.2.7 nome
Método pelo qual obtém-se o nome do sensor, atrelado ao atributo homônimo, o que é
usado para chamar um determinado sensor no conjunto de sensores do ator.
3.7.1.2.8 nome: umString
Método usado para definir qual nome que será utilizado pelo sensor.
42
3.7.2 CLASSES DE SENSORES
3.7.2.1 Classe Sensor De Área
Nesta classe, tem-se a reimplementação do método ativado, que retorna true quando o
ator que tem este sensor não se encontra numa determinada área definida pelo usuário. Essa
definição de área pode ser feita através do método area: umRetangulo, e é armazenada na
variável area. O método de mesmo nome (area), retorna qual é a área na qual esse sensor está
atuando.
3.7.2.2 Classe Sensor De Borda
Nesta classe, tem-se a definição de uma área retangular, através do método borda:
umRetangulo, na qual o sensor tem implementado uma detecção de toque do ator nessa borda,
retornando true caso haja esse toque. Essa implementação é feita no método ativado. O método
borda retorna essa área com a variável borda, e o método disparaReflexao está disponível para
calcular o ângulo de reflexão do ator que estiver utilizando esse sensor.
3.7.2.3 Classe Sensor De Atores
A classe sensor de atores está no sistema como uma superclasse que engloba todos os
atributos e métodos destinados à detecção de outros atores no palco. Segue-se uma descrição
detalhada de suas características.
Os atributos desta classe são os seguintes:
- cardinalidadeUnitaria
- classeDeSensibilidade
O atributo cardinalidadeUnitaria se refere ao número de atores que será detectado pelo
sensor. Se estiver marcado como verdadeiro, apenas um ator será retornado como resposta, e se
não estiver, o retorno é um conjunto de atores. Já o atributo classeDeSensibilidade é o
responsável por definir a qual classe é sensível o ator, ou seja, atores de qual classe que poderão
ativar o sensor e retornados como resposta às chamadas dos métodos.
Os métodos desta classe (com os seus argumentos) são os seguintes:
43
• atorDetectado
• atoresDetectados
• detectaAtorDoTipo: umaClasse
• detectaAtoresDoTipo: umaClasse
• executa
• initialize
O método atorDetectado retorna um ator que tenha sido detectado, enquanto o método
atoresDetectados retorna todo um conjunto de atores nesta situação. O método seguinte,
detectaAtorDoTipo: umaClasse, é usado para definir o atributo cardinalidadeUnitaria como
ativado, e a classeDeSensibilidade como sendo a umaClasse passada no método. Já
detectaAtoresDoTipo: umaClasse tem a mesma funcionalidade quanto à
classeDeSensibilidade, mas deixa a cardinalidadeUnitaria desativada. Por fim, executa define a
execução da acao e da acaoDeFalha, e o initialize define o valor inicial das variáveis internas.
3.7.2.4 Classe Sensor De Proximidade
Primeira subclasse de SensorDeAtores, tem o método ativado disparando o método
detectaAtoresProximos, que faz a checagem para ver se é detectado algum ator no alcance
(variável definida no método alcance), e retorna true se for detectado algum. O atributo
atoresProximos é retornado na ação de mesmo nome, assim como retorna o método
atoresDetectados.
Os métodos atorMaisProximo e atorMaisProximoNoAlcance retornam apenas um ator,
aquele que está mais próximo do ator com esse sensor, sendo que o segundo pode-se definir
qual alcance. AtorMaisProximo também é uma variável com o ator que se encontra nessa
condição. Os métodos executa e initialize seguem o mesmo padrão, sendo responsáveis pela
realização de ações nos atores e inicialização do sensor.
3.7.2.5 Classe Sensor De Toque
44
Nesta classe, tem-se também a reimplementação do método ativado, que neste caso
retorna true se o ator que tem esse sensor estiver em contato com algum outro ator. A
reimplementação de atoresDetectados computa o conjunto de atores tocados (atributo
atoresTocados), através do método detectaAtoresTocados. Com atoresTocados, existe o mesmo
conjunto, já computado, obtido através da variável interna. O executa detecta se há algum ator
que está sendo tocado, realizando a acao, se estiver configurada, assim como o initialize, que é
o responsável por inicializar o conjunto atoresTocados, uma coleção que inicia vazia.
3.7.2.6 Classe Sensor De Visão
Esta classe de sensores tem o método área: umaArea, em que o atributo área, referente à
area onde a visão do sensor é efetiva, é definido com o valor dado. Área esta que é inicializada
com valor zero no método initialize. O ativado é o método que retorna true se o conjunto de
atores vistos pelo sensor for não vazio. Este conjunto é computado com o método
detectaAtoresVistos (com ou sem a área dada) e obtido através do método atoresDetectados. O
atributo atoresVistos, a coleção dos os atores vistos, pode ser obtido pelo método de mesmo
nome, depois de computado.
Os métodos veAlguem e veQuantos calculam se o sensor detecta algum ator na área dada e
retorna true caso veja alguém e o devolve número de atores vistos, respectivamente. O
retanguloNaFrente é usado para calcular a área de visão do sensor. O método executa trata de
executar as ações necessárias, conferindo a condição do sensor.
3.8 USO DOS SENSORES
Os atores que fazem uso dos sensores para obterem informações do ambiente em que se
45
encontram podem se utilizar destes de três maneiras distintas, de modo que se tem a opção de
escolha de qual será a maneira mais adequada ao caso em que se encontra a necessidade de uso
dos sensores presentes. Essas maneiras distintas de implementação são baseadas nas duas
formas de sensores vistas em 3.2, os sensores Passivos (3.2.1) e os Ativos (3.2.2).
3.8.1 Dicionário de Sensores
A primeira maneira é através da coleção sensores (um dicionário), onde, na definição
dos sensores, são colocados os sensores que se determina que este ator tenha em si. Essa
definição pode ser feita na inicialização, ou com o uso do método defineSensores, presente nos
atores com esta função. O método homônimo retorna essa coleção inteira. A adição de novos
sensores a esta coleção se dá com o método adicionaSensor: , onde é passado um sensor a ser
adicionado.
Um determinado sensor pode ser chamado no dicionário pelo seu atributo nome,
atributo que representa unicamente um dos sensores da coleção. Um sensor de um tipo
específico pode ser retornado com o método sensor, para que seja possível a utilização das
funcionalidades deste sensor, dentro do ator, sem ter que trabalhar com todo a coleção.
Com essa mesma estruturação, pode-se também trabalhar com o conjunto de sensores,
quando essa for a solução mais adequada, utilizando operações diretamente sobre os conjuntos.
Essa forma faz utilização dos sensores passivos, vistos em 3.2.1.
Essa maneira de utilização não implica mudanças na atual implementação do modelo
de execução. O ator reage à informação obtida conforme as suas condições estão configuradas
para a interpretação desse dado.
3.8.2 Métodos de Verificação
Uma segunda maneira de utilização é através dos métodos de verificação citados a
46
seguir:
- verificarSempre: umSensor
- verificar: umSensor aCada:
- verificar: umSensor comProbabilidadeDe:
- verificar: umSensor em:
- verificar: umSensor sempreQue:
Estes métodos presentes na classe AtorComSensores são todos usados na definição do
papel dos atores, para que a execução atrelada aos sensores (método executa, configurado em
cada sensor) seja executada sempre conforme a condição dada. Essa forma de verificação é
também baseada em sensores Passivos (vistos em 3.2.1), pois o ator obtém os dados sob
demanda, ao consultar o sensor.
Desta maneira, o schedule não é alterado, pois é passado um bloco
condição/ação semelhante ao de uma definição de ação normal, onde a execução é dependente
da condição de cada um dos sensores. As ações a serem tomadas são configuradas nas variáveis
acao e acaoDeFalha, presentes em cada um dos sensores. Essa maneira de utilização dos
sensores também não implica mudanças na atual implementação do modelo de execução. O ator
reage à informação obtida conforme as suas condições interpretem esse dado.
De uma maneira simplificada, pode-se descrever a utilização destes métodos da seguinte
maneira:
- verificarSempre: umSensor
Este método é usado para que um sensor seja sempre verificado e suas ações
sempre executadas quando ele estiver na condição ativado. É colocado no caso de sensores que
estão sempre verificando o ambiente.
- verificar: umSensor aCada:
Este método define um intervalo de tempo (um valor inteiro) em que o sensor
deva ser verificado quanto à sua ativação. A cada passagem de tempo deste intervalo, o sensor é
47
verificado e dispara as ações necessárias, caso o sensor esteja ativado neste exato momento.
- verificar: umSensor comProbabilidadeDe:
Este adiciona um valor probabilístico para a realização da verificação do sensor
dado. Desta maneira, tem-se como trabalhar com atores que tenham sensores não precisos,
quanto à realização da verificação de seus dados.
- verificar: umSensor em:
Esta situação ocorre quando se deseja marcar um momento exato para a
realização de uma verificação do sensor, de maneira que ele só detecte o ambiente nesse dado
momento. Após este momento, a verificação deste sensor não é mais realizada.
- verificar: umSensor sempreQue:
Desta forma acima, tem-se uma maneira de condicionar a verificação de um
sensor conforme um valor booleano, uma maneira muito comum de verificação, onde a
verificação pode ser atrelada à condição de alguma variável interna do ator, ou outra condição
do ambiente.
3.8.3 Inserção no Schedule do ator
A terceira maneira de se utilizar os sensores é através dos seguintes métodos:
- seSensorAtivado: umSensor faca: umaAcao
- seSensorAtivado: umSensor faca: umaAcao emCasoDeFalha: outraAcao
- seSensorAtivado: umSensor e: outroSensor faca: outraAcao
- seSensorAtivado: umSensor ou: outroSensor faca: umaAcao
- seFalhaESensorAtivado: umSensor faca: umaAcao
- seFalhaGeralNosSensores: umaAcao
Estes métodos da classe dos atores atorComSensores, permitem que a verificação de um
sensor, juntamente com a ação a ser tomada, sejam colocados, através da definição do papel, no
48
schedule do ator, de maneira que a verificação da sua condição de atuação seja feita e a ação a
ser tomada seja dada nesta mesma mensagem. Com esta abordagem, os sensores agem de forma
mais independente, sendo chamados de sensores ativos, como vistos em 3.2.2. Devido a
limitações inerentes ao modelo de execução, o sensor acaba sendo passivo, mas para o usuário,
que não se encarrega de configurar o envio de mensagens dos atores para os sensores, a
operação acaba ocorrendo de forma transparente, de maneira semelhante a um sensor ativo, sem
que eles se enquadrem realmente nessa classificação.
Desta maneira, não se fica atrelada a verificação da condição de ativação do sensor com
as ações presentes em seus atributos (acao e acaoDeFalha), pode-se passar qualquer ação para
que seja disparada pela condição do sensor.
3.8.3.1 Descrição dos métodos
- seSensorAtivado: umSensor faca:
Da maneira acima, pode-se definir uma ação a ser realizada ao ser detectado uma
condição de ativação no sensor.
- seSensorAtivado: umSensor faca: umaAcao emCasoDeFalha:
Desta maneira, pode-se também definir uma ação a ser realizada quando for
detectada uma condição de ativação no sensor, e, além disso, define-se uma ação que é
realizada sempre que essa condição não for detectada.
- seSensorAtivado: umSensor e: outroSensor faca:
Com este comando, define-se uma ação a ser realizada quando os dois sensores
dados encontrem-se ativados.
- seSensorAtivado: umSensor ou: outroSensor faca:
Nesta condição, dos dois sensores passados na mensagem, quando um deles
estiver ativado, a ação é realizada.
- seFalhaESensorAtivado: umSensor faca:
Com este caso, a ação dada é executada quando a situação de desativado foi
acusada pelo sensor anterior, e o sensor atual apresenta-se ativado.
49
- seFalhaGeralNosSensores:
Nesta mensagem, é definida uma ação a ser realizada quando todos os sensores
verificados anteriormente, na mesma fatia de tempo, apresentem-se na condição de desativados,
caracterizando uma falha geral nos sensores.
3.8.3.2 Mudanças no Schedule
A classe Schedule é a classe responsável por ter os dados que são definidos como papel de
todos os atores. Nela, são inseridos conjuntos constituídos principalmente de duplas
condição/ação, assim como é responsável por ela a realização dos testes e ativações das ações,
para cada um dos atores de cada palco.
Com estas responsabilidades, tornou-se necessário que o Schedule também fosse capaz de
aceitar a colocação de sensores no ambiente, controlando tanto o teste de ativação como a ação
que deve ser disparada, conforme a necessidade e dependendo do resultado da verificação. Isso
foi necessário para que a utilização de sensores ativos (vistos em 3.2.2) pudesse ser realizada.
3.8.3.2.1 Métodos Principais
Os principais métodos implementados são os dois seguintes:
- quandoSensorAtivado: umSensor
- sempreQueSensorAtivado: umSensor
Estes métodos estão disponíveis com variações que permitem também o teste de um
segundo sensor, com as opções e: e ou:. No caso do quandoSensorAtivado, pode-se também
passar uma ação para caso de falha.
Vê-se a seguir como é formada a estrutura do comando executeCom: , que se encarrega
de avaliar as condições e os sensores, para executar ações cujas condições sejam satisfeitas.
3.8.3.2.2 Implementação
executeCom: umAtor
50
[indice <= eventos size] whileTrue: [
falhaGeral := true.
evento := eventos at: indice.
Neste teste, vê-se se o primeiro argumento é um sensor, para disparar os testes e, se
preciso, executar também as ações necessárias.
(evento at: 1) isSensor ifTrue:[
Após a confirmação de o primeiro argumento ser um sensor, tem-se um teste para ver se
o Segundo argumento também o é. Se for afirmativo, é o caso em que a existe uma comparação
lógica entre os dois resultados, ou um E:, onde os dois devem estar ativados para realizar a
ação, ou um OU:, onde, caso um dos dois sensores esteja ativado, a ação é acionada.
(evento at: 2) isSensor ifTrue:[ "Se o segundo for sensor, é um E: ou um
OU:"
(evento at: 5) ifTrue:[ "Caso do E:"
sensor := evento at: 1.
resultado := sensor ativado.
resultado ifTrue: [
sensor := evento at: 2.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 3) "with: sensor atoresDetectados".
falhaGeral := false.
].
]
Na próxima parte, tem-se a execução do caso onde tem-se dois sensores, e a condição
para que a ação seja executada seja a ativação de qualquer um dos dois sensores. Se o primeiro
sensor estiver ativado, o segundo não necessita estar ativado.
51
] ifFalse:[ "Caso do OU:"
ouExecutado := false.
sensor := evento at: 1.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 3) "with: sensor atoresDetectados".
ouExecutado := true.
falhaGeral := false.
]
Testa para ver se execução da ação já foi executada no teste do primeiro sensor, para
que não haja uma dupla execução da ação.
ouExecutado ifFalse:[
sensor := evento at: 2.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 3) "with: sensor atoresDetectados".
falhaGeral := false.
].
]
]. "Final do OU:"
Neste caso, há apenas um sensor, onde dependendo do resultado deste sensor, a ação é
executada, ou não. Neste caso, também há a execução da ação de falha, caso ela tenha sido
configurada anteriormente, conforme o método usado para configurar o schedule do ator.
] ifFalse: [ "Caso em que há apenas um sensor"
sensor := evento at: 1.
resultado := sensor ativado.
resultado ifTrue: [
52
umAtor perform: (evento at: 2) "with: sensor atoresDetectados".
falhaGeral := false.
] ifFalse: [
(evento at: 3) isNil ifFalse: [
umAtor perform: (evento at: 3)
].
].
foiLimpo ifTrue: [
^self ].
(evento at: 4) ifTrue: [
eventos removeIndex: indice
] ifFalse: [
indice := indice + 1
].
]
Este caso mostra a maneira tradicional de execução das duplas condição/ação, no caso
da configuração em que não há nenhum sensor para ser testado no papel do ator.
] ifFalse: [ "Se for sensor em 1, executa normalmente o bloco condição/ação"
resultado := (evento at: 1) value.
resultado isBoolean ifFalse: [
self error: 'Condição do papel do ator não resulta em um valor true ou false'
].
resultado ifTrue: [
(evento at: 2) value.
foiLimpo ifTrue: [
^self
].
(evento at: 3) ifTrue: [
eventos removeIndex: indice
] ifFalse: [
indice := indice + 1
]
53
] ifFalse: [
indice := indice + 1.
foiLimpo ifTrue: [
^self
]
]
].
palco executaEventos.
].
tempo := tempo + 1.
3.8.4 Sensores com Interrupções
Uma outra maneira de implementação que pode ser realizada é com o uso de
sensores ativos, os quais podem ficar de maneira sempre ativa, realizando a verificação do
ambiente e interromper o ator a qual pertencem, para disparar alguma ação pertinente a
condição verificada no ambiente. Esse modelo de interrupções é encontrado em outros modelos
de execução distintos do utilizado pela versão atual Mundo dos Atores, o Modelo de Eventos
Discretos (visto em 1.1.2). Essa maneira de utilização implica mudanças na atual
implementação do modelo de execução, de maneira a fazer com que essa verificação seja algo
interno ao sistema, ou seja, faça parte do modelo de execução. Essa informação obtida pelo
sensor pode disparar ações a serem executadas pelo ator conforme as condições dadas pelo
usuário. Essas ações a serem disparadas podem ser interpretadas como as interrupções
existentes em modelos de execução paralelos.
3.9 DEFINIÇÃO DE PAPÉIS EM ATORES COM SENSORES
No Mundo dos Atores, cada ator envolvido com algum palco desempenha as suas
funções ao seguir um roteiro de ações, ações essas que estão descritas no seu papel dentro do
palco. Em muitos casos, a utilização dos sensores permite uma implementação alternativa com
54
relação aos papéis descritos nos atores, já que muitas das ações descritas nesse papel dos atores
podem ser relacionadas com consultas aos sensores que estejam inseridos nesses atores e,
através dessas consultas, as ações podem ser realizadas pelos atores. Fazendo o uso de sensores
na descrição destes papéis, tem-se uma diminuição da complexidade dessa descrição. Com isso,
essa tarefa torna-se mais fácil de ser compreendida.
Neste tópico encontra-se feita uma análise de alguns dos palcos quanto à mudança
ocorrida na definição dos papéis dos atores. O uso dos sensores nos atores, aqui analisado, foi
baseado na utilização de um dicionário de sensores (descrito em 3.7.1), no qual estão contidos
todos os sensores de cada ator.
As maneiras de se implementar variam em cada caso, estando dependentes de qual o
conjunto de atores e sensores que interagem em um determinado palco. Primeiramente, os
atores que tem implementados em si os sensores devem ser subclasse de AtorComSensores,
assim como o palco deve ser subclasse do palco PalcoComSensores, para que seja possível a
utilização dos sensores nestes casos, devido aos atributos e métodos implementados nestas
superclasses, específicos para serem usados em ambientes com sensores. Verifica-se agora, em
alguns exemplares de palcos específicos, quais são e de que forma são feitas essas
implementações da definição dos papéis destes atores.
3.9.1 PalcoMeioAmbiente
No caso desse palco, os atores envolvidos no palco são de diversas classes, com todas
elas sendo subclasse de AtorMeioAmbiente, sendo elas: Grama, Predador e Presa, que pode ser
PresaJovem, PresaAdulta, PresaVelha ou PresaMorta. Uma descrição da dinâmica de
funcionamento desse palco, sem a presença de sensores, pode ser vista no item 1.3.2.
As classes Presa e Predador foram reimplementadas em classes PredadorComSensores,
PresaComSensores e suas subclasses. A classe Grama foi posteriormente reimplementada na
classe GramaComSensores, também para que pudesse usar sensores em seu comportamento.
Com relação ao Predador, o papel difinido é o seguinte:
definePapel
"Define o schedule do predador, ou seja, as ações que ele executa e quando"
|jovem|
55
self sempreQue: [nivelDeAlimentacao = 0] faca: [ self saiDoPalco].
self sempreQue: [nivelDeAlimentacao < 700] faca: [ self caca].
self sempreFaca: [
nivelDeAlimentacao := nivelDeAlimentacao - 1. ].
self em: 3000 faca: [ self saiDoPalco ].
self cada: 1050 faca: [ self seReproduz ].
Com relação a esse papel desempenhado pelo Predador, a diferença principal para o
PredadorComSensores é na realização da caça, que pode ser realizado com o uso de um sensor
específico para verificação de proximidade das presas que podem lhe servir de alimento. Com
essa possibilidade, foi implementado um método cacaComSensores, para ser usado com esses
atores. A utilização desse método não interferiu na definição do papel do
PredadorComSensores, apenas foi adequada a seguinte linha:
self sempreQue: [nivelDeAlimentacao < 700] faca: [ self cacaComSensores].
Este novo método pode fazer uso de uma nova implementação do método
presaMaisProxima, para realizar a caça do predador. Este método teve a sua implementação
alternativa de:
^self palco atorDoTipo: Presa maisProximoDe: self.
Para o seguinte:
sensores do: [:sensor| ^sensor atorMaisProximo].
Para que os sensores inseridos no predador funcionem de maneira a fornecerem a presa
mais próxima, assim como desempenhar as outras funcionalidades, eles devem ser configurados
da seguinte forma, na inicialização, através do método defineSensores:
defineSensores
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'visão presa';
56
detectaAtorDoTipo: PresaComSensores;
alcance: 100).
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque presa';
detectaAtorDoTipo: PresaComSensores).
self adicionaSensor: (
(SensorDeArea new: self)
nome: 'area visivel').
Dessa maneira, o sensor tem sensibilidade para atores da classe PresaComSensores,
incluindo com isso, também todas as suas subclasses. Com esta possibilidade, pode-se
implementar o método cacaComSensores de uma maneira mais simplificada, como mostrada a
seguir:
cacaComSensores
(self sensor: 'visão presa') ativado ifTrue: [
(self sensor: 'toque presa') ativado ifTrue: [
self cacou: (self sensor: 'toque presa') atorDetectado
] ifFalse: [
(self sensor: 'visão presa') atorMaisProximo notNil ifTrue: [
self apontaPara: (self sensor: 'visão presa') atorMaisProximo;
anda: 15.1. ] ]
] ifFalse: [
self andaAEsmo. ].
Com esta forma de se fazer a implementação deste método, a caça do
PredadorComSensores é realizada utilizando-se do SensorDeProximidade, e de seu atributo
distância, que define qual é o raio de ação no qual o sensor é capaz de detectar os atores dentro
do palco, facilitando a maneira com que a verificação de distância ocorre, o que é usado para
definir quais são as ações a serem tomadas pelo ator.
57
O sensor de toque também é utilizado no ator, sendo usado para saber se há um toque do
predador em alguma presa, no caso do ator PredadorComSensores caçar uma presa qualquer.
Esse sensor é denominado 'toque presa', como ficou definido em sua inicialização. O método
andaAEsmo foi implementado para facilitar a compreensão da classe. Esse método faz
utilização do sensorDeArea, denominado 'area visivel' e configurado com a área visível do
palco, para que o predadorComSensores não se afaste desta área enquanto estiver
desempenhando o seu papel. Este é o terceiro sensor utilizado nesta classe. A implementação
deste método é feita da seguinte maneira:
andaAEsmo
((self sensor: 'area visivel') ativado not) ifTrue: [self apontaPara: self palco centro].
self gira: (self aleatorio: 20) - 10;
anda: 6+(self aleatorio: 2).
Este método testa, através do sensorDeArea, se devido ao seu movimento o ator está
fora da área visível do palco, fazendo com que ele dispare a ação de apontar para o centro do
palco, disparada em caso afirmativo. Além dessa verificação, o predador anda aleatoriamente
pelo palco, girando de –10 a 10 e andando sete unidades de espaço pelo palco.
A classe de atores Grama, que inicialmente não seria reimplementada em uma versão
com sensores, foi reimplementada na classe GramaComSensores, para que o papel pudesse ser
reimplemetado com o uso de sensores, para verificar a presença na área visível do palco. A
linha adicionada à definição do papel desta classe foi a seguinte:
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self saiDoPalco ].
Com relação aos atores das classes Presa e subclasses, onde cada subclasse tem o seu
papel definido de forma diferente, os sensores de proximidade são usados para a implementação
dos métodos comidaMaisProxima e predadorMaisProximo. Nestes métodos, ao invés de uma
implementação onde cada ator busca saber a informação através de uma consulta ao palco ao
qual pertencem, eles passam a coletar os dados nos sensores de presença que cada um deles
possui. Também é implementado a utilização de um sensor dedicado a verificar a presença na
58
área visível do palco, pois essa condição gera uma mudança na direção da presa, que aponta
para uma posição próxima ao centro do palco, e desloca-se. Nestas classes também não se tem
grandes diferenças nos papeis dos atores, na presença de sensores, mas têm-se principalmente
nas implementações dos métodos dos mesmos. Segue-se a definição dos sensores, no método
defineSensores:
defineSensores
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'visão predador';
detectaAtorDoTipo: PredadorComSensores;
alcance: 110).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'visão grama';
detectaAtorDoTipo: GramaComSensores).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'toque grama';
detectaAtorDoTipo: GramaComSensores;
alcance: 10).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'presa adulta';
detectaAtorDoTipo: PresaAdultaComSensores).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'presa velha';
detectaAtorDoTipo: PresaVelhaComSensores).
59
self adicionaSensor: (
(SensorDeArea new: self)
nome: 'area visivel').
Nota-se nessa inicialização a grande quantidade e variedade de sensores utilizados neste
caso. Ao todo, a classe apresenta seis sensores distintos em sua implementação. A seguir, vê-se
a implementação dos métodos com a utilização destes sensores. Tem-se nos seus detalhes a
mudança na implementação do método procuraComida:
procuraComida
|comida distancia|
(comida := self comidaMaisProxima) isNil ifTrue: [
^self gira: (self aleatorio: 10) - 5;
anda: 8
].
distancia := self distanciaPara: comida.
distancia <= 10 ifTrue: [
comida saiDoPalco.
nivelDeAlimentacao := nivelDeAlimentacao + 200
] ifFalse: [
self apontaPara: comida;
anda: (distancia min: 10). ].
foi reimplementado da forma:
procuraComida
|gramaProxima|
(gramaProxima := (self sensor: 'visão grama') atorMaisProximo) isNil ifTrue: [
^self gira: (self aleatorio: 10) - 5;
anda: 8
].
60
(self sensor: 'toque grama') ativado ifTrue: [
(self sensor: 'toque grama') atorDetectado saiDoPalco.
nivelDeAlimentacao := nivelDeAlimentacao + 200
] ifFalse: [
self apontaPara: gramaProxima;
anda: 7 + (self aleatorio: 4).
].
Nesta alternativa de implementação, o método não precisa ter a variável referente à
distância da comida, assim como as comparações de distância não precisam ser feitas. Isso tudo
acaba substituído pelo atributo dos sensores referente ao alcance, que só retorna uma presa
próxima se ela já se encontrar dentro desse limite, fixado na definição dos sensores. Esses
sensores utilizados nesse método são denominados 'visão grama' para o sensor de proximidade
que verifica os atores GramaComSensores e 'toque grama' para o que sente o toque entre os
atores, no caso da presa se alimentar da GramaComSensores. Já a definição do papel dos atores
PresaAdulta foi alterada em dois comandos.
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self apontaPara: self palco centro.
].
self sempreFaca: [
predador := (self sensor: 'visão predador') atorMaisProximo.
predador isNil ifTrue: [
nivelDeAlimentacao > 300 ifTrue: [
self gira: (self aleatorio: 10) - 5;
anda: 5.
] ifFalse: [
self procuraComida.
]
] ifFalse: [
self apontaPara: predador;
gira: 180 + (self aleatorio: 50) - 25;
61
anda: 15. ]. ].
Com essas definições, usa-se o sensorDeArea denominado 'area visivel' para apontar o
ator para o centro do palco, cada vez que ele se encontrar em uma posição que esteja fora da
área visível do palco, e na segunda, usa-se um sensor de proximidade chamado 'visão predador'
para verificar a perigosa presença de um PredadorComSensores pelas imediações, fazendo com
que a PresaAdulta se afaste do Predador. De maneira semelhante, a PresaVelhaComSensores
faz o uso dos mesmos sensores, mas o teste é numa área mais estreita, visto que a idade
influencia na capacidade visual do animal.
A PresaJovemComSensores também faz uso de sensores, no método
adultoMaisProximo, onde a verificação da presença de um ator PresaComSensores que já seja
adulto é tesdada. A implementação feita com os sensores é implementada da seguinte maneira:
adultoMaisProximo
|adultoMaisProximo velhaMaisProxima|
adultoMaisProximo := (self sensor: 'presa adulta') atorMaisProximo.
velhaMaisProxima := (self sensor: 'presa velha') atorMaisProximo.
velhaMaisProxima isNil ifFalse:[
(self distanciaPara: velhaMaisProxima) < (self distanciaPara:
adultoMaisProximo) ifTrue: [
adultoMaisProximo := velhaMaisProxima
] ].
^adultoMaisProximo.
Assim, com o uso de sensores, a PresaJovemComSensores pode saber quem deve adotar
como mãe. Neste método, são usados os sensores chamados 'presa adulta' e 'presa velha', sois
sensores da classe SensorDeProximidade. Desta maneira tem-se uma forma mais simplificada
de definir as ações dos atores, aproveitando-se das capacidades dos sensores e das facilidades
que eles proporcionam, como no caso da verificação da distância entre a PresaComSensores e a
GramaComSensores, assim como o SensorDeProximidade utilizado no PredadorComSensores.
Nestes casos, a utilização de sensores nos atores faz com que a interação com o palco
em que se encontram não seja feita diretamente, e sim através de seus métodos. Desta maneira,
garante-se o encapsulamento, sendo o sensor a interface do ator para com o meio externo onde
62
ele se encontra.
3.9.2 PalcoDeTransito
Neste palco, tem-se a interação entre atores Carro, colocados no palco por um conjunto
de quatro geradores da classe GeradorDeCarros, com atores AreaAmarela e Semaforo, que se
localizam próximos ao centro do palco. Uma descrição desse palco pode ser vista no item 1.3.4,
ainda sem a presença de sensores nos atores envolvidos. Para o funcionamento do Semaforo, há
a classe Sincronizador, e sua subclasse, SincronizadorDeDoisTempos. Essa é a classe
responsável pelo controle de abertura e fechamento dos semáforos.
Os atores Carro têm a responsabilidade de andar em linha reta e se retirarem do palco
quando não estiverem mais na área visível dele. Isso, porém, deve ser feito respeitando-se os
semáforos e a presença de carros na sua frente, além do posicionamento em relação à área
amarela do centro do palco. A classe reimplementada para a inserção dos sensores é a classe
GeradorDeCarros, que tem o seu papel mantido:
definePapel
self comProbabilidadeDe: 0.04 faca: [self geraCarro].
Porém, a implementação do método geraCarro é alterada. Tem-se aqui a implementação
original:
geraCarro
|carro|
(self palco atoresEm: self retangulo doTipo: Carro) isEmpty ifFalse: [
^self ].
carro := Carro new.
carro entraNoPalco: self palco ;
pulaPara: self posicao;
apontaPara: self direcao.
E a nova implementação, com os sensores:
63
geraCarro
|carro|
(self palco atoresEm: self retangulo doTipo: CarroComSensores) isEmpty
ifFalse: [ ^self ].
carro := CarroComSensores new.
carro entraNoPalco: self palco ;
pulaPara: self posicao;
apontaPara: self direcao.
Essa principal modificação é feita para que os atores principais deste palco sejam
colocados no palco, os atores CarroComSensores. Estes carros utilizam-se de sensores de visão
e sensores de toque para realizar as suas verificações do ambiente, enquanto estão presentes,
desempenhando o seu papel. O método retanguloNaFrente: não é mais necessário, pois a
mesma funcionalidade está implementada na classe sensorDeVisao não sendo, portanto,
reimplementado.
Os sensores utilizados pelos atores da classe CarroComSensores são definidos na
inicialização, mostrada a seguir:
defineSensores
self adicionaSensor: (
(SensorDeVisao new: self)
nome: 'visão carro';
detectaAtoresDoTipo: CarroComSensores).
self adicionaSensor: (
(SensorDeVisao new: self)
nome: 'visão semaforo';
detectaAtoresDoTipo: Semaforo).
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque semaforo';
detectaAtorDoTipo: Semaforo).
self adicionaSensor: (
64
(SensorDeArea new: self)
nome: 'area visivel').
Desta maneira, com esses quatro sensores, tem-se todos os sensores necessários para a
atuação do CarroComSensores. Foi implementado também um método chamado testaFigura,
que se encarrega de testar a condição de aceleração do ator e mudar a figura conforme a
condição. Com este método, fica mais clara a definição do papel desse ator.
testaFigura
acelerando ifTrue: [
self mudaFiguraAndando
] ifFalse: [
self mudaFiguraFreiando. ].
Os métodos de detecção usados, que tem a definição no papel do ator, são alterados para
funcionar com sensores. O primeiro deles é o método haSemaforoVermelho, que da sua
implementação original, a seguir:
haSemaforoVermelho
(self palco atoresDoTipo: Semaforo queSobrepoem: self) notEmpty ifTrue: [
^false ].
(self palco atoresEm: (self retanguloNaFrente: 30) doTipo: Semaforo) do: [ :sinal |
sinal figuraCorrente = (Mundo bitmaps at: 'semaforoVermelho') ifTrue: [
^true ]. ].
^false
Foi reimplementado como:
haSemaforoVermelho
((self sensor: 'toque semaforo') atoresTocados) notNil ifTrue: [
^false ].
((self sensor: 'visão semaforo') detectaAtoresVistos: 30) do: [ :sinal |
65
sinal figuraCorrente = (Mundo bitmaps at: 'semaforoVermelho') ifTrue: [
^true ]. ].
^false
O mesmo ocorre com o método naoHaCarroNaFrente, que tem a última linha alterada.
Sem os sensores é a seguinte linha:
^(self palco atoresEm: retangulo doTipo: Carro) isEmpty
Já na implementação com a presença dos sensores, um deles é usado:
^(self sensor: 'visão carro') veAlguem: retangulo isEmpty.
Outro método que não é necessário no palco com a presença dos sensores é o
haCarroNaFrente, já que o ator usa o sensor de visão presente no ator para verificar a presença
de um carro na sua frente, enquanto estiver andando, não precisando ter a implementação deste
método.
Neste palco, embora os atores principais sejam os da classe CarroComSensores, eles
interagem não só entre si, mas com os outros atores presentes no palco, e essa interação é toda
ela mediada pelos sensores, que através das suas funcionalidades, sentem o meio, tornando
possível a tomada de decisões pelo ator, baseado nesses dados
3.9.3 Comentários
Através do uso dos sensores, tem-se uma maneira fácil de encapsular a comunicação do
ator com o palco em que ele desempenha seu papel, de maneira que toda a informação que o
ator com sensores tiver que receber do palco, com relação ao seu próprio estado, ou com
relação com os outros atores presentes, ele receberá através das funcionalidades dos sensores.
Toda consulta aos sensores retorna um valor consistente, pois a verificação do ambiente
66
é sempre feita no momento em que o sensor vai efetivamente utilizar a resposta para a tomada
de decisão, como reação à mensagem passada pelo ator. O uso dos sensores é simples, de
maneira a tornar a implementação mais simples que uma consulta ao palco, visto que não é
mais necessário que o implementador tenha conhecimento dos métodos presentes no palco, mas
apenas dos métodos dos sensores, que se apresentam sempre de maneira específica para o que
foram projetados.
CAPÍTULO 4 – CONSIDERAÇÕES FINAIS
4.1 CONCLUSÃO
67
Os sensores implementados foram implementados de maneira completamente
integrada ao ambiente/linguagem Smalltalk, assim com o Mundo dos Atores,
permitindo que o aprendiz faca uso desses sensores da forma natural, assim como a
hierarquia de palcos e atores do Mundo do Atores.
A Hierarquia de Sensores é expansível, facilitando a inclusão de novos
sensores.
O aprendiz não necessita conhecer os métodos da classe Palco, bastando
conhecer os métodos dos sensores, que são mais específicos para o uso no qual se
destinam. Com isso, consegue-se uma mesma funcionalidade já provida anteriormente
pelos métodos do palco, mas de uma forma mais direta.
A implementação dos sensores no Mundo dos Atores permitiu que a descrição
dos papéis dos atores se apresente de uma maneira menos complexa que
anteriormente, tornando mais simples a programação e a interpretação destes papéis.
Isso foi verificado através da comparação dos palcos que não faziam uso de sensores,
e dos palcos onde os atores fazem uso destes sensores.
As três maneiras de utilização permitem uma flexibilização, fazendo com que o
uso seja feito com os sensores da maneira mais adequada possível a uma determinada
ocasião. Isso é possível, pois os dois paradigmas de sensores, tanto Sensores Reativos
como Sensores Pró-Ativos, podem ser utilizados.
O trabalho em disciplinas, ou seja, com grupo de estudantes, não foi realizado
para avaliação do uso dos sensores de forma conjunta com a ferramenta, para que o
uso dos sensores possa ser verificado na prática.
O uso de Smalltalk como linguagem de programação neste trabalho foi
interessante por ter uma sintaxe diferente das linguagens usuais, como C, Pascal ou
Fortran. Esse uso é importante, para que o aprendiz tenha contato com uma outra
visão em termos de linguagens de programação.
69
O principal trabalho a ser realizado com essa implementação dos sensores
vai ser o seu uso, junto aos alunos que utilizam o Mundo dos Atores no ensino de
computação. Com esse uso, pretende-se facilitar a obtenção de informações para os
atores envolvidos no Palco, liberando os programadores dessa tarefa de aquisição dos
dados e de cálculos como a distância entre atores e posicionamento dentro do palco.
Com essa utilização, surgirão observações das mais variadas com relação
à implementação dos mesmos, às quais podem ser mais claras quanto à usabilidade e
a outros fatores, como a própria hierarquia formada pelos sensores que foram
implementados nesse trabalho. Com isso, o trabalho vem fazer parte de um
desenvolvimento continuado, onde o seu uso de maneira conjunta com outros
trabalhos fará com que ele se apresente de uma forma cada vez mais madura.
4.2.2 Adição de novas classes
Devido ao uso do ambiente para a modelagem dos mais variados
ambientes, surgirão, certamente, outras oportunidades onde sejam necessários
sensores que não foram definidos nesse primeiro momento como necessários. Com o
surgimento dessa necessidade, também surgirão novas classes que se encaixam no
modelo de forma a preencher essa lacuna, adicionando novas possibilidades de uso
dos sensores.
Pode-se imaginar que essas novas classes venham a serem inseridas na
hierarquia de sensores de maneira a preservar a divisão lógica existente atualmente,
em que existem os sensores que derivam de SensorDeAtores e os demais, Sensores de
Palco.
4.2.3 Adição de novos métodos
Muitas vezes, no processo de modelagem, e posteriormente na
implementação de uma série de objetos, imagina-se estar fazendo isso da maneira
mais completa possível, para que todas as possibilidades de uso desses objetos
venham a ser contempladas em seus atributos e métodos. Nem sempre, porém, pode-
70
se fazer, por mais completo que tenha sido o projeto, um objeto que tenha tudo aquilo
que pode ser requerido no futuro, de maneira a não precisar ser adaptado em situações
futuras, no uso desse objeto, seja por falta de uma visão mais precisa do uso que se
fará desse objeto, ou de qualquer outro fator que influa no processo de
desenvolvimento.
Assim como no caso da modularização de algoritmos [Berg 1998], à
medida que os sensores se adaptem a uma variedade maior de situações, como um
todo, o conjunto de sensores será composto por sensores mais específicos e
especializados. Isso garante as vantagens de ter os sensores de maneira leve. Para
garantir a manutenção dessa leveza, a cada novo método a ser implementado, deve-se
pensar se uma nova classe na árvore de sensores não seria uma implementação mais
adequada do que a inserção de um método, simplesmente, em um sensor já existente.
Às vezes, nem mesmo é objetivo do projeto fazer uma série de objetos de
maneira mais completa possível. Essa idéia se baseia em objetos enxutos, que não
sejam construídos de uma maneira que se tornem pesados em seu uso, contendo
métodos e atributos que não sejam usados freqüentemente. Com esse objetivo, obtêm-
se objetos mais leves em termos de usos de processamento e de uso de memória.
Dessa maneira, é muito comum que se achem limitações na funcionalidade desses
objetos, ao se deparar com uma situação de uso não muito corriqueira.
Sejam quaisquer dessas alternativas acima citadas, a implementação dos
sensores no Mundo dos Atores vai, certamente, no seu uso futuro, requerer a
implementação de novos métodos nos sensores existentes, assim como a colocação de
novos atributos que venham a se mostrar necessários no seu uso.
É fato que existe a possibilidade, ao se verificar uma necessidade não
implementada, de criar-se uma nova classe (ou um novo conjunto de classes) que
satisfaça estas necessidades verificadas, como já foi citado, mas no caso de uma
necessidade local, e que acarrete pouca mudança na estrutura já implementada, pode
ser feita com a adição simples de métodos e atributos nos sensores já existentes
atualmente.
71
4.2.4 Verificação com outros modelos de paralelismo
Verificar a implementação de sensores em outros ambientes onde o
modelo seja diferente do modelo de eventos discretos, usado no Mundo dos Atores.
Nestes casos, os sensores poderão ser realmente ativos, sendo capazes de enviar
mensagens para os atores a quem pertencem e também para os atores que tem
interação com este ator. Desta forma, os atores podem desviar a atenção daquilo que
estão executando para ações a serem tomadas quando da ocorrência de algum aviso de
alguma verificação feita por parte dos sensores, através do uso de interrupções nos
atores.
4.3 REFERÊNCIAS BIBLIOGRÁFICAS
[Abdala 2002] Abdala, D. D. & Wangenheim, A. von (2002) em Conhecendo
Smalltalk
72
[Franchin 1999] Franchin, M. N. (1999). Elementos de Robótica.
http://www.dee.bauru.unesp.br/~Emarcelo/robotica, último acesso em
10/05/2003
[Jonathan 1994] Jonathan, M. Introdução à Programação Orientada a Objetos
com Smalltalk. http://www.inf.ufsc.br/poo/smalltalk/jonathan/index.html, último
acesso em 7/12/2003
[Launt 2003] Lount, P. W. A Brief Introduction to Smalltalk.
http://www.smalltalk.org, último acesso em 7/12/2003
[Liskov e Ziller 74] Liskov, B e S. Ziller, Programming with Abstract Data
Types, SIGPLAN Notices, April 1974, pp. 50-59.
[Mariani 1998] Mariani, A. C. (1998) O Mundo dos Atores: uma perspectiva de
introdução à programação orientada a objetos. Anais do Simpósio Brasileiro de
Informática na Educação (SBIE). Fortaleza, Ceará.
[Mariani 2001] Mariani, A. C. (2001) O Mundo dos Atores.
http://www.inf.ufsc.br/poo/atores, último acesso em 7/12/2003
73
[Matsui 2002] Matsui, T. & Hirukawa, H. (2002) Constrained Motion
Simulation on WWW. http://www.etl.go.jp/~matsui/Motion/, último acesso em
10/05/2003
[Sick 2002] Sick Brasil. Tipos Especiais de Sensores.
http://www.sick.com.br/especiais.htm, último acesso em 12/07/2003
[Swarm 2002] Swarm Project. http://www.swarm.org/, último acesso em
10/05/2003
[Taylor 2002] Taylor, H. (2002) Multimedia Technology.
http://www.cee.hw.ac.uk/courses/5ig2/, último acesso em 10/05/2003
[Wazlawick 1999] Wazlawick, R. S. & Mariani, A. C. (1999) em
Aprendizagem de Programação Orientada a Objetos com Smalltalk. Anais da VII
Escola Regional de Informática da SBC, Regional Sul. Londrina, PR; Chapecó, SC;
Novo Hamburgo, RS.
[Berg 1998] Berg, A. C. & Figueiró, J. P. (1998) em Lógica de Programação
4.4 BIBLIOGRAFIA
74
[Bramorski 1998] Bramorski, M.M. & Marques E. F. , J. (1998) Apostila de
VRML Básico
[Fraden 1996] Fraden, J. Handbook of Modern Sensors
[Flesch 1996] Flesch, C. A. Medição de Grandezas Mecânicas
[Pianesso 2002] Pianesso, A. C. Fiorin. Identificação e Classificação de
Comportamentos de Objetos Dinâmicos.
[Dowling 2002] Dowling, K. Robotics Frequently Asked Questions List
http://www.frc.ri.cmu.edu/robotics-faq/, último acesso em 22/01/2003
75
ANEXO 1 – ARTIGO
IMPLEMENTAÇÃO DE SENSORES NO MUNDO DOS ATORES
Autor: Fabrício Barcellos Aguirre
RESUMO
Esse trabalho descreve a implementação de sensores na ferramenta didática Mundo dos Atores. Os sensores são inseridos na ferramenta de maneira natural, como uma hierarquia de objetos, fazendo parte do sistema.
Os comportamentos dos atores são definidos no papel dos mesmos. Essa descrição dos comportamentos é algo relativamente complexo, sendo um problema para a aprendizagem. Uma alternativa para diminuir a complexidade na descrição dos papéis dos atores é a implementação de sensores no Mundo dos Atores. Com essa alternativa, espera-se facilitar a descrição dos papéis, diminuindo uma dificuldade na aprendizagem de Orientação a Objetos utilizando essa ferramenta.
PALAVRAS CHAVE: Sensores, informática na educação, orientação a objetos, SmallTalk
ABSTRACT
This work describes the implementation of sensors in the didactic tool Mundo dos Atores. The sensors are inserted in the tool in natural way, as an object hierarchy, being part of the system.
The behaviors of the actors are defined in the schedule of the them. This description of the behaviors is something relatively complex, being a problem for the learning. An alternative to diminish the complexity in the description of the schedules of the actors is the implementation of sensors in the World of the Actors. With this alternative, is expected to facilitate the description of the schedules, diminishing the difficulty in the learning of Orientation the Objects using this tool.
KEYWORDS: Sensors, computer science in the education, object orientation, SmallTalk
INTRODUÇÃO
A Programação Orientada a Objetos (POO) é a mais usual forma de programação, atualmente. A POO, com características como hierarquia, heranças, atributos, métodos e seus vários conceitos, trás inúmeras vantagens para
76
os programadores, como possibilidade de reutilização de código e modularização da programação. Devido a esse conjunto de qualidades e a grande utilização desta programação no mercado de trabalho, a POO é muito explorada nos cursos da área de computação, onde muitas vezes esse tipo de programação é ensinado aos alunos desde as fases iniciais destes cursos.
O grande número de conceitos, assim como a interligação entre eles, acaba fazendo com que a aprendizagem da Orientação a Objetos seja algo difícil para alguns alunos, principalmente por aqueles que estão tendo seus primeiros contatos com a computação e a programação.
Visando diminuir essa dificuldade, foi desenvolvido o Mundo dos Atores. O Mundo dos Atores é uma ferramenta pensada para auxiliar o processo de aprendizado de Programação Orientada a Objetos. Com essa ferramenta, procura-se diminuir as dificuldades que possam surgir no aprendizado, tornando o conteúdo algo acessível para todos os alunos.
A ferramenta Mundo dos Atores é construída e integrada ao ambiente de programação Smalltalk, permitindo que se explorem desde os conceitos mais básicos aos mais avançados de POO. O Mundo dos Atores se baseia na programação por atores, em que os objetos não são simplesmente objetos estáticos, reativos, mas sim objetos dinâmicos, proativos, capazes de agir conforme forem programados para fazê-lo. Ele se baseia na metáfora palco/ator, na qual os objetos, que são os atores, estão presentes em um palco (também um objeto), e dentro deste, realizam as suas ações, trocando mensagens e interagindo entre si e com o próprio palco.
Alguns palcos se apresentam de maneira estática, porém outros, onde há a interação entre os atores, são baseados num modelo de computação por eventos discretos. Neste modelo, todos os atores são regidos por
um tempo discreto, e realizam suas ações através de um escalonamento do tempo, realizando troca de mensagens.
As ações que os atores devem realizar, quando estão no palco, seus comportamentos, são definidas em seus papéis. Essa descrição dos comportamentos é algo que por vezes se apresenta de maneira relativamente complexa, dificultando muitas vezes o propósito do ambiente, sendo essa complexidade um problema para a aprendizagem.
Uma alternativa para diminuir a complexidade na descrição dos papéis dos atores, ponto central a ser aprimorado neste trabalho, é a implementação de sensores no Mundo dos Atores. Com essa alternativa, espera-se facilitar a descrição dos papéis, diminuindo uma dificuldade na aprendizagem de Orientação a Objetos utilizando essa ferramenta.
Neste trabalho foram implementados sensores, de maneira que a descrição dos papéis desempenhados pelos atores fosse descrita de uma maneira menos complexa. A noção de sensores é baseada nos sensores mecânicos existentes na área de engenharia mecânica e também nos sentidos dos seres vivos, especialmente os humanos.
Os sensores implementados podem ser usados segundo duas alternativas, seguindo a idéia de sensores passivos (reativos), com os dados sob demanda ou os sensores pró-ativos, com o sensor sendo capaz de disparar ações nos atores.
1 – LEVANTAMENTO PRELIMINAR
1.1 MUNDO DOS ATORES
77
O Mundo dos Atores (Figura 1) é uma ferramenta pensada para auxiliar o processo de aprendizado de Programação Orientada a Objetos (POO), com facilidades de maneira a ensinar de maneira paralela à modelagem e a implementação de sistemas. Por ser implementado e completamente integrado no ambiente Smalltalk, o Mundo dos Atores oferece uma forma bem didática de exploração dos conceitos relacionados com a programação orientada a objetos, partindo dos conceitos mais básicos até os mais avançados. Do primeiro ao último contato com ele, o aprendiz estará se expressando e se familiarizando de acordo com o paradigma de orientação a objetos.
Não é necessário nenhum conhecimento prévio sobre técnicas de programação de computadores para poder interagir com o Mundo dos Atores. Ele necessita, apenas, uma certa "alfabetização tecnológica" do usuário que desejar utilizá-lo, no que se refere a operação com um ambiente computacional (saber usar os dispositivos de entrada, como mouse e teclado, ou o ambiente operacional, devem ser técnicas bem dominadas).
É baseado numa metáfora de palco e atores, de maneira que o aprendiz trabalhe com elementos virtuais atores e o palco, manipulando objetos, mesmo que não tenha recebido a explicação formal sobre os objetos. Os atores se encontram dentro do palco, e realizam as suas ações, trocando mensagens e interagindo entre si e com o próprio palco.
O Mundo dos atores é aberto e expansível. Apresenta um palco mais simples, o Palco da Caneta, onde existe apenas uma área gráfica (o palco) e um ator (a caneta), e está estruturado de forma a permitir que o aprendiz também possa definir outros atores e pô-los para interagir, assim como criar outros palcos particulares, conforme a necessidade. Esta possibilidade de construção progressiva de modelos cada vez mais complexos é o ponto base para exploração sistemática dos conceitos
da POO.
A ferramenta está implementada na linguagem/ambiente Smalltalk-V/Win, estando em completa integração com esse ambiente de POO. Com isso o Mundo dos Atores pode ser facilmente integrado com qualquer outra aplicação disponível. Isto significa que o aprendiz não está restrito aos recursos oferecidos pelo Mundo dos Atores, mas sim livre para utilizar todos os recursos oferecidos por Smalltalk. Ele é, em realidade, uma aplicação que faz uso dos recursos do ambiente Smalltalk, inclusive de sua linguagem de programação a qual é utilizada para descrever o comportamento dos atores e para definir novos palcos. Segundo [Mariani 1998], esta característica é desejável, pois permite uma passagem gradativa e incremental para o desenvolvimento de sistemas computacionais completamente independentes do Mundo dos Atores, a exemplo de aplicações comerciais.
Com as características, o Mundo dos Atores é particularmente indicado para utilização em disciplinas introdutórias de computação ou informática em qualquer nível, assim como disciplinas de modelagem, programação orientada a objetos ou programação de forma paralela. Por também apresentar como um de seus componentes internos um ambiente similar ao oferecido pela linguagem LOGO (Seymour Papert), ele também pode ser utilizado para explorar vários conceitos matemáticos, assim como exercitar aspectos como desenvolvimento da criatividade e habilidade estética entre os usuários do sistema.
1.2 COMO FUNCIONA
Alguns palcos se apresentam de maneira estática, onde os atores são inseridos pelo aprendiz, e respondem a comandos passados a eles na forma de mensagens. Outros palcos, onde há a interação entre os atores, são
78
baseados num modelo de computação por eventos discretos. Neste modelo, todos os atores são regidos por um tempo discreto, e realizam suas ações através de um escalonamento do tempo, realizando troca de mensagens entre si. As ações dos atores, neste caso, estão descritas num roteiro, que indica seus papéis no palco. A definição desses papéis possibilita o estabelecimento de comportamentos para os atores. O PalcoComEventosDiscretos é que responsável por implementar o processo de animação chamado de modelo de eventos discretos.
Cada objeto que for criado pelo usuário do Mundo dos Atores deve ser uma subclasse da classe Ator. Nos palcos com eventos discretos, tem-se a classe AtorComEventosDiscretos, que implementa as operações básicas do tipo de atores que implementam uma forma de paralelismo, com o uso de papéis para cada ator, tendo um comportamento associado à sua existência no ambiente. Atores com eventos discretos, associados a um papel, deixam de ser apenas objetos estáticos (reativos), passando a ser objetos dinâmicos (pró-ativos), pois não apenas reagem a comandos passados pelo aprendiz, mas sim, desempenham seu comportamento conforme descrito na descrição do papel.
O método "definePapel" deve ser implementado em todos os atores com eventos discretos dos quais se deseja a realização de alguma atividade no tempo discreto. Esse método, o "definePapel" estabelece o 'schedule' de um ator, ou seja, um conjunto de ações que compõem o seu papel, que ele executará em determinados momentos nos quais estão especificados no seu papel.
O 'schedule' de um ator consiste em uma tabela em que as linhas contêm uma condição, seguida de uma ação. Todas as linhas desta tabela são verificadas a cada passo de interação do tempo discreto. Se a condição for verdadeira, então a ação é executada. Entretanto, alguns comandos pré-definidos
tornam a definição do 'schedule' mais intuitiva. Estes principais comandos são basicamente: "sempreFaca:", "sempreQue:faca:", "cada:faca" e "comProbabilidadeDe:faca:", embora outras variações também existam e possam ser implementadas pelo usuário conforme a necessidade de uso num determinado momento.
Uma das características importantes de orientação a objetos que é pouco explorada hoje em dia, especialmente nos cursos de introdução à computação, é o paralelismo. Normalmente o aluno aprende a pensar e a modelar os problemas de uma forma seqüencial, mesmo vivendo em um mundo em que os objetos são todos de existência paralela. O paralelismo é visto somente em fases avançadas como uma forma de implementação (e modelagem) alternativa. Nessa visão, o paralelismo é aplicado para processos que envolvem principalmente o estudo de técnicas de concorrência a recursos, em termos de hardware e programas básicos como os sistemas operacionais. Este tipo de curso, normalmente no contexto de sistemas operacionais, não incentivam o aluno a produzir modelos que tenham paralelo com a realidade. Assim, a maioria dos programas continuam sendo concebidos de uma forma seqüencial, com um pensamento adquirido e treinado apenas para isso, programar seqüencialmente, mesmo quando uma abordagem de modelagem e programação de maneira paralela seria a mais indicada.
Um controlador de execução faz com que a cada instante cada um dos atores tenha oportunidade de executar o que está definido em seu papel (seus comandos). Desta maneira, evitam-se os problemas relacionados com a concorrência real, onde os atores poderiam acessar um recurso simultaneamente (disputa de recursos), e todos os mecanismos de controle associados a esse problema. Com o modelo de eventos discretos, pode-se trabalhar o conceito de paralelismo de uma forma bastante simples para o aprendiz, mantendo uma boa característica didática para, como já foi dito, que não se descuide de atingir os
79
objetivos de aprendizagem com os alunos.
Segundo [Wazlawick 1999], seria mais interessante iniciar os estudos de modelagem e programação com os estudantes utilizando-se diretamente uma abordagem que lhes permita modelar um problema paralelo da forma mais real possível, de forma paralela. Esta introdução, entretanto, não pode ser feita de uma forma muito complexa, para que não se descuide de atingir os objetivos de aprendizagem com os alunos.
Um modelo considerado adequado para ser utilizado na introdução à programação de forma a ensinar o modelo de paralelismo aos estudantes é o modelo de eventos discretos, presente no Mundo dos Atores. De uma maneira resumida, pode-se dizer que: “Do primeiro ao último contato com ele o aprendiz estará ‘falando’ segundo os preceitos da POO”. [Mariani 2001].
1.3 DIFICULDADES
Neste modelo de eventos discretos, em que cada objeto possui um papel (por isso, muitas vezes, se refere aos objetos como 'atores' do modelo) que define os comandos que devem ser executados por ele a cada instante (fatia de tempo ou time slice). Esse papel é muitas vezes denominado como o comportamento do objeto dinâmico.
Como visto na descrição detalhada (em 1.2), o 'schedule', ou plano, de cada ator deve ser programado para que ele desempenhe seu papel no ambiente, definindo de forma que ele faça, a cada instante desejado de tempo, uma checagem do ambiente, uma movimentação ou uma alteração no sistema, ou seja, tudo aquilo em que se deseja que o ator faça em termos de interação com o sistema.
Essa descrição dos comportamentos é algo que por vezes se apresenta de maneira complexa, contribuindo para muitas vezes dificultar o processo de aprendizagem. Visto que o propósito do ambiente é facilitar a aprendizagem, servindo como ferramenta prática para uma disciplina de introdução a POO em cursos de computação/informática [Mariani 1998], essa complexidade é algo que deve ser diminuído.
1.2 A LINGUAGEM SMALLTALK
A linguagem/ambiente de programação usada nesse trabalho é a linguagem Smalltalk-V/Win (Figura 4), na qual foi desenvolvido o Mundo dos Atores e que tem sido utilizado para ensino de Programação Orientada a Objetos, servindo como ferramenta prática para uma disciplina de introdução a POO.
Segundo [Abdala 2002], a linguagem Smalltalk inventou o conceito de orientação a objetos, sendo também a linguagem mais citada como exemplo de uma linguagem de programação revolucionária, bem concebida e elegante, sendo ainda, a única linguagem de programação comercialmente aplicada realmente orientada a objetos. Nada mais adequado, então, do que utilizar-se dessa linguagem para a apresentação de conceitos de orientação a objetos. Nesse caso, considera-se o uso da linguagem Smalltalk, visto que nela está implementada a ferramenta Mundo dos Atores.
Smalltalk foi projetado para ser fácil de aprender e usar. É uma linguagem expressiva que usa um sub conjunto da linguagem humana, baseado em substantivos e verbos. Isso facilita que se usem expressões claras, bem de acordo com o pensamento humano. Com isso, os programas em Smalltalk acabam se apresentando bem menores do que programas semelhantes, feitos em outras linguagens, fazendo mais trabalho com menor
80
quantidade de código, e com isso, menos custo de produção e manutenção de programas [Launt 2003].
2 – SENSORES NO MUNDO
Os sensores são baseados nos cinco sentidos dos seres humanos, ou seja, visão, tato, audição, olfato e paladar. Tem por função, transmitir informações acerca do ambiente para uma central de controle, semelhante ao cérebro humano, que se encarrega de fazer uso dessas informações.
O levantamento mostrou que estão presentes principalmente nas áreas de robótica (engenharia mecânica) e na Realidade Virtual (RV). Os sensores mais variados são os de robótica, pois essa área apresenta um vasto campo de aplicação. Estes sensores, de robótica são os que oferecem mais idéias para a implementação deste mecanismo em um ambiente computacional.
Os sensores que atualmente estão mais desenvolvidos são os sensores de visão, como radar e sensor de cores e os sensores de tato, como sensores de toque e de força.
2.1 SENSORES
O sensor é um dispositivo capaz de monitorar a variação de uma grandeza física e transmitir esta informação a um sistema de indicação que seja inteligível para o elemento de controle do sistema. É um dispositivo de entrada que converte um sinal de qualquer espécie em outro sinal que possa ser transmitido ao elemento indicador, para que este mostre o valor da grandeza que está sendo medida [Franchin 1999].
Podem ser chamados de Transdutores ativos ou transdutores passivos, pois convertem os sinais medidos em sinais de um medidor, por exemplo, como a pressão em um ponteiro ou numa coluna de líquido.
Primeiramente, ao se falar em sensores, lembram-se dos sentidos humanos, visão, tato, audição, olfato e paladar. É através desses sentidos que o ser humano percebe como se encontra o ambiente em que ele está inserido em um determinado momento, transformando as informações físicas, recebidas por eles, em impulsos cerebrais nas áreas responsáveis pelo processamento desses dados no cérebro. Os sentidos humanos são, portanto, transdutores ativos.
Pensando-se na maneira com que esses 'sensores humanos' interagem com o ambiente e o próprio ser, a robótica tem obtido avanços em adaptar esses sensores em suas tecnologias, nas funções semelhantes às em que desempenham papéis nos seres humanos.
Dos cinco sentidos humanos - visão, tato, ouvido, olfato e paladar - aqueles cujo paralelo artificial tem sido mais extensamente desenvolvidos são a visão e o tato (Figura 6). A visão do homem é o principal método de entrada de dados. Muita pesquisa em desenvolvimento industrial tem sido aplicada na tentativa de aumentar esta capacidade. Grandes esforços também tem sido voltados ao desenvolvimento de sensores de toque. Alguns avanços têm sido obtidos na área dos sensores de escuta, como por exemplo, a identificação de vozes humanas [Franchin 1999].
Neste presente trabalho, mostra-se que esses sensores são importantes para a robótica, e de que maneira são aproveitados, formulando uma boa idéia de quais sensores serão mais úteis e como implementá-los no Mundo dos Atores.
81
2.2 TIPOS DE SENSORES NA ROBÓTICA
Os sensores atualmente podem ser classificados de acordo com os princípios físicos sobre os quais eles estão baseados (ótico, acústico, e etc) ou de acordo com as quantidades medidas (distância, força, e etc). Entretanto, segundo [Franchin, 1999], os sensores são habitualmente classificados em dois principais tipos: sensores de contato e sensores sem contato. Em robótica, existem também sensores que indicam as condições internas dos robôs (como condições de voltagens e a carga da bateria, por exemplo) [Franchin, 1999].
2.2.1 SENSORES DE CONTATO
O primeiro grande grupo de sensores é o grupo dos chamados sensores de contato. Os sensores de contato são sensores que necessitam de um contato físico com algum objeto, para conseguirem desempenharem suas funções de sensoriamento. São sensores que tocam objetos para sentirem as informações.
2.2.2 SENSORES SEM CONTATO
O segundo grande grupo de sensores na robótica é o grupo dos chamados sensores sem contato. Os sensores sem contato são sensores que não necessitam de um contato físico com objetos para que consigam desempenhar as suas funções de sensoriamento. São sensores que vêem os objetos, ou a ausência desses objetos, para fornecerem as informações de sensoriamento.
2.3 SENSORES EM VRML
Uma outra área em que os sensores são implementados e aproveitados é na realidade virtual. A imersão em uma 'outra realidade' será mais completa quanto mais informações do ambiente simulado puderem ser passadas à pessoa que está inserida nessa realidade, assim como as informações relativas às ações da pessoa forem passadas ao sistema. Cabem aos sensores, tanto da pessoa envolvida, quanto os do sistema, fazerem a mediação de trocas de informações entre as ações de interação entre esse ambiente e o indivíduo que está imerso no ambiente.
Virtual Reality Modeling Language (VRML) é uma linguagem que tem por objetivo levar as características da realidade virtual inicialmente à Internet, estendendo-se a outros ambientes, como simulações históricas e industriais. De forma semelhante ao HTML (Hypertext Markup Language), pode-se usar o VRML para modelar diversos locais existentes como locais em mundos de realidade virtual. Para que isso fosse possível, foi necessário que houvesse dispositivos sensores nessa linguagem, para permitir a interação entre os objetos desses mundos de realidade virtual e com as pessoas inseridas nestes ambientes [Matsui 2002].
Segue uma lista dos sensores existentes na linguagem VRML e a descrição de cada função desempenhada por eles [Taylor 2002].
3 – DESCRIÇÃO DE PAPÉIS COM SENSORES
3.1 SENSORES – DESCRIÇÃO E
82
COMENTÁRIOS
A hierarquia de sensores pode sofrer modificações durante o seu uso, seja devido a limitações inerentes aos tipos de sensores escolhidos ou à linguagem e também devido à possível inexistência de sensores que se façam necessários nos seus diversos usos. Seguindo-se a arquitetura, novos sensores podem ser inseridos de forma a fazerem parte da árvore hierárquica de sensores já definida anteriormente. Isto ocorre pois todo o trabalho foi feito baseado no paradigma de Orientação a Objetos (OO).
Escolheu-se o paralelo dos sensores existentes em outras áreas de estudo (como visto em 2.5) para facilitar a compreensão dos atributos e das funcionalidades de que cada sensor dispõe em seu ambiente de trabalho, tornando o seu paralelo computacional mais adequado ao uso em ambientes com as variáveis de condição sendo semelhantes às apresentadas nos ambientes em que foram baseados.
3.2 SENSORES ATIVOS E SENSORES PASSIVOS
No Mundo dos Atores, quando um ator necessita informações sobre outros atores ele consulta diretamente estes atores via mecanismo de troca de mensagens oferecido pela POO. De forma similar, no caso dele necessitar informações sobre o ambiente, ele envia mensagens diretamente para o palco (exemplar da classe Palco) onde ele está. Esta abordagem tem alguns inconvenientes, conforme mencionado em 1.3. O uso de sensores visa precisamente intermediar esta obtenção de dados e, desta forma, facilitar a descrição dos papéis dos atores ao mesmo tempo em que busca reutilizar código.
No que se refere à forma de interação
entre os atores e os sensores, há dois modelos básicos: o de sensores passivos e o de sensores ativos.
3.2.1 Sensores Passivos
No caso de sensores passivos, a interação entre um ator e um sensor sempre é iniciada pelo ator. Sob demanda, o sensor verifica os dados e fornece aos atores, no caso de uma consulta. Esta alternativa segue o modelo clássico de troca de mensagens da POO. Desta maneira, os sensores encontram-se inativos enquanto não são consultados.
Durante a realização de uma consulta por parte do ator ao sensor, o sensor que está sendo consultado verifica o ambiente, naquele exato momento, obtendo uma informação e fornecendo para o ator o resultado dessa verificação. Desta forma, os dados são obtidos pelo ator sob demanda e quando não é consultado, o sensor permanece inativo.
3.2.2 Sensores Ativos
No caso dos Sensores Ativos, tem-se os dados verificados pelos sensores de forma autônoma, sem necessitar um consulta direta por parte do ator. Essas informações são verificadas pelo sensor e podem disparar ações ao serem fornecidas ao ator. Desta maneira, os sensores encontram-se sempre ativos e não são consultados, fornecendo as informações ao ator a cada instante. As ações disparadas pelos sensores nos atores são como interrupções em ambientes de execução paralelos.
O sensor que está sempre ativo, realizando uma verificação no ambiente e a cada momento o sensor está obtendo as informações externas e fornecendo para o ator o resultado dessas verificações.
83
3.3 PRINCÍPIOS DO SENSORIAMENTO DISCRETO
O princípio de ação dos sensores é que eles tenham, presentes em si próprios as informações pertinentes à sua função, que sejam capazes de descreverem estados do ambiente em que se encontram. Essas informações estarão presentes internamente no objeto sensor, e serão consultadas pelos objetos que agregaram a si um objeto de uma das classes de sensores.
Para que a informação fornecida seja confiável, se faz necessário que o sensor encontre-se sempre atualizado, ou seja, que as informações sejam, sempre que solicitadas, consistentes com aquilo que representa o estado do ambiente no momento em que é realizada a verificação. Isso se faz necessário para a confiabilidade do sensor e dos sistemas que dependem dos dados colhidos no ambiente. Essa confiabilidade dos dados de sensoriamento é um dos fundamentos no uso de sensores, em todas as áreas de utilização dos mesmos. A forma escolhida para que os sensores tenham as informações do ambiente de maneira consistente foi o repasse da informação solicitada no exato momento em que ela for verificada, de forma atômica.
A maneira de visualizar os dados do ambiente onde o sensores estão localizados, é através da utilização dos diversos métodos presentes nos sensores, disparado com o objetivo de se obterem os dados do sistema (do ambiente ou de outros atores), sempre que seja necessário para o ator obter esses dados, sempre consistentes.
Como o ambiente em questão, em todos os casos de utilização dos sensores no Mundo Dos Atores, será primordialmente um objeto da classe Palco, ou mais especificamente da classe PalcoComEventosDiscretos, decidiu-se criar uma subclasse chamada
PalcoComSensores, onde estão os palcos nos quais seus atores fazem uso de sensores para interagir com o ambiente.
3.4 ENCAPSULAMENTO
Uma das diferenças de termos sensores implementados no Mundo dos Atores é ter uma outra maneira de fazer com que os atores adquiram as informações referentes ao ambiente onde se encontram, ou seja, o palco e os outros atores também presentes. Sendo o sistema implementado sem a presença dos sensores, para poder saber qualquer informação no que se refere ao ambiente, o ator deve, através de seus métodos, mandar mensagens para o palco, para que possa receber essas informações. Após ter as informações em mãos, o ator toma as devidas decisões.
No caso de atores com sensores, essa comunicação do ator diretamente com o palco deixa de ser necessária. Com os sensores, os atores apenas mandam mensagens pedindo as informações que necessitam para os sensores, de maneira que a comunicação com o palco seja toda controlada unicamente pelo sensor. Após adquirir esses dados, comunicando-se com o palco, o sensor transmite, de forma transparente para o ator, os dados requeridos. De posse dessas informações, o ator pode tomar as suas decisões normalmente. Com essa maneira de ser implementado, o ator não precisa saber como se comunicar com o palco, não precisando saber os métodos usados, apenas precisa utilizar as funções equivalentes dos sensores. Desta forma, a comunicação entre atores e o palco fica sempre a cargo dos sensores, que oferecem um canal de comunicação, organizando a ligação entre palco e atores, facilitando a obtenção de informações pertinentes por parte dos atores.
Desta forma, a comunicação entre os atores e o palco fica mais clara e mais fácil de ser implementada. Essa facilidade vem do fato
84
de que, tendo os sensores uma maneira de obterem informações do palco, os atores que utilizem esses sensores não precisam saber como interagir diretamente com o palco, bastando apenas utilizar as capacidades dos sensores de obter essas informações.
3.5 SENSORES IMPLEMENTADOS
3.5.1 Classe Sensor
Nesta classe, têm-se as implementações de alguns dos métodos que devem estar presentes em todos os sensores das subclasses. Muitos deles só são implementados definitivamente nas subclasses. Além disto, também atributos comuns a todos os sensores são definidos nesta classe.
Os atributos desta classe são os seguintes:
- ator
- acao
- acaoDeFalha
- nome
Os métodos (com os argumentos) desta classe são os seguintes:
- acao: umSimbolo
- ativado
- ator: umAtor
- execu ta
- initialize
- isSensor
- nome
- nome: umString
3.5.2 CLASSES DE SENSORES
3.5.2.1 Classe Sensor De Área
Nesta classe, têm-se a reimplementação do método ativado, que retorna true quando o ator que tem este sensor não se encontra numa determinada área definida pelo usuário. Essa definição de área pode ser feita através do método area: umRetangulo, e é armazenada na variável area. O método de mesmo nome (area), retorna qual é a área na qual esse sensor está atuando.
3.5.2.2 Classe Sensor De Borda
Nesta classe, tem-se a definição de uma área retangular, através do método borda: umRetangulo, na qual o sensor tem implementado uma detecção de toque do ator nessa borda, retornando true caso haja esse toque. Essa implementação é feita no método ativado. O método borda retorna essa área com a variável borda, e o método disparaReflexao está disponível para calcular o ângulo de reflexão do ator que estiver utilizando esse sensor.
3.5.2.3 Classe Sensor De Atores
A classe sensor de atores está no
85
sistema como uma superclasse que engloba todos os atributos e métodos destinados à detecção de outros atores no palco. Segue-se uma descrição detalhada de suas características.
3.5.2.4 Classe Sensor De Proximidade
Primeira subclasse de SensorDeAtores, tem o método ativado disparando o método detectaAtoresProximos, que faz a checagem para ver se é detectado algum ator no alcance (variável definida no método alcance), e retorna true se for detectado algum. O atributo atoresProximos é retornado na ação de mesmo nome, assim como retorna o método atoresDetectados.
Os métodos atorMaisProximo e atorMaisProximoNoAlcance retornam apenas um ator, aquele que está mais próximo do ator com esse sensor, sendo que o segundo pode-se definir qual alcance. AtorMaisProximo também é uma variável com o ator que se encontra nessa condição. Os métodos executa e initialize seguem o mesmo padrão, sendo responsáveis pela realização de ações nos atores e inicialização do sensor.
3.5.2.5 Classe Sensor De Toque
Nesta classe, tem-se também a reimplementação do método ativado, que neste caso retorna true se o ator que tem esse sensor estiver em contato com algum outro ator. A reimplementação de atoresDetectados computa o conjunto de atores tocados (atributo atoresTocados), através do método detectaAtoresTocados. Com atoresTocados, existe o mesmo conjunto, já computado, obtido através da variável interna. O executa detecta se há algum ator que está sendo tocado, realizando a acao , se estiver configurada, assim como o initialize, que é o responsável por inicializar o
conjunto atoresTocados, uma coleção que inicia vazia.
3.5.2.6 Classe Sensor De Visão
Esta classe de sensores tem o método área: umaArea, em que o atributo área, referente à area onde a visão do sensor é efetiva, é definido com o valor dado. Área esta que é inicializada com valor zero no método initialize. O ativado é o método que retorna true se o conjunto de atores vistos pelo sensor for não vazio. Este conjunto é computado com o método detectaAtoresVistos (com ou sem a área dada) e obtido através do método atoresDetectados. O atributo atoresVistos, a coleção cos os atores vistos, pode ser obtido pelo método de mesmo nome, depois de computado.
Os métodos veAlguem e veQuantos calculam se o sensor detecta algum ator na área dada e retorna true caso veja alguém e o devolve número de atores vistos, respectivamente. O retanguloNaFrente é usado para calcular a área de visão do sensor. O método executa trata de executar as ações necessárias, conferindo a condição do sensor.
3.6 USO DOS SENSORES
Os atores que fazem uso dos sensores para obterem informações do ambiente em que se encontram podem se utilizar destes de três maneiras distintas, de modo que se tem a opção de escolha de qual será a maneira mais adequada ao caso em que se encontra a necessidade de uso dos sensores presentes. Essas maneiras distintas de implementação são baseadas nas duas formas de sensores vistas em 3.2, os sensores Passivos (3.2.1) e os Ativos (3.2.2).
86
3.6.1 Dicionário de Sensores
A primeira maneira é através da coleção sensores (um dicionário), onde, na definição dos sensores, são colocados os sensores que se determina que este ator tenha em si. Essa definição pode ser feita na inicialização, ou com o uso do método defineSensores, presente nos atores com esta função. O método homônimo retorna essa coleção inteira. A adição de novos sensores a esta coleção se dá com o método adicionaSensor: , onde é passado um sensor a ser adicionado.
Um determinado sensor pode ser chamado no dicionário pelo seu atributo nome, atributo que representa unicamente um dos sensores da coleção. Um sensor de um tipo específico pode ser retornado com o método sensor, para que seja possível a utilização das funcionalidades deste sensor, dentro do ator, sem ter que trabalhar com todo o coleção.
Com essa mesma estruturação, pode-se também trabalhar com o conjunto de sensores, quando essa for a solução mais adequada, utilizando operações diretamente sobre os conjuntos. Essa forma faz utilização dos sensores passivos, vistos em 3.2.1.
Essa maneira de utilização não implica mudanças na atual implementação do modelo de execução. O ator reage à informação obtida conforme as suas condições estão configuradas para a interpretação desse dado.
3.6.2 Métodos de Verificação
Uma segunda maneira de utilização é através dos métodos de verificação citados a seguir:
- verificarSempre: umSensor
- verificar: umSensor aCada:
-verificar: umSensor comProbabilidadeDe:
- verificar: umSensor em:
- verificar: umSensor sempreQue:
Estes métodos presentes na classe AtorComSensores são todos usados na definição do papel dos atores, para que a execução atrelada aos sensores (método executa, configurado em cada sensor) seja executada sempre conforme a condição dada. Essa forma de verificação é também baseada em sensores Passivos (vistos em 3.2.1), pois o ator obtém os dados sob demanda, ao consultar o sensor.
Desta maneira, o schedule não é alterado, pois é passado um bloco condição/ação semelhante ao de uma definição de ação normal, onde a execução é dependente da condição de cada um dos sensores. As ações a serem tomadas são configuradas nas variáveis acao e acaoDeFalha, presentes em cada um dos sensores. Essa maneira de utilização dos sensores também não implica mudanças na atual implementação do modelo de execução. O ator reage à informação obtida conforme as suas condições interpretem esse dado.
3.6.3 Inserção no Schedule do ator
A terceira maneira de se utilizar os sensores é através dos seguintes métodos:
- seSensorAtivado: umSensor faca: umaAcao
- seSensorAtivado: umSensor faca: umaAcao
87
emCasoDeFalha: outraAcao
- seSensorAtivado: umSensor e: outroSensor faca: outraAcao
- seSensorAtivado: umSensor ou: outroSensor faca: umaAcao
- seFalhaESensorAtivado: umSensor faca: umaAcao
- seFalhaGeralNosSensores: umaAcao
Estes métodos da classe dos atores atorComSensores, permitem que a verificação de um sensor, juntamente com a ação a ser tomada, sejam colocados, através da definição do papel, no schedule do ator, de maneira que a verificação da sua condição de atuação seja feita e a ação a ser tomada seja dada nesta mesma mensagem. Com esta abordagem, os sensores agem de forma mais independente, sendo chamados de sensores ativos, como vistos em 3.2.2. Devido a limitações inerentes ao modelo de execução, o sensor acaba sendo passivo, mas para o usuário, que não se encarrega de configurar o envio de mensagens dos atores para os sensores, a operação acaba ocorrendo de forma transparente, de maneira semelhante a um sensor ativo, sem que eles se enquadrem realmente nessa classificação.
Desta maneira, não se fica atrelada a verificação da condição de ativação do sensor com as ações presentes em seus atributos (acao e acaoDeFalha), pode-se passar qualquer ação para que seja disparada pela condição do sensor.
3.7 DEFINIÇÃO DE PAPÉIS EM ATORES COM SENSORES
No Mundo dos Atores, cada ator envolvido com algum palco desempenha as
suas funções ao seguir um roteiro de ações, ações essas que estão descritas no seu papel dentro do palco. Em muitos casos, a utilização dos sensores permite uma implementação alternativa com relação aos papéis descritos nos atores, já que muitas das ações descritas nesse papel dos atores podem ser relacionadas com consultas aos sensores que estejam inseridos nesses atores e, através dessas consultas, as ações podem ser realizadas pelos atores. Fazendo o uso de sensores na descrição destes papéis, tem-se uma diminuição da complexidade dessa descrição. Com isso, essa tarefa torna-se mais fácil de ser compreendida.
Neste tópico encontra-se feita uma análise de alguns dos palcos quanto à mudança ocorrida na definição dos papéis dos atores. O uso dos sensores nos atores, aqui analisado, foi baseado na utilização de um dicionário de sensores (descrito em 3.6.1), no qual estão contidos todos os sensores de cada ator.
As maneiras de se implementar variam em cada caso, estando dependentes de qual o conjunto de atores e sensores que interagem em um determinado palco. Primeiramente, os atores que tem implementados em si os sensores devem ser subclasse de AtorComSensores, assim como o palco deve ser subclasse do palco PalcoComSensores, para que seja possível a utilização dos sensores nestes casos, devido aos atributos e métodos implementados nestas superclasses, específicos para serem usados em ambientes com sensores. Verifica-se agora, em alguns exemplares de palcos específicos, quais são e de que forma são feitas essas implementações da definição dos papéis destes atores.
Através do uso dos sensores, tem-se uma maneira fácil de encapsular a comunicação do ator com o palco em que ele desempenha seu papel, de maneira que toda a informação que o ator com sensores tiver que receber do palco, com relação ao seu próprio estado, ou com relação com os outros atores presentes, ele receberá através das funcionalidades dos
88
sensores.
Toda consulta aos sensores retorna um valor consistente, pois a verificação do ambiente é sempre feita no momento em que o sensor vai efetivamente utilizar a resposta para a tomada de decisão, como reação à mensagem passada pelo ator. O uso dos sensores é simples, de maneira a tornar a implementação mais simples que uma consulta ao palco, visto que não é mais necessário que o implementador tenha conhecimento dos métodos presentes no palco, mas apenas dos métodos dos sensores, que se apresentam sempre de maneira específica para o que foram projetados.
4 – CONSIDERAÇÕES FINAIS
4.1 CONCLUSÃO
Os sensores implementados foram implementados de maneira completamente integrada ao ambiente/linguagem Smalltalk, assim com o Mundo dos Atores, permitindo que o aprendiz faca uso desses sensores da forma natural, assim como a hierarquia de palcos e atores do Mundo do Atores.
A Hierarquia de Sensores é expansível, facilitando a inclusão de novos sensores.
O aprendiz não necessita conhecer os métodos da classe Palco, bastando conhecer os métodos dos sensores, que são mais específicos para o uso no qual se destinam. Com isso, consegue-se uma mesma funcionalidade já provida anteriormente pelos métodos do palco, mas de uma forma mais direta.
A implementação dos sensores no Mundo dos Atores permitiu que a descrição dos papéis dos atores se apresente de uma maneira menos complexa que anteriormente, tornando mais simples a programação e a interpretação destes papéis. Isso foi verificado através da comparação dos palcos que não faziam uso de sensores, e dos palcos onde os atores fazem uso destes sensores.
As três maneiras de utilização permitem uma flexibilização, fazendo com que o uso seja feito com os sensores da maneira mais adequada possível a uma determinada ocasião. Isso é possível pois os dois paradigmas de sensores, tanto Sensores Reativos como Sensores Pró-Ativos, podem ser utilizados.
O trabalho em disciplinas, ou seja, com grupo de estudantes, não foi realizado para avaliação do uso dos sensores de forma conjunta com a ferramenta, para que o uso dos sensores possa ser verificado na prática.
O uso de Smalltalk como linguagem de programação neste trabalho foi interessante por ter uma sintaxe diferente das linguagens usuais, como C, Pascal ou Fortran. Esse uso é importante, para que o aprendiz tenha contato com uma outra visão em termos de linguagens de programação.
REFERÊNCIAS BIBLIOGRÁFICAS
[Abdala 2002] Abdala, D. D. & Wangenheim, A. von (2002) em Conhecendo Smalltalk
89
[Franchin 1999] Franchin, M. N. (1999). Elementos de Robótica.
http://www.dee.bauru.unesp.br/~Emarcelo/robotica, último acesso em 10/05/2003
[Jonathan 1994] Jonathan, M. Introdução à Programação Orientada a Objetos com Smalltalk. http://www.inf.ufsc.br/poo/smalltalk/jonathan/index.html, último acesso em 7/12/2003
[Launt 2003] Lount, P. W. A Brief Introduction to Smalltalk. http://www.smalltalk.org, último acesso em 7/12/2003
[Liskov e Ziller 74] Liskov, B e S. Ziller, Programming with Abstract Data Types, SIGPLAN Notices, April 1974, pp. 50-59.
[Mariani 1998] Mariani, A. C. (1998) O Mundo dos Atores: uma perspectiva de introdução à programação orientada a objetos. Anais do Simpósio Brasileiro de Informática na Educação (SBIE). Fortaleza, Ceará.
[Mariani 2001] Mariani, A. C. (2001) O Mundo dos Atores. http://www.inf.ufsc.br/poo/atores, último acesso em 7/12/2003
[Matsui 2002] Matsui, T. & Hirukawa, H. (2002) Constrained Motion Simulation on WWW. http://www.etl.go.jp/~matsui/Motion/, último acesso em 10/05/2003
[Sick 2002] Sick Brasil. Tipos Especiais de Sensores. http://www.sick.com.br/especiais.htm, último acesso em 12/07/2003
[Swarm 2002] Swarm Project. http://www.swarm.org/, último acesso em 10/05/2003
[Taylor 2002] Taylor, H. (2002) Multimedia Technology. http://www.cee.hw.ac.uk/courses/5ig2/, último acesso em 10/05/2003
[Wazlawick 1999] Wazlawick, R. S. & Mariani, A. C. (1999) em Aprendizagem de Programação Orientada a Objetos com Smalltalk. Anais da VII Escola Regional de Informática da SBC, Regional Sul. Londrina, PR; Chapecó, SC; Novo Hamburgo, RS.
[Berg 1998] Berg, A. C. & Figueiró, J. P. (1998) em Lógica de Programação
[Bramorski 1998] Bramorski, M.M. & Marques E. F. , J. (1998) Apostila de VRML Básico
[Fraden 1996] Fraden, J. Handbook of Modern Sensors
[Flesch 1996] Flesch, C. A. Medição de Grandezas Mecânicas
[Pianesso 2002] Pianesso, A. C. Fiorin. Identificação e Classificação de Comportamentos de Objetos Dinâmicos.
[Dowling 2002] Dowling, K. Robotics Frequently Asked Questions List
http://www.frc.ri.cmu.edu/robotics-faq/, último acesso em 22/01/200
89
ANEXO 2 – CÓDIGO FONTE PRODUZIDO
Classe Sensor
Object subclass: #Sensor
instanceVariableNames:
'ator acao acaoDeFalha nome '
classVariableNames: ''
poolDictionaries: '' !
!Sensor class methods !
new
"Answer a new instance of the receiver."
self error: 'Utilizar o método #new: para criar sensores'.!
new: umAtor
^super new
initialize;
ator: umAtor;
yourself! !
90
!Sensor methods !
acao: umSimbolo
"Define qual a ação a ser disparada pelo sensor"
acao := umSimbolo.!
ativado
"Ação presente em todos os sensores
Permite o retorno da condição do sensor Ativado/Desativado
Implementado nas subclasses"
self implementedBySubclass.!
ator: umAtor
"Permite configurar a que ator o sensor pertence"
ator := umAtor.!
91
executa
"Faz com que o ator execute uma ação caso o sensor se
encontre ativado (acao), ou em caso contrário (acaoDeFalha)"
self ativado ifTrue: [
acao notNil ifTrue: [
ator perform: acao.
].
] ifFalse: [
acaoDeFalha notNil ifTrue: [
ator perform: acaoDeFalha.
].
].!
initialize
"Ação para inicializar o sensor"!
isSensor
"Retorna true se o objeto for um sensor"
^true.!
92
nome
"Recebe o nome que identifica o sensor"
^nome!
nome: umString
"Define um nome para identificar o sensor"
nome := umString.! !
93
Classe SensorDeArea
Sensor subclass: #SensorDeArea
instanceVariableNames:
'area '
classVariableNames: ''
poolDictionaries: '' !
!SensorDeArea class methods ! !
!SensorDeArea methods !
area
"Retorna a área de ativação do sensor"
area ifNil: [
^ator palco retangulo
].
^area!
94
area: umRetangulo
"Define a área de ativação para o sensor"
area := umRetangulo.!
ativado
"Retorna true se o sensor estiver ativado, ou seja, se o ator
que contém esse sensor se encontrar dentro da área de ativação"
^self area containsPoint: ator posicao.! !
95
Classe SensorDeAtores
Sensor subclass: #SensorDeAtores
instanceVariableNames:
'classeDeSensibilidade cardinalidadeUnitaria '
classVariableNames: ''
poolDictionaries: '' !
!SensorDeAtores class methods ! !
!SensorDeAtores methods !
atorDetectado
"Ação presente em todos os sensores
Permite que os sensores detectem um ator
Implementado nas subclasses"
self atoresDetectados notEmpty ifTrue: [
^self atoresDetectados asArray first
] ifFalse: [
96
^nil
]!
atoresDetectados
"Ação presente em todos os sensores
Permite que os sensores disparem ações configuradas,
caso o sensor esteja na condição ativado
Implementado nas subclasses"
self implementedBySubclass.!
detectaAtorDoTipo: umaClasse
"Detecta um ator do tipo pedido"
cardinalidadeUnitaria := true.
classeDeSensibilidade := umaClasse.!
detectaAtoresDoTipo: umaClasse
"Detecta vários atores do tipo pedido"
cardinalidadeUnitaria := false.
classeDeSensibilidade := umaClasse.!
97
executa
"Faz com que todos os atores que tenham tido
contato entre si executem uma ação (acao, atributo
desta classe), ou em si próprio(acaoEmSi)"
|atores|
atores := self atoresDetectados.
atores notEmpty ifTrue: [
acao notNil ifTrue: [
cardinalidadeUnitaria ifTrue: [
ator perform: acao" with: (atores asArray first)".
] ifFalse: [
ator perform: acao" with: atores".
]
].
] ifFalse: [
acaoDeFalha notNil ifTrue: [
ator perform: acaoDeFalha.
].
].!
initialize
98
"Ação que inicializa as características dos sensores"
classeDeSensibilidade := Ator.
cardinalidadeUnitaria := false.! !
99
Classe SensorDeProximidade
SensorDeAtores subclass: #SensorDeProximidade
instanceVariableNames:
'atorMaisProximo atoresProximos alcance '
classVariableNames: ''
poolDictionaries: '' !
!SensorDeProximidade class methods ! !
!SensorDeProximidade methods !
alcance: umValor
"Define o valor do alcance do sensor de proximidade"
alcance:= umValor.!
ativado
"Retorna true caso haja algum ator detectado dentro do alcance do sensor"
100
atoresProximos := self detectaAtoresProximos.
^atoresProximos notEmpty.!
atoresDetectados
"Retorna o conjunto de atores detectados por este sensor"
^self detectaAtoresProximos.!
atoresProximos
"Retorna os atores mais próximos do ator que tem esse sensor"
^atoresProximos.!
atorMaisProximo
"Retorna o ator mais próximo do ator ao qual pertence esse sensor"
atorMaisProximo := ator palco atorDoTipo: classeDeSensibilidade maisProximoDe: ator.
atorMaisProximo isNil ifFalse:[
alcance notNil ifTrue: [
((atorMaisProximo distanciaPara: ator) > alcance) ifTrue: [atorMaisProximo := nil].
101
]
].
^atorMaisProximo.
" atorMaisProximo := self detectaAtoresProximos."!
atorMaisProximoNoAlcance: umValor
"Retorna o ator mais próximo do ator ao qual pertence esse
sensor dentro do alcance passado como parâmetro desse método"
atorMaisProximo := self atorMaisProximo.
atorMaisProximo isNil ifFalse:[
((atorMaisProximo distanciaPara: ator) > umValor) ifTrue: [atorMaisProximo := nil]].
^atorMaisProximo.!
detectaAtoresProximos
"Retorna os atores mais próximos do ator que tem esse sensor"
atoresProximos := ator palco atoresDoTipo: classeDeSensibilidade.
102
alcance notNil ifTrue:[
atoresProximos do: [:umAtor| ((umAtor distanciaPara: ator) > alcance) ifTrue:[
atoresProximos remove:
umAtor
]
]
].
^atoresProximos.! !
103
Classe SensorDeToque
SensorDeAtores subclass: #SensorDeToque
instanceVariableNames:
'atoresTocados '
classVariableNames: ''
poolDictionaries: '' !
!SensorDeToque class methods ! !
!SensorDeToque methods !
ativado
"Retorna true se exista algum ator que esteja tocando o ator com este sensor"
atoresTocados := self detectaAtoresTocados.
^atoresTocados notEmpty.!
atoresDetectados
104
"Retorna o conjunto de atores que foi tocado
pelo ator que tem este sensor"
^self detectaAtoresTocados.!
atoresTocados
"Retorna os atores tocados pelo ator que tem o que tem o sensor"
^atoresTocados!
detectaAtoresTocados
"Retorna os atores tocados pelo ator que tem o que tem o sensor"
classeDeSensibilidade isNil ifTrue: [
^ator palco atoresQueSobrepoem: ator
] ifFalse: [
^ator palco atoresDoTipo: classeDeSensibilidade queSobrepoem: ator
].! !
105
Classe SensorDeVisao
SensorDeAtores subclass: #SensorDeVisao
instanceVariableNames:
'atoresVistos area '
classVariableNames: ''
poolDictionaries: '' !
!SensorDeVisao class methods ! !
!SensorDeVisao methods !
area: umaArea
"Configura a area de visão deste sensor"
area := umaArea.!
ativado
"Retorna true se houver algum ator visto na área do sensor"
106
atoresVistos := self detectaAtoresVistos.
^atoresVistos notEmpty.!
atoresDetectados
"Detecta os atores vistos e retorna o conjunto os contendo"
^self detectaAtoresVistos.!
atoresVistos
"Responde uma coleção de atores da ClasseDeSensibiliade
na area previamente informada"
^atoresVistos.!
detectaAtoresVistos
"Responde uma coleção de atores da ClasseDeSensibiliade na area informada"
classeDeSensibilidade isNil ifTrue: [
^(ator palco atoresEm: (self retanguloNaFrente: area) doTipo: Ator)
] ifFalse: [
^(ator palco atoresEm: (self retanguloNaFrente: area) doTipo: classeDeSensibilidade)
107
].!
detectaAtoresVistos: umaArea
"Responde uma coleção de atores da ClasseDeSensibiliade
na area informada como parâmetro deste método"
classeDeSensibilidade isNil ifTrue: [
^(ator palco atoresEm: (self retanguloNaFrente: umaArea) doTipo: Ator)
] ifFalse: [
^(ator palco atoresEm: (self retanguloNaFrente: umaArea) doTipo:
classeDeSensibilidade)
].!
initialize
"Inicializa os parâmetros sensor"
super initialize.
area := 0.!
retanguloNaFrente: tamanho
"Retorna uma área de retângulo na frente do ator"
108
|retangulo |
retangulo := ator retangulo.
ator direcao = 90 ifTrue: [
retangulo moveBy: 0 @ tamanho negated;
height: tamanho
] ifFalse: [
ator direcao = 180 ifTrue: [
retangulo moveBy: tamanho negated @ 0;
width: tamanho
] ifFalse: [
ator direcao = 270 ifTrue: [
retangulo moveBy: 0 @ ator tamanho y;
height: tamanho
] ifFalse: [
retangulo moveBy: ator tamanho x @ 0;
width: tamanho
].
].
].
^retangulo!
veAlguem: umaArea
109
"Responde se ele ve alguém da ClasseDeSensibiliade
na area de visão informada"
^(self detectaAtoresVistos: umaArea)notEmpty!
veQuantos: umaArea
"Detecta a quantidade de atores vistos"
^(self detectaAtoresVistos: umaArea)size.! !
110
Classe SensorDeBorda
Sensor subclass: #SensorDeBorda
instanceVariableNames:
'borda '
classVariableNames: ''
poolDictionaries: '' !
!SensorDeBorda class methods ! !
!SensorDeBorda methods !
ativado
"Retorna true se o sensor estiver ativado, ou seja, se o ator
que contém esse sensor se encontrar tocando a borda"
|areaInterseccao areaAtor|
areaAtor := ator retangulo.
(self borda intersects: areaAtor) ifFalse: [
111
^false
].
areaInterseccao := self borda intersect: areaAtor.
areaInterseccao extent < areaAtor extent ifTrue: [
^true
].
^(areaInterseccao top = areaAtor top) or: [
(areaInterseccao bottom = areaAtor bottom) or: [
(areaInterseccao left = areaAtor left) or: [
(areaInterseccao right = areaAtor right) ] ] ].!
borda
"Retorna a borda definida como de ativação"
borda ifNil: [
^ator palco retangulo
].
^borda!
borda: umRetangulo
"Configura a borda onde o sensor se ativará"
borda := umRetangulo.!
112
disparaReflexao
"Esta reflexão ocorre quando o ator bate na borda"
|retangulo|
retangulo := ator retangulo.
((retangulo left <= 0) or: [retangulo right >= ator palco tamanho x]) ifTrue: [
((retangulo top <= 0) or: [retangulo bottom >= ator palco tamanho y]) ifTrue: [
^ator gira: 180
] ifFalse: [
^ator apontaPara: 180 - ator direcao
]
].
((retangulo top <= 0) or: [retangulo bottom >= ator palco tamanho y]) ifTrue: [
((retangulo left <= 0) or: [retangulo right >= ator palco tamanho x]) ifTrue: [
^ator gira: 180
] ifFalse: [
^ator apontaPara: ator direcao negated
]
].! !
113
Classe Schedule
Object subclass: #Schedule
instanceVariableNames:
'eventos tempo foiLimpo '
classVariableNames: ''
poolDictionaries: '' !
!Schedule class methods !
executeCom: umAtor
"Avalia as condições e executa aquelas
ações cujas condições estejam satisfeitas."
|resultado indice evento palco sensor ouExecutado falhaAtual falhaGeral|
(palco := umAtor palco) ifNil: [
^self
].
foiLimpo := false.
indice := 1.
114
palco executaEventos.
[indice <= eventos size] whileTrue: [
falhaGeral := true.
evento := eventos at: indice.
(evento at: 1) isSensor ifTrue:[
(evento at: 2) isSensor ifTrue:[ "Se o segundo for sensor, é um E: ou um OU:"
(evento at: 5) ifTrue:[ "Caso do E:"
sensor := evento at: 1.
resultado := sensor ativado.
resultado ifTrue: [
sensor := evento at: 2.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 3) "with: sensor atoresDetectados".
falhaGeral := false.
].
]
] ifFalse:[ "Caso do OU:"
ouExecutado := false.
sensor := evento at: 1.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 3) "with: sensor atoresDetectados".
ouExecutado := true.
falhaGeral := false.
115
]
ouExecutado ifFalse:[
sensor := evento at: 2.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 3) "with: sensor atoresDetectados".
falhaGeral := false.
].
]
]. "Final do OU:"
] ifFalse: [ "Caso em que há apenas um sensor"
sensor := evento at: 1.
resultado := sensor ativado.
resultado ifTrue: [
umAtor perform: (evento at: 2) "with: sensor atoresDetectados".
falhaGeral := false.
] ifFalse: [
(evento at: 3) isNil ifFalse: [
umAtor perform: (evento at: 3)
].
].
foiLimpo ifTrue: [
^self
].
116
(evento at: 4) ifTrue: [
eventos removeIndex: indice
] ifFalse: [
indice := indice + 1
].
]
] ifFalse: [ "Se for valor lógico em 1, executa normalmente o bloco condição/ação"
resultado := (evento at: 1) value.
resultado isBoolean ifFalse: [
(evento at: 1) isSymbol ifTrue:[ "Caso do teste de Falha Geral"
falhaGeral ifTrue:[
umAtor perform: (evento at: 1).
].
] ifFalse: [ "Fim do Falha Geral"
self error: 'Condição do papel do ator não resulta em um valor true ou false'
]
].
resultado ifTrue: [
(evento at: 2) value.
foiLimpo ifTrue: [
^self
].
(evento at: 3) ifTrue: [
eventos removeIndex: indice
] ifFalse: [
117
indice := indice + 1
]
] ifFalse: [
indice := indice + 1.
foiLimpo ifTrue: [
^self
]
]
]. "Fim do Condição/Ação"
palco executaEventos.
].
tempo := tempo + 1.!
118
Classe PalcoComSensores
PalcoComEventosDiscretos subclass: #PalcoComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!PalcoComSensores class methods ! !
!PalcoComSensores methods !
anima
"Inicia animação"
self setFocus.
estaEmAnimacao := true.
self owner desabilitaEventos.
(self owner menuTitled: '&Atores')
enableItem: #paraExecucao.
Processor fork: [
119
[estaEmAnimacao] whileTrue: [
self atores do:[:ator|
ator executaSchedule.
].
tempo := tempo + 1.
tempo \\ self intervaloAtualizacaoDaTela = 0 ifTrue: [
self mostraAtores
]
]
] at: 3 name: 'Mundo'.!
sensores
|sensores|
sensores := OrderedCollection new.
self atores do: [:ator| sensores addAll: ator sensores].
^sensores! !
120
Classe PalcoInvasoresDoEspacoComSensores
PalcoComSensores subclass: #PalcoInvasoresDoEspacoComSensores
instanceVariableNames:
'canhao '
classVariableNames: ''
poolDictionaries: '' !
!PalcoInvasoresDoEspacoComSensores class methods ! !
!PalcoInvasoresDoEspacoComSensores methods !
characterInput: aCharacter
"Private - Process all character and control key input."
canhao dispara.!
insereAtores
"Insere dos atores principais no palco"
|lancador|
121
canhao := CanhaoComSensores new.
canhao entraNoPalco: self ;
pulaPara: (self tamanho x // 2) @ (self tamanho y - 50).
lancador := LancadorDeNavesComSensores new.
lancador entraNoPalco: self ;
pulaPara: 10@30.
self anima.!
scrollHorizontal: umInteiro
"Uma das teclas de deslocamento horizontal
foi pressionada. Se umInteiro for positivo
indica movimento para a esquerda, enquanto que
negativo indica movimento para a direita."
umInteiro negative ifTrue:[
canhao apontaPara: 0;
anda: 20
] ifFalse:[
canhao apontaPara: 180;
anda: 20
]! !
122
Classe PalcoMeioAmbienteComSensores
PalcoComSensores subclass: #PalcoMeioAmbienteComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries:
'Colors ' !
!PalcoMeioAmbienteComSensores class methods ! !
!PalcoMeioAmbienteComSensores methods !
insereAtores
"Insere dos atores principais no palco"
|ator tamanho presasAdultas presasJovens predadores gramas|
presasAdultas := 10.
presasJovens := 17.
predadores := 2.
gramas := 17.
123
tamanho := self tamanho.
presasAdultas vezesRepita: [
ator := PresaAdultaComSensores new.
ator entraNoPalco: self ;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y);
apontaPara: (self aleatorio: 360).
].
presasJovens vezesRepita: [
ator := PresaJovemComSensores new.
ator entraNoPalco: self ;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y);
apontaPara: (self aleatorio: 360).
].
predadores timesRepeat: [
ator := PredadorComSensores new.
ator entraNoPalco: self ;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y);
apontaPara: (self aleatorio: 360).
].
gramas vezesRepita: [
124
ator := GramaComSensores new.
ator entraNoPalco: self ;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).
].
" self anima. "! !
125
Classe PalcoSinucaComSensores
PalcoComSensores subclass: #PalcoSinucaComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries:
'Colors ' !
!PalcoSinucaComSensores class methods ! !
!PalcoSinucaComSensores methods !
Doit self bola tocouEmOutraBola!
insereAtores
"Insere os atores principais no palco"
|bola|
bola := BolaDeSinucaComSensores new
raio: 15 cor: Amarelo.
126
bola entraNoPalco: self;
pulaPara: 100@100;
apontaPara: 135.
bola := BolaDeSinucaComSensores new
raio: 15 cor: Verde.
bola entraNoPalco: self;
pulaPara: 200@200;
apontaPara: 35.
bola := BolaDeSinucaComSensores new
raio: 15 cor: Azul.
bola entraNoPalco: self;
pulaPara: 300@300;
apontaPara: -30.
bola := BolaDeSinucaComSensores new
raio: 15 cor: Vermelho.
bola entraNoPalco: self;
pulaPara: 400@400;
apontaPara: 80.! !
127
Classe PalcoSistemaBancárioComSensores
PalcoComSensores subclass: #PalcoSistemaBancarioComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!PalcoSistemaBancarioComSensores class methods ! !
!PalcoSistemaBancarioComSensores methods !
agenciaBancaria
"Retorna a agência bancária"
^self atorDoTipo: AgenciaBancaria!
insereAtores
"Insere dos atores principais no palco"
|agencia|
128
agencia := AgenciaBancaria new.
agencia nome: 'Trindade';
entraNoPalco: self;
pulaPara: self tamanho * 2 / 3.
self inserePessoas.
self insereLojas.
self anima.!
insereLojas
|loja |
loja := Loja new.
loja entraNoPalco: self;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).
loja := Loja new.
loja entraNoPalco: self;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).
loja := Loja new.
loja entraNoPalco: self;
129
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).
loja := Loja new.
loja entraNoPalco: self;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).!
inserePessoas
|pessoa |
pessoa := PessoaComSensores new.
pessoa nome: 'José';
entraNoPalco: self;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).
pessoa := PessoaComSensores new.
pessoa nome: 'Maria';
entraNoPalco: self;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).
pessoa := PessoaComSensores new.
pessoa nome: 'João';
entraNoPalco: self;
pulaPara: (self aleatorio: self tamanho x) @ (self aleatorio: self tamanho y).! !
130
Classe AtorComSensores
AtorComEventosDiscretos subclass: #AtorComSensores
instanceVariableNames:
'sensores '
classVariableNames: ''
poolDictionaries: '' !
!AtorComSensores class methods ! !
!AtorComSensores methods !
adicionaSensor: umSensor
(sensores includesKey: umSensor nome) ifTrue:[
MessageBox message: 'Já há sensor de nome ', umSensor nome,
' definido no ator ', self class name.
self halt.
] ifFalse: [
sensores at: umSensor nome put: umSensor.
].!
131
defineSensores
"Ação para configurar as características dos sensores"
"Implementado em cada classe de ator da sua maneira"!
initialize
"Private - Initialize the receiver."
sensores := Dictionary new.
super initialize.
self defineSensores.!
seFalhaESensorAtivado: umSensor faca: umaAcao
" seSensorAtivado: self sensorDeBola faca: #redirecionaBolas:
schedule sempreQue: booleanBloco faca: acaoBloco"!
seFalhaGeralNosSensores: umaAcao
"Se houver falha em todos os sensores anteriores, dispara a umaAcao"
schedule seFalhaGeral: umaAcao.!
132
sensor: umString
"Retorna o primeiro sensor da classe solicitada.
Retorna nil caso não haja nenhum.
Açaõ realizada sobre o Dicionário sensores"
^sensores at: umString ifAbsent: [
MessageBox message: 'Não há sensor de nome ', umString,
' definido no ator ', self class name.
self halt.
].!
sensores
^sensores!
seSensorAtivado: umSensor e: outroSensor faca: umaAcao
" seSensorAtivado: self sensorDeBola faca: #redirecionaBolas:
schedule sempreQue: booleanBloco faca: acaoBloco"!
seSensorAtivado: umSensor faca: umaAcao
133
" seSensorAtivado: self sensorDeBola faca: #redirecionaBolas:"
schedule sempreQueSensorAtivado: umSensor faca: umaAcao.!
seSensorAtivado: umSensor faca: umaAcao emCasoDeFalha: outraAcao
schedule quandoSensorAtivado: umSensor faca: umaAcao falha: outraAcao
removerAposExecucao: false!
seSensorAtivado: umSensor ou: outroSensor faca: umaAcao
" seSensorAtivado: self sensorDeBola faca: #redirecionaBolas:
schedule sempreQue: booleanBloco faca: acaoBloco"
schedule sempreQueSensorAtivado: umSensor ou: outroSensor faca: umaAcao.!
verificar: umSensor aCada: umInteiro
sensores add: umSensor.
schedule cada: umInteiro faca: [umSensor executa].!
verificar: umSensor comProbabilidadeDe: umFloat
134
schedule comProbabilidadeDe: umFloat faca: [umSensor executa].!
verificar: umSensor em: umInteiro
schedule em: umInteiro faca: [umSensor executa].!
verificar: umSensor sempreQue: booleanBloco
schedule sempreQue: booleanBloco faca: [umSensor executa].!
verificarSempre: umSensor
schedule sempreFaca: [umSensor executa].! !
135
Classe AtorDeTransitoComSensores
AtorComSensores subclass: #AtorDeTransitoComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!AtorDeTransitoComSensores class methods ! !
!AtorDeTransitoComSensores methods ! !
136
Classe CarroComSensores
AtorDeTransitoComSensores subclass: #CarroComSensores
instanceVariableNames:
'velocidade acelerando '
classVariableNames: ''
poolDictionaries: '' !
!CarroComSensores class methods ! !
!CarroComSensores methods !
apontaPara: umNumeroPontoOuAtor
"Aponta o ator para o ângulo umInteiro
do círculo trigonométrico (referência absoluta)
Ex: caneta apontaPara: 73.
caneta apontaPara: 73/5"
super apontaPara: umNumeroPontoOuAtor.
self mudaFiguraAndando.!
137
carroMaisProximoNaFrente: tamanho
"Retorna o carro que esta imediatamente à frente do receptor.
Retorna nil caso não haja carro na frente"
|distancia menorDistancia carroMaisProximo |
menorDistancia := 99999999.
((self sensor: 'visão carro') detectaAtoresVistos: tamanho) do: [:carro|
(distancia := self distanciaPara: carro) < menorDistancia ifTrue: [
menorDistancia := distancia.
carroMaisProximo := carro.
]
].
^carroMaisProximo!
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
|carroProximo novaVelocidade|
138
self sempreFaca: [
self haSemaforoVermelho ifTrue: [
velocidade := 0.
acelerando := false.
] ifFalse: [
carroProximo := self carroMaisProximoNaFrente: 60.
carroProximo isNil ifTrue: [
velocidade := 10.
acelerando := true.
] ifFalse: [
novaVelocidade := ((self distanciaPara: carroProximo) - 35 // 10) max: 0.
novaVelocidade > velocidade ifTrue: [
acelerando := true.
] ifFalse: [
novaVelocidade < velocidade ifTrue: [
acelerando := false.
]
].
velocidade := novaVelocidade.
].
].
self testaFigura;
anda: velocidade.
].
139
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self saiDoPalco
].!
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
(SensorDeVisao new: self)
nome: 'visão carro';
detectaAtoresDoTipo: CarroComSensores).
self adicionaSensor: (
(SensorDeVisao new: self)
nome: 'visão semaforo';
detectaAtoresDoTipo: Semaforo).
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque semaforo';
detectaAtorDoTipo: Semaforo).
self adicionaSensor: (
140
(SensorDeArea new: self)
nome: 'area visivel').!
gira: aNumber
"Change the direction of the receiver aNumber
number of degrees. If aNumber is positive, it
turns clockwise, if negative counter-clockwise."
super gira: aNumber.
self mudaFiguraAndando.!
haSemaforoVermelho
"Retorna true se não há semafaroVermelho na estrada"
((self sensor: 'toque semaforo') atoresTocados) notNil ifTrue: [
^false
].
((self sensor: 'visão semaforo') detectaAtoresVistos: 30) do: [ :sinal |
sinal figuraCorrente = (Mundo bitmaps at: 'semaforoVermelho') ifTrue: [
^true
].
141
].
^false!
initialize
"Private - Initialize the receiver."
|sensorDeVisao sensorDeToque|
super initialize.
self adicionaFigura:'CarroLeste';
adicionaFigura: 'CarroNorte';
adicionaFigura: 'CarroOeste';
adicionaFigura: 'CarroSul'.
self adicionaFigura:'CarroLesteFreiando';
adicionaFigura: 'CarroNorteFreiando';
adicionaFigura: 'CarroOesteFreiando';
adicionaFigura: 'CarroSulFreiando'.
direcao := 0.
acelerando := false.
velocidade := 0.
142
self opaco.!
mudaFiguraAndando
"Muda a figura do Carro quando andando"
self figura: (self direcao // 90) + 1!
mudaFiguraFreiando
"Muda a figura do Carro quando freiando"
self figura: (self direcao // 90) + 1 + 4!
naoHaCarroNaFrente
"Retorna true se o carro tem a preferencia na estrada"
|retangulo |
retangulo := self retangulo.
self direcao = 90 ifTrue: [
retangulo moveBy: 0 @ (self tamanho y negated // 2);
height: self tamanho y // 2
] ifFalse: [
self direcao = 180 ifTrue: [
143
retangulo moveBy: (self tamanho x negated // 2) @ 0;
width: self tamanho x // 2
] ifFalse: [
self direcao = 270 ifTrue: [
retangulo moveBy: 0 @ (self tamanho y);
height: self tamanho y // 2
] ifFalse: [
retangulo moveBy: (self tamanho x) @ 0;
width: self tamanho x // 2
].
]. ].
^(self sensor: 'visão carro') veAlguem: retangulo isEmpty.!
testaFigura
"Testa a condição de aceleração e muda a figura atual"
acelerando ifTrue: [
self mudaFiguraAndando
] ifFalse: [
self mudaFiguraFreiando.
].! !
144
Classe GeradorDeCarrosComSensores
AtorDeTransitoComSensores subclass: #GeradorDeCarrosComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!GeradorDeCarrosComSensores class methods ! !
!GeradorDeCarrosComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self comProbabilidadeDe: 0.04 faca: [self geraCarro].!
geraCarro
"Insere um novo CarroComSensores no palco."
145
|carro|
(self palco atoresEm: self retangulo doTipo: CarroComSensores) isEmpty ifFalse: [
^self
].
carro := CarroComSensores new.
carro entraNoPalco: self palco ;
pulaPara: self posicao;
apontaPara: self direcao.!
initialize
"Private - Initialize the receiver."
super initialize.
self adicionaFigura: 'disc';
invisivel.! !
146
Classe AtorFiguraGeometricaComSensores
AtorComSensores subclass: #AtorFiguraGeometricaComSensores
instanceVariableNames:
'figuraGeometrica '
classVariableNames: ''
poolDictionaries:
'Colors ' !
!AtorFiguraGeometricaComSensores class methods ! !
!AtorFiguraGeometricaComSensores methods !
contemPonto: umPonto
figuraGeometrica ifNil: [
^false
].
^figuraGeometrica containsPoint: umPonto!
corBorda
147
"Retorna a cor da borda do receptor"
^figuraGeometrica borderColor!
corBorda: umaCor
"Define a cor da borda do retângulo"
figuraGeometrica borderColor: umaCor.
self exibe.!
corPreenchimento
"Retorna a cor do interior do receptor"
^figuraGeometrica fillColor!
corPreenchimento: umaCor
"Define a cor do interior do retângulo"
figuraGeometrica fillColor: umaCor.
self exibe.!
148
duplica
|ator|
ator := self species new.
ator figuraGeometrica: self figuraGeometrica deepCopy;
corBorda: self corBorda;
corPreenchimento: self corPreenchimento.
ator entraNoPalco: self palco;
pulaPara: self posicao + 10.
^ator!
estaEm: umPontoOuRetangulo
"Retorna true caso o ator esteja ocupando um
espaço no palco que de alguma forma coincida
com umPontoOuRetangulo.
Retorna falso em caso contrário"
umPontoOuRetangulo isPoint ifTrue: [
^self contemPonto: umPontoOuRetangulo
] ifFalse: [
^self retangulo intersects: umPontoOuRetangulo
]!
149
exibeCom: aPen
"Private - Apresenta o receptor utilizando aPen."
figuraGeometrica ifNil: [
^self
].
figuraGeometrica displayWith: aPen.!
figuraGeometrica
^figuraGeometrica!
figuraGeometrica: aFiguraGeometrica
figuraGeometrica := aFiguraGeometrica!
menu
"Define o pop up menu para o ator"
|subMenu menu|
menu := super menu
150
appendSeparator;
appendItem: 'Cor de preenchimento' selector: #mudaCorDePreenchimento;
appendItem: 'Cor da borda' selector: #mudaCorDaBorda;
appendSeparator;
appendItem: 'Duplica' selector: #duplica;
yourself.
subMenu := Menu labelArray: #( '1' '2' '3' '4' '5' '10' '30' '90' ) lines: #() selectors: #( 1 2 3
4 5 10 30 90 ).
subMenu title: 'Rotaciona no sentido anti-horário';
selector: #rotacionaAntiHorario:;
owner: self.
menu appendSubMenu: subMenu.
subMenu := Menu labelArray: #( '1' '2' '3' '4' '5' '10' '30' '90' ) lines: #() selectors: #( 1 2 3
4 5 10 30 90 ).
subMenu title: 'Rotaciona no sentido horário';
selector: #rotacionaHorario:;
owner: self.
menu appendSubMenu: subMenu.
^menu!
mudaCorDaBorda
151
|novaCor|
novaCor := ListDialog openOn: Colors keys asSortedCollection
title: 'Selecione a cor da borda'.
novaCor ifNil: [^self].
self corBorda: (Colors at: novaCor).!
mudaCorDePreenchimento
|novaCor|
novaCor := ListDialog openOn: Colors keys asSortedCollection
title: 'Selecione a cor de preenchimento'.
novaCor ifNil: [^self].
self corPreenchimento: (Colors at: novaCor).!
posicao: aPoint
super posicao: aPoint.
self figuraGeometrica == nil ifFalse: [
self figuraGeometrica moveTo: aPoint
].!
retangulo
152
"Retorna um retângulo que indica a área
limítrofe do receptor no palco"
figuraGeometrica ifNil: [
^self posicao extent: 0@0
].
^figuraGeometrica rectangle origin truncated
corner: figuraGeometrica rectangle corner rounded!
rotaciona
|pos|
pos := figuraGeometrica position.
self rotaciona: 5 relativoA: pos.!
rotaciona: umAngulo relativoA: umPonto
figuraGeometrica ifNil: [
^self
].
figuraGeometrica rotate: umAngulo relatedTo: umPonto.
153
posicao := figuraGeometrica position.
self exibe.!
rotacionaAntiHorario: umAngulo
|pos|
pos := figuraGeometrica position.
self rotaciona: umAngulo negated relativoA: pos.!
rotacionaHorario: umAngulo
|pos|
pos := figuraGeometrica position.
self rotaciona: umAngulo relativoA: pos.!
sobrepoe: umAtor
"Verifica se o ator receptor se sobrepõe a umAtor, ou seja,
se eles ocupam um espaço em comum"
figuraGeometrica ifNil: [
^false
].
154
self == umAtor ifTrue: [
^true
].
(umAtor isKindOf: AtorFiguraGeometricaComSensores) ifFalse: [
^super sobrepoe: umAtor
].
^self figuraGeometrica intersects: umAtor figuraGeometrica!
tamanho
"Public - Retorna o tamanho do Ator"
self palco ifNil: [
^0@0
].
figuraGeometrica ifNil: [
^0@0
].
^figuraGeometrica extent! !
155
Classe AtorCirculoComSensores
AtorFiguraGeometricaComSensores subclass: #AtorCirculoComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!AtorCirculoComSensores class methods ! !
!AtorCirculoComSensores methods !
raio: umInteiro cor: umaCor
"Define o raio e a cor do círculo com sensores"
figuraGeometrica := Circulo new radius: umInteiro.
figuraGeometrica fillColor: umaCor;
moveTo: self posicao.
self exibe.! !
156
Classe BolaDeSinucaComSensores
AtorCirculoComSensores subclass: #BolaDeSinucaComSensores
instanceVariableNames:
'velocidade '
classVariableNames: ''
poolDictionaries: '' !
!BolaDeSinucaComSensores class methods ! !
!BolaDeSinucaComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self sempreQue: [ (self sensor: 'toque borda') ativado ] faca: [
(self sensor: 'toque borda') disparaReflexao
].
self sempreFaca: [
157
self anda: velocidade.
].
self cada: 500 faca: [
self gira: (self aleatorio: 10).
].
self sempreQue: [(self sensor: 'toque bola') ativado] faca: [
self redirecionaBolas
].
" self sempreFaca: [
self verificarToque.
]."
" self verificarSempre: (self sensor2: 'toque bola')."
"self verificarSempre: (self sensorDeBola). ""Faz o sensor estar ativo sempre"
"Outra opção para a mesma execução"
" self seSensorAtivado: (self sensor2: 'toque bola') faca: #redirecionaBolas."!
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
158
(SensorDeToque new: self)
nome: 'toque bola';
detectaAtorDoTipo: BolaDeSinucaComSensores).
self adicionaSensor: (
(SensorDeBorda new: self)
nome: 'toque borda').!
initialize
"Inicializa o ator, fazendo com que ele adicione um Sensor de Toque"
super initialize.
velocidade := 2.!
redirecionaBolas
"Ação realizada com as bolas que detectaram o toque"
self gira: 178 + (self aleatorio: 4).!
velocidade: umNumero
"Ação para definir a velocidade da bola"
velocidade := umNumero.! !
159
Classe AtorInvasoresDoEspacoComSensores
AtorComSensores subclass: #AtorInvasoresDoEspacoComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!AtorInvasoresDoEspacoComSensores class methods ! !
!AtorInvasoresDoEspacoComSensores methods ! !
160
Classe BalaComSensores
AtorInvasoresDoEspacoComSensores subclass: #BalaComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!BalaComSensores class methods ! !
!BalaComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self sempreFaca: [self anda: 10].
self sempreQue: [(self sensor: 'toque nave') ativado] faca: [
self tornase: BalaExplodida new
].
161
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self saiDoPalco
].
"Possibilidade 1"
" self verificarSempre: (self sensorDeNave)." "Ativa o sensor"
"Possibilidade 2"
" self seSensorAtivado: self sensorDeNave faca: #mudaBala."
"Possibilidade 3"
" self sempreFaca: [
(self sensor: SensorDeToque) executa.
]."!
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque nave';
detectaAtorDoTipo: NaveComSensores).
self adicionaSensor: (
(SensorDeArea new: self)
162
nome: 'area visivel').!
initialize
"Inicializa o ator, fazendo com que ele adicione um Sensor de Toque"
super initialize.
self adicionaFigura: 'times'.! !
163
Classe CanhaoComSensores
AtorInvasoresDoEspacoComSensores subclass: #CanhaoComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!CanhaoComSensores class methods ! !
!CanhaoComSensores methods !
dispara
"Dispara bala"
|bala|
bala := BalaComSensores new.
bala entraNoPalco: self palco ;
pulaPara: self posicao - (0@30);
apontaPara: 90.!
initialize
164
"Private - Initialize the receiver."
|sensorDeToque|
super initialize.
self adicionaFigura: 'crayons'.! !
165
Classe LancadorDeNavesComSensores
AtorInvasoresDoEspacoComSensores subclass: #LancadorDeNavesComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!LancadorDeNavesComSensores class methods ! !
!LancadorDeNavesComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self comProbabilidadeDe: 0.01 faca: [self lancaNave].!
initialize
"Private - Initialize the receiver."
166
|sensorDeToque|
super initialize.
self adicionaFigura: 'disc'.!
lancaNave
"Insere uma nova naveComSensores no palco."
|naveComSensores|
naveComSensores := NaveComSensores new.
naveComSensores entraNoPalco: self palco ;
pulaPara: self posicao;
apontaPara: 0.! !
167
Classe NaveComSensores
AtorInvasoresDoEspacoComSensores subclass: #NaveComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!NaveComSensores class methods ! !
!NaveComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self sempreFaca: [self anda: 2].
self sempreQue: [(self sensor: 'toque nave') ativado] faca: [
self saiDoPalco
].
168
self sempreQue: [(self sensor: 'toque bala') ativado] faca: [
self foiDanificada
].
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self saiDoPalco
].!
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque bala';
detectaAtorDoTipo: BalaExplodida).
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque nave';
detectaAtorDoTipo: NaveComSensores).
self adicionaSensor: (
(SensorDeArea new: self)
nome: 'area visivel').!
169
foiDanificada
"A nave foi atingida por algum objeto"
self apontaPara: 280;
anda: 5;
apontaPara: 325!
initialize
"Inicializa o ator, fazendo com que ele adicione um Sensor de Toque"
super initialize.
self adicionaFigura: 'disc'.! !
170
Classe AtorMeioAmbienteComSensores
AtorComSensores subclass: #AtorMeioAmbienteComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!AtorMeioAmbienteComSensores class methods ! !
!AtorMeioAmbienteComSensores methods ! !
171
Classe GramaComSensores
AtorMeioAmbienteComSensores subclass: #GramaComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!GramaComSensores class methods ! !
!GramaComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
|grama|
self comProbabilidadeDe: 1/300 faca: [ self seReproduz ].
self em: 750 faca: [ self saiDoPalco ].
172
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self saiDoPalco
].!
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
(SensorDeArea new: self)
nome: 'area visivel').!
initialize
"Private - Initialize the receiver."
super initialize.
self adicionaFigura: 'Grama'.!
menu
"Define o pop up menu para o ator"
^super menu
173
appendSeparator;
appendItem: 'Duplica' selector: #seReproduz;
yourself.!
seReproduz
"Ação para a grama se reproduzir"
|grama|
grama := GramaComSensores new.
grama entraNoPalco: self palco ;
pulaPara: self posicao;
apontaPara: (self aleatorio: 360);
anda: self tamanho x.! !
174
Classe PredadorComSensores
AtorMeioAmbienteComSensores subclass: #PredadorComSensores
instanceVariableNames:
'nivelDeAlimentacao '
classVariableNames: ''
poolDictionaries: '' !
!PredadorComSensores class methods ! !
!PredadorComSensores methods !
andaAEsmo
"Anda pelo palco aleatoriamente"
((self sensor: 'area visivel') ativado not) ifTrue: [self apontaPara: self palco centro].
self gira: (self aleatorio: 20) - 10;
anda: 6+(self aleatorio: 2).!
cacaComSensores
175
"O predador que esta com fome, vai à caça"
(self sensor: 'visão presa') ativado ifTrue: [
(self sensor: 'toque presa') ativado ifTrue: [
self cacou: (self sensor: 'toque presa') atorDetectado
] ifFalse: [
(self sensor: 'visão presa') atorMaisProximo notNil ifTrue: [
self apontaPara: (self sensor: 'visão presa') atorMaisProximo;
anda: 15.1.
]
]
] ifFalse: [
self andaAEsmo.
].!
cacou: umaPresa
"umaPresa foi caçada. Ela desaparece e é aumentado
o nível de alimentação do predador"
umaPresa saiDoPalco.
umaPresa class == PresaJovem ifTrue: [
nivelDeAlimentacao := nivelDeAlimentacao + 300
176
] ifFalse: [
nivelDeAlimentacao := nivelDeAlimentacao + 500
]!
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self sempreQue: [nivelDeAlimentacao = 0] faca: [ self saiDoPalco ].
self sempreQue: [ nivelDeAlimentacao < 700 ]
faca: [ self cacaComSensores ].
self sempreFaca: [
nivelDeAlimentacao := nivelDeAlimentacao - 1.
].
self em: 3000 faca: [ self saiDoPalco ].
self cada: 1050 faca: [ self seReproduz ].!
defineSensores
"Ação para configurar as características dos sensores"
177
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'visão presa';
detectaAtorDoTipo: PresaComSensores;
alcance: 100).
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque presa';
detectaAtorDoTipo: PresaComSensores).
self adicionaSensor: (
(SensorDeArea new: self)
nome: 'area visivel').!
initialize
"Private - Initialize the receiver."
|sensorDeProximidade|
super initialize.
self adicionaFigura: 'plus';
apontaPara: (self aleatorio: 360).
178
nivelDeAlimentacao := 700.!
menu
"Define o pop up menu para o ator"
^super menu
appendSeparator;
appendItem: 'Duplica' selector: #seReproduz;
yourself.!
nivelDeAlimentacao
"Retorna o nível de alimentação do predador"
^nivelDeAlimentacao!
presaMaisProxima
"Retorna a presa que está mais próxima."
^(self sensor: 'visão presa') atorMaisProximo.!
seReproduz
179
"Só se reproduz se estiver bem alimentado"
|jovem|
nivelDeAlimentacao > 400 ifTrue: [
jovem := PredadorComSensores new.
jovem entraNoPalco: self palco ;
pulaPara: self posicao.
].! !
180
Classe PresaComSensores
AtorMeioAmbienteComSensores subclass: #PresaComSensores
instanceVariableNames:
'nivelDeAlimentacao '
classVariableNames: ''
poolDictionaries: '' !
!PresaComSensores class methods ! !
!PresaComSensores methods !
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'visão predador';
detectaAtorDoTipo: PredadorComSensores;
alcance: 110).
181
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'visão grama';
detectaAtorDoTipo: GramaComSensores).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'toque grama';
detectaAtorDoTipo: GramaComSensores;
alcance: 10).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'presa adulta';
detectaAtorDoTipo: PresaAdultaComSensores).
self adicionaSensor: (
(SensorDeProximidade new: self)
nome: 'presa velha';
detectaAtorDoTipo: PresaVelhaComSensores).
self adicionaSensor: (
(SensorDeArea new: self)
nome: 'area visivel').!
182
menu
"Define o pop up menu para o ator"
^super menu
appendSeparator;
appendItem: 'Duplica' selector: #seReproduz;
yourself!
nivelDeAlimentacao
"Retorna o nível de alimentação do predador"
^nivelDeAlimentacao!
procuraComida
"A presa está com fome e sai procurando comida"
|gramaProxima|
(gramaProxima := (self sensor: 'visão grama') atorMaisProximo) isNil ifTrue: [
^self gira: (self aleatorio: 10) - 5;
anda: 8
].
183
(self sensor: 'toque grama') ativado ifTrue: [
(self sensor: 'toque grama') atorDetectado saiDoPalco.
nivelDeAlimentacao := nivelDeAlimentacao + 200
] ifFalse: [
self apontaPara: gramaProxima;
anda: 7 + (self aleatorio: 4).
].!
seReproduz
"Só se reproduz se estiver bem alimentado"
|outro|
nivelDeAlimentacao > 100 ifTrue: [
outro := self species new.
outro entraNoPalco: self palco ;
pulaPara: self posicao.
].! !
184
Classe PresaAdultaComSensores
PresaComSensores subclass: #PresaAdultaComSensores
instanceVariableNames:
'predador '
classVariableNames: ''
poolDictionaries: '' !
!PresaAdultaComSensores class methods ! !
!PresaAdultaComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self sempreQue: [nivelDeAlimentacao = 0] faca: [ self saiDoPalco].
self sempreFaca: [
nivelDeAlimentacao := nivelDeAlimentacao - 1.
].
185
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self apontaPara: self palco centro.
].
self sempreFaca: [
predador := (self sensor: 'visão predador') atorMaisProximo.
predador isNil ifTrue: [
nivelDeAlimentacao > 300 ifTrue: [
self gira: (self aleatorio: 10) - 5;
anda: 5.
] ifFalse: [
self procuraComida.
]
] ifFalse: [
self apontaPara: predador;
gira: 180 + (self aleatorio: 50) - 25;
anda: 15.
].
].
self em: 1550 faca: [ self tornase: PresaVelhaComSensores new].
self cada: 350 faca: [
self seReproduz.
186
].!
initialize
"Private - Initialize the receiver."
super initialize.
nivelDeAlimentacao := 500.
self adicionaFigura: 'radioButtonOn' ;
apontaPara: (self aleatorio: 360).!
seReproduz
"Só se reproduz se estiver bem alimentado"
|jovem|
nivelDeAlimentacao > 150 ifTrue: [
jovem := PresaJovemComSensores new.
jovem entraNoPalco: self palco ;
pulaPara: self posicao + (10@10).
].! !
187
Classe PresaJovemComSensores
PresaComSensores subclass: #PresaJovemComSensores
instanceVariableNames:
'mae '
classVariableNames: ''
poolDictionaries: '' !
!PresaJovemComSensores class methods ! !
!PresaJovemComSensores methods !
adultoMaisProximo
"Retorna a presa adulta ou velha que está mais próxima."
|adultoMaisProximo velhaMaisProxima|
adultoMaisProximo := (self sensor: 'presa adulta') atorMaisProximo.
velhaMaisProxima := (self sensor: 'presa velha') atorMaisProximo.
188
velhaMaisProxima isNil ifFalse:[
(self distanciaPara: velhaMaisProxima) < (self distanciaPara: adultoMaisProximo)
ifTrue: [
adultoMaisProximo := velhaMaisProxima
]
].
^adultoMaisProximo.!
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
| distancia|
self sempreQue: [mae isNil or: [mae palco isNil]] faca: [
mae := self adultoMaisProximo].
self sempreFaca: [
mae isNil ifTrue: [
self gira: (self aleatorio: 90) - 45;
anda: 5.
] ifFalse: [
(distancia := self distanciaPara: mae) > 15 ifTrue: [
189
self apontaPara: mae;
anda: (distancia - 15 min: 13)
].
].
].
self em: 1000 faca: [ self tornase: PresaAdultaComSensores new].!
initialize
"Private - Initialize the receiver."
super initialize.
self adicionaFigura: 'checkBox'.! !
190
Classe PresaMortaComSensores
PresaComSensores subclass: #PresaMortaComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!PresaMortaComSensores class methods ! !
!PresaMortaComSensores methods !
initialize
"Private - Initialize the receiver."
super initialize.
self adicionaFigura: 'radioButton'.! !
191
Classe PresaVelhaComSensores
PresaComSensores subclass: #PresaVelhaComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!PresaVelhaComSensores class methods ! !
!PresaVelhaComSensores methods !
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
|predador distancia|
self sempreQue: [nivelDeAlimentacao = 0] faca: [ self saiDoPalco].
self sempreFaca: [
nivelDeAlimentacao := nivelDeAlimentacao - 1.
192
].
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self apontaPara: self palco centro.
].
self sempreFaca: [
((predador := (self sensor: 'visão predador') atorMaisProximo) isNil or: [
(distancia := self distanciaPara: predador) > 105]) ifTrue: [
nivelDeAlimentacao > 300 ifTrue: [
self gira: (self aleatorio: 10) - 5;
anda: 5.
] ifFalse: [
self procuraComida
]
] ifFalse: [
self apontaPara: predador;
gira: 180 + (self aleatorio: 30) - 15;
anda: 10 + (self aleatorio: 2).
].
].
self em: 1000 faca: [self tornase: PresaMortaComSensores new].!
initialize
193
"Private - Initialize the receiver."
super initialize.
nivelDeAlimentacao := 300.
self adicionaFigura: 'radioButton'.! !
194
Classe AtorSistemaBancarioComSensores
AtorComSensores subclass: #AtorSistemaBancarioComSensores
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: '' !
!AtorSistemaBancarioComSensores class methods ! !
!AtorSistemaBancarioComSensores methods ! !
195
Classe PessoaComSensores
AtorSistemaBancarioComSensores subclass: #PessoaComSensores
instanceVariableNames:
'nome endereco dataDeNascimento numeroDaConta granaNoBolso estavaNaLoja
estavaNoBanco '
classVariableNames: ''
poolDictionaries: '' !
!PessoaComSensores class methods ! !
!PessoaComSensores methods !
ajusteCondicao
"Ajusta a condição da pessoa, se ela estava na loja ou no banco."
( estavaNoBanco and: [self saiuDoBanco] ) ifTrue: [
estavaNoBanco := false
].
( estavaNoBanco not and: [self entrouNoBanco] ) ifTrue: [
196
estavaNoBanco := true
].
( estavaNaLoja and: [self saiuDaLoja] ) ifTrue: [
estavaNaLoja := false
].
( estavaNaLoja not and: [self entrouNaLoja] ) ifTrue: [
estavaNaLoja := true
].!
definePapel
"Define o schedule do ator, ou seja, as ações
que ele executa e quando"
self sempreQue: [(self sensor: 'area visivel') ativado not] faca: [
self apontaPara: self palco centro.
].
self sempreQue: [self granaNoBolso > 10] faca: [
self gira: (self aleatorio: 20) - 10;
anda: 4.
].
197
self sempreQue: [self granaNoBolso <= 10] faca: [
self apontaPara: (self palco agenciaBancaria);
anda: 4.5.
].
self sempreQue: [self entrouNoBanco & (self granaNoBolso <= 10) ] faca: [
self numeroDaConta isNil ifTrue: [
numeroDaConta := self palco agenciaBancaria abreContaPara: self.
].
self palco agenciaBancaria saque: 50 daConta: self numeroDaConta.
granaNoBolso := granaNoBolso + 50.
].
self sempreQue: [self entrouNaLoja & (self granaNoBolso >= 9) ] faca: [
granaNoBolso := granaNoBolso - (self aleatorio: 10).
].
self sempreFaca: [self ajusteCondicao].!
defineSensores
"Ação para configurar as características dos sensores"
self adicionaSensor: (
(SensorDeArea new: self)
198
nome: 'area visivel').
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque loja';
detectaAtorDoTipo: Loja).
self adicionaSensor: (
(SensorDeToque new: self)
nome: 'toque banco'";
detectaAtorDoTipo: AgenciaBancaria").!
entrouNaLoja
"Retorna true caso a pessoa esteja entrando na loja"
^estavaNaLoja not and: [self estaNaLoja].!
entrouNoBanco
"Retorna true caso a pessoa esteja entrando no banco"
^estavaNoBanco not and: [self estaNoBanco].!
estaNaLoja
199
"Retorna true caso a pessoa esteja sob uma loja"
^(self sensor: 'toque loja') ativado.!
estaNoBanco
"Retorna true caso a pessoa esteja sob um agencia Bancaria"
^(self sensor: 'toque banco') ativado.!
granaNoBolso
"Retorna o valor de granaNoBolso dessa Pessoa"
^granaNoBolso!
initialize
"Private - Initialize the receiver."
super initialize.
granaNoBolso := 0.
estavaNaLoja := false.
estavaNoBanco := false.
self adicionaFigura: 'monaLisa'.!
200
nome
"Retorna o nome da pessoa"
^nome.!
nome: umString
"Define o nome da pessoa"
nome := umString.!
numeroDaConta
"Retorna o número da conta da pessoa"
^numeroDaConta!
saiuDaLoja
"Retorna true caso a pessoa esteja saindo da loja"
^estavaNaLoja and: [self estaNaLoja not].!
saiuDoBanco
"Retorna true caso a pessoa esteja saindo do banco"
^estavaNoBanco and: [self estaNoBanco not].! !