IMPLEMENTAÇÃO DE SENSORES NO MUNDO DOS ATORES · objetos, fazendo parte do sistema. ......

201
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

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.

68

4.2 TRABALHOS FUTUROS

4.2.1 Utilização Prática - Validaçã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].! !