Entity
In questa sezione, viene descritta la struttura e le funzionalità delle entità nel sistema di simulazione.
Entità

Il trait Entity modella un oggetto bidimensionale con:
id: UUID: identificativo univoco dell'entità;position: Point2D: posizione cartesiana;shape: ShapeType: forma geometrica;orientation: Orientation: direzione espressa in gradi.
Costituisce l’interfaccia base comune per oggetti statici e dinamici.
Posizione
Point2D rappresenta un punto nel piano cartesiano (x: Double e y: Double) e fornisce primitive geometriche, quali:
- somma/sottrazione vettoriale, moltiplicazione per scalare;
- prodotto scalare, modulo, normalizzazione;
- distanza euclidea.
Nota: queste operazioni sono la base per spostamenti, direzioni e collisioni.
Forma
ShapeType è un'enum con due varianti:
Circle(radius: Double): cerchio di raggioradius;Rectangle(width: Double, height: Double): rettangolo con larghezza e altezza.
Nota: questo approccio consente una modellazione semplice ma estensibile delle dimensioni fisiche degli oggetti nello spazio simulato.
Orientamento
Orientation rappresenta l’angolo di rotazione rispetto a un riferimento fisso:
degrees: Double: gradi;toRadians: Double: conversione in radianti per la trigonometria.
Nota: l’orientamento permette di rappresentare la direzione verso cui è rivolto un oggetto nello spazio, supportando il movimento direzionale e la rotazione.
Entità statiche e dinamiche

StaticEntity e DynamicEntity estendono Entity separando così le responsabilità.
DynamicEntity
DynamicEntity rappresenta un’entità che percepisce e agisce nel ciclo sense → plan → act:
sensors: Vector[Sensor[? <: DynamicEntity, ? <: Environment, ?]];actuators: Seq[Actuator[? <: DynamicEntity]];behavior: Policy.
I sensori raccolgono dati dall’ambiente; il behavior elabora le letture in base alla policy e seleziona un’azione; gli attuatori applicano l’azione all’entità. Questa struttura consente di modellare agenti robotici con ciclo sense–plan–act.
Progettazione del motore decisionale (Behavior) - regole, comportamenti, policy e DSL - nella pagina di design Behavior.
StaticEntity
StaticEntity modella entità non mobili che possono interagire passivamente con l'ambiente. Possono essere:
Obstacle/Boundary: rettangoli (orientabili) che occupano spazio e collidono;Light: cerchi che emettono illuminazione (isotropica).
Nota: i boundary sono creati automaticamente durante la validazione dell’ambiente: sono rettangoli sottili posti sui bordi. Partecipano a collisioni e alla resistenza luminosa, e sono percepibili dai sensori di prossimità.
Ostacoli
Gli ostacoli (StaticEntity.Obstacle) sono “muri” rettangolari che bloccano il movimento e la luce, creando
corridoi, stanze e scenari di navigazione.
Attributi principali:
id: UUID: identificativo univoco dell'entità;position: Point2D: posizione del centro dell’ostacolo;orientation: Orientation: angolo in gradi;width: Double,height: Double: dimensioni;shape: Rectangle(width, height): forma rettangolare.
La validazione include:
- Dimensioni > 0;
- Inclusione nei limiti dell’ambiente;
- Assenza di sovrapposizioni con altre entità;
Nota: servono a costruire scenari realistici - dal corridoio stretto al piccolo labirinto - in cui i robot devono pianificare il movimento ed evitare collisioni.
Luce
Le luci (StaticEntity.Light) sono sorgenti radiali che forniscono un campo percettivo per i
LightSensor e rendono osservabile lo stato luminoso (Environment.lightField).
Attributi:
id: UUID: identificativo univoco dell’entità;position: Point2D: posizione del centro della luce;orientation: Orientation: presente per uniformità di modello; impostato aOrientation(0.0); l’emissione è isotropica (non direzionale);radius: Double: raggio geometrico usato per lashape(ShapeType.Circle(radius));illuminationRadius: Double: portata luminosa efficace (raggio del contributo nel campo luce);intensity: Double,attenuation: Double: livello e decadimento con la distanza;shape: Circle(radius): forma circolare.
La validazione include:
- parametri strettamente > 0;
- inclusione nei limiti dell’ambiente;
- assenza di sovrapposizioni con altre entità.
Nota: servono a creare zone buie/illuminate utili per testare policy di navigazione e priorità tra comportamenti.
Boundary
I boundary (StaticEntity.Boundary) definiscono i confini dell’ambiente. Sono creati automaticamente in
validazione, in modo tale che l'utente non debba preoccuparsi di definirli esplicitamente. Simili agli ostacoli,
ma con la differenza che hanno larghezza o altezza pari a zero.
La creazione viene effettuata tramite la factory method nel companion object StaticEntity.Boundary.
Attributi principali:
id: UUID: identificativo univoco dell’entità;position: Point2D: centro del lato;orientation: Orientation: in factory impostato aOrientation(0.0);shape: Rectangle(width, height)con uno dei due lati pari a zero.
La validazione include:
- presenza su tutti i lati dell’ambiente;
- dimensioni coerenti con i bordi (spessore zero consentito per i boundary);
- nessuna sovrapposizione anomala con entità interne.
Nota: gli eventuali boundary definiti nel file YAML vengono ignorati: in validazione vengono sempre ricreati i 4 canonici. Questi elementi sono fondamentali per definire i limiti entro cui le entità possono muoversi e interagire.
Robot

La case class Robot estende DynamicEntity e rappresenta un’entità autonoma in grado di muoversi e interagire con
l’ambiente circostante nello spazio bidimensionale. Ogni robot è caratterizzato da un identificativo univoco (UUID),
una posizione e un’orientazione nello spazio, nonché da una forma geometrica circolare (ShapeType.Circle).
Il robot è dotato di un insieme di attuatori (Seq[Actuator[Robot]]) e di una collezione di sensori
(Vector[Sensor[Robot, Environment]]), che gli permettono di percepire e raccogliere informazioni sull’ambiente.
Inoltre, possiede una strategia comportamentale (Policy) che definisce la logica decisionale del
robot in base ai dati forniti dai sensori.
Vedere la sezione Action per i dettagli sull’algebra delle azioni e il pattern Tagless Final.
Attuatori

Un attuatore è un componente in grado di modificare lo stato di un’entità dinamica (DynamicEntity). Il trait Actuator[E]
definisce l’interfaccia generica, tramite il metodo act(dt, entity), che aggiorna l’entità dopo un intervallo temporale
dt (delta time), restituendone una nuova istanza in un contesto monadico F[_].
Attuatori di movimento
Gli attuatori di movimento sono modellati tramite i motori differenziali.
DifferentialWheelMotor estende Actuator[Robot] ed è costituito da due
ruote (Wheel) – sinistra e destra – dotate di velocità lineare (speed) e una forma circolare (ShapeType.Circle).
Il movimento del robot viene calcolato con un modello cinematico differenziale (DifferentialKinematics).
- Velocità lineare (media delle velocità delle due ruote; ottenute moltiplicando la velocità (
speed) per il raggio della ruota (radius)):
- Velocità angolare (proporzionale alla differenza tra le velocità delle ruote divisa per la distanza tra le ruote; si assume che la distanza tra le ruote sia pari al diametro del robot):
- Nuova posizione e orientazione del robot integrando le equazioni del moto su un intervallo di tempo
dt:
Questa logica, incapsulata nel metodo act, consente di aggiornare lo stato del robot in modo funzionale e validato,
rendendo il comportamento dell’attuatore modulare ed estendibile.
Per ulteriori dettagli sull’implementazione degli attuatori, vedere la sezione Attuatori.
Sensori

I sensori sono componenti che permettono a un'entità dinamica di percepire l'ambiente circostante. Il trait
Sensor[Entity, Environment] definisce un'interfaccia generica per i sensori.
I sensori sono parametrizzati su tre tipi:
Entity: il tipo di entità che il sensore può percepire, sottotipo diDynamicEntity(ad esempio,Robot).Environment: il tipo di ambiente in cui il sensore opera, sottotipo diEnvironment(ad esempio,Environmentstesso).Data: il tipo di dato restituito dal sensore.
Inoltre i sensori contengono un campo offset che rappresenta la posizione del sensore rispetto all'entità che lo
possiede.
Infine, un metodo sense[F[_]](entity: Entity, env: Environment): F[Data] che permette di ottenere i dati di rilevamento
dal sensore.
Il tipo F[_] è un tipo di effetto generico (come IO, Id, Task, etc.) che permette:
- astrazione rispetto al tipo di effetto utilizzato per l'esecuzione;
- composizione funzionale con altre operazioni monadiche;
- testabilità tramite interpreti fittizi o mock.
Il tipo SensorReading è un tipo di utilità che aiuta a rappresentare i dati letti da un sensore.
Si tratta di un case class che contiene:
sensor: Sensor[?, ?]: il sensore che ha effettuato la lettura;value: A: il valore letto dal sensore, parametrizzato su un tipoA.
Questo tipo consente di incapsulare le letture dei sensori in un formato coerente, facilitando la gestione e l'elaborazione dei dati raccolti.
SensorReadings è un tipo di utilità che rappresenta una raccolta di letture dei sensori.
I dettagli implementativi riguardanti i sensori sono disponibili nella sezione Implementazione dei sensori.
Sensori di prossimità
La case class ProximitySensor estende Sensor[Robot, Environment] e rappresenta un sensore di prossimità che rileva
la presenza di altre entità nell'ambiente.
Questo sensore dispone di un campo range che rappresenta il raggio di azione del sensore.
I valori ritornati da questo sensore sono di tipo Double, e rappresentano la distanza alla quale si trova l'entità più
vicina (normalizzata tra 0 e 1):
- 0 indica che l'entità è molto vicina;
- 1 indica che è molto lontana.
Il metodo
senseimplementa la logica di rilevamento, tramite ray casting, che calcola la distanza tra il sensore e le entità nell'ambiente, restituendo il valore normalizzato.
Sensori di luce
La case class LightSensor estende Sensor[Robot, Environment] e rappresenta un sensore di luce, in grado di
rilevare l'intensità luminosa in una determinata area.
I valori restituiti dal sensore sono Double, e rappresentano l'intensità luminosa normalizzata
tra 0 e 1, dove:
- 0 indica assenza di luce;
- 1 indica luce massima.
La distribuzione della luce nell'ambiente è rappresentata da un campo
lightFieldall'interno diEnvironment. Il metodosenseimplementa la logica di rilevamento, utilizzando illightFieldper ottenere i dati di intensità luminosa.