Skip to content
Snippets Groups Projects
Commit eebdd9f1 authored by nollet's avatar nollet
Browse files

update 14/06/2022

parent 6ecb5179
Branches
No related tags found
No related merge requests found
Showing
with 245 additions and 109 deletions
# Documentation Technique : Flocking Simulator
[**↩️ Retour à l'accueil**](../../README.md)
## Sommaire
## Rajouter un Comportement
## Classes
\ No newline at end of file
File added
File added
......@@ -55,11 +55,12 @@ public class Agent : MonoBehaviour, Visible
{
system = GameObject.Find("SMA").GetComponent<SMA>();
//List<Comportement> comps = new List<Comportement> { new TangenteBord1(this), new Constant(this)};
//List<Comportement> comps = new List<Comportement> { new Bord(this), new Constant(this),new Reynolds(this), new Aleatoire(this)};
//List<int> imps = new List<int> { 6,6,4,1 };
List<Comportement> comps = new List<Comportement> { new TangenteBord2(this), new Constant(this)};
List<int> imps = new List<int> { 1,1 };
List<Comportement> comps = new List<Comportement> {
new TangenteBord2(this),new Reynolds(this), new Aleatoire(this)
};
List<int> imps = new List<int> {
10,10,1
};
Comportement c = new CompositeSum(this,comps,imps);
if(system._3D) comportement = c;
......
......@@ -31,10 +31,16 @@ public class TangenteBord1 : Bord
// retourne le vecteur en réponse à l'observation
protected virtual Vector3 answerTan(Observation o) {
Obstacle ob = (Obstacle) o.objet;
(Vector3,Vector3) tan = ob.getTangentes(proprietaire);
if(Vector3.Angle(proprietaire.deplacement,tan.Item1) > Vector3.Angle(proprietaire.deplacement,tan.Item2))
return tan.Item1;
else return tan.Item2;
List<Vector3> tan = ob.getTangentes(proprietaire);
if(tan.Count == 0) return Vector3.zero;
else {
Vector3 res = tan[0];
for(int i = 1; i<tan.Count;i++)
if(Vector3.Angle(proprietaire.deplacement,tan[i]) < Vector3.Angle(proprietaire.deplacement,res))
res = tan[i];
return res;
}
}
}
......@@ -12,7 +12,7 @@ public class Reynolds : Comportement
// constante de distance de séparation
static public float Escape = 10.0f;
// poids de la séparation
static public float EscapeWeight = 3.0f;
static public float EscapeWeight = 1.0f;
// constante de distance de l'alignement
static public float Together = 20.0f;
// poids de l'alignement
......@@ -20,7 +20,7 @@ public class Reynolds : Comportement
// constante de distance de cohésion
static public float Follow = 25.0f;
// poids de la cohésion
static public float FollowWeight = 2.0f;
static public float FollowWeight = 1.0f;
// Méthodes
......@@ -31,6 +31,7 @@ public class Reynolds : Comportement
public override Vector3 reagir(List<Observation> observation) {
List<Vector3> vectorsFuir = new List<Vector3>();
List<Vector3> vectorsSuivre = new List<Vector3>();
vectorsSuivre.Add(proprietaire.deplacement);
List<Vector3> vectorsRapprocher = new List<Vector3>();
foreach(Observation o in observation) {
if (o.objet.isAlive()) {
......
......@@ -14,8 +14,8 @@ public class Environnement : MonoBehaviour
public GameObject cube;
// Visuel environnement en carré
public GameObject carre;
// Visuel test
public GameObject test;
// Visuel possible pour les obstacles
public GameObject figure;
// système utilisant l'environnement
private SMA system;
......@@ -24,7 +24,7 @@ public class Environnement : MonoBehaviour
// topologie de l'environnement
private Topologie topologie;
// liste des obstacles dans l'environnement
private List<Obstacle> obstacles = new List<Obstacle>();
private List<CustomObstacle> obstacles;
// Méthodes
......@@ -48,43 +48,106 @@ public class Environnement : MonoBehaviour
public void notify() {
if(_3D != system._3D) {
_3D = system._3D;
if(_3D) topologie = new Cube(cube);
else topologie = new Carre(carre);
setTheTopologie();
if(_3D) setTheTopologie(new Cube(this,cube));
else setTheTopologie(new Carre(this,carre));
createObstacles();
}
}
// Initialise l'environnement avec seulement son contour
private void setTheTopologie() {
foreach (Transform child in transform) Destroy(child.gameObject);
Instantiate(topologie.getGameObject(), Vector3.zero, Quaternion.identity,transform);
createObject(topologie.getGameObject(), Vector3.zero);
}
// Initialise l'environnement avec seulement son contour entré en paramètre
private void setTheTopologie(Topologie topo) {
foreach (Transform child in transform) Destroy(child.gameObject);
topologie = topo;
createObject(topologie.getGameObject(), Vector3.zero);
}
// renvoie le voisinage de l'agent current dans cet environnement selon un rayon et un angle de vue
public List<Observation> getVoisinage(Agent current, float rayon, float angle) {
List<Observation> res = detectAgents(current,rayon,angle);
res = detectObstacles(current,res,rayon);
return detectBord(current,res,rayon,angle);
}
private List<Observation> detectAgents(Agent current, float rayon, float angle) {
Vector3 dist; float l; float a;
List<Observation> res = new List<Observation>();
List<Agent> agents = system.getAgents();
RaycastHit[] hits;Ray ray;
Vector3 pos = current.transform.position;
bool notSeen;
for(int i = 0; i<agents.Count;i++) {
dist = agents[i].transform.position - current.transform.position;
dist = agents[i].transform.position - pos;
ray = new Ray(pos,dist);
l = Utils.normVector(dist);
a = Vector3.Angle(current.deplacement,dist);
if (agents[i] != current && l <= rayon && a <= angle/2.0f) res.Add(new Observation(agents[i],dist));
notSeen = false;
if (agents[i] != current && l <= rayon && a <= angle/2.0f) {
hits = Physics.RaycastAll(ray, rayon);
for(int j = 0; j<hits.Length;j++)
if(hits[j].transform.GetComponent<Agent>() == null)
if(hits[j].distance < l) notSeen = true;
if(!notSeen)res.Add(new Observation(agents[i],dist));
}
}
return res;
}
private List<Observation> detectObstacles(Agent current, List<Observation> res,float rayon) {
Vector3 pos = current.transform.position;
bool notSeen = true;
int k = 0;
Ray ray = new Ray(pos,current.deplacement);
RaycastHit[] hits = Physics.RaycastAll(ray, rayon);
List<Vector3> tangentes = new List<Vector3> {
Quaternion.Euler(-90, 0, 0) * current.deplacement, Quaternion.Euler(90, 0, 0) * current.deplacement,
Quaternion.Euler(0, -90, 0) * current.deplacement, Quaternion.Euler(0, 90, 0) * current.deplacement,
Quaternion.Euler(0, 0, -90) * current.deplacement, Quaternion.Euler(0, 0, 90) * current.deplacement
};
while(k < hits.Length && notSeen) {
if(hits[k].transform.GetComponent<Agent>() == null) {
res.Add(new Observation(new PointObstacle(this,hits[k].point,tangentes),hits[k].point-pos));
notSeen = false;
}
k++;
}
return res;
}
private List<Observation> detectBord(Agent current, List<Observation> res, float rayon, float angle) {
float l, a;
Observation bord = topologie.detectEnv(current);
l = Utils.normVector(bord.distance); a = Vector3.Angle(current.deplacement,bord.distance);
if(l <= rayon && a <= angle/2.0f) {
res.Add(bord);
}
if(l <= rayon && a <= angle/2.0f) res.Add(bord);
return res;
}
// permet de créer un objet dans l'environnement
public void createObject(GameObject obj, Vector3 pos) {
Instantiate(obj,pos,Quaternion.identity,transform);
}
// Start est appelé avant la première image affichée
void Start()
{
system = GameObject.Find("SMA").GetComponent<SMA>();
_3D = !system._3D;
obstacles = new List<CustomObstacle> {
new CustomObstacle(this,new Vector3(-20.0f,-20.0f,0.0f),figure), new CustomObstacle(this,new Vector3(20.0f,-20.0f,0.0f),figure),
//new CustomObstacle(this,new Vector3(-20.0f,20.0f,0.0f),figure), new CustomObstacle(this,new Vector3(20.0f,20.0f,0.0f),figure)
};
notify();
}
private void createObstacles() {
for(int i = 0; i<obstacles.Count;i++) obstacles[i].createObject();
}
}
// Vector3
using UnityEngine;
//List
using System.Collections.Generic;
// Classe pour les obstacles qui sont des points d'impacts
public class CustomObstacle : Obstacle
{
// Attributs
// l'esthetique de l'obstacle
public GameObject figure;
// Méthodes
// point d'obstacle construit par rapport à sa position
public CustomObstacle(Environnement e, Vector3 p,GameObject g) : base(e,p) {figure = g;}
// créer l'objet 3D relatif à cet obstacle
public override void createObject() {
env.createObject(figure, position);
}
// retourne les deux tangentes au point d'impact entre l'agent et l'obstacle
public override List<Vector3> getTangentes(Agent a) {
return new List<Vector3> {
Quaternion.Euler(-90, 0, 0) * a.deplacement, Quaternion.Euler(90, 0, 0) * a.deplacement,
Quaternion.Euler(0, -90, 0) * a.deplacement, Quaternion.Euler(0, 90, 0) * a.deplacement,
Quaternion.Euler(0, 0, -90) * a.deplacement, Quaternion.Euler(0, 0, 90) * a.deplacement
};
}
// retourne le point de contact en l'Agent a et l'obstacle
public override Vector3 getPointContact(Agent a) {
return position;
}
}
// Vector3
using UnityEngine;
//List
using System.Collections.Generic;
// Classe pour les objets obstacles (environnement ou objet)
public abstract class Obstacle : Visible
......@@ -9,6 +11,8 @@ public abstract class Obstacle : Visible
// position de l'objet
public Vector3 position;
// environnement de l'objet
protected Environnement env;
// Méthodes
......@@ -16,7 +20,8 @@ public abstract class Obstacle : Visible
public bool isAlive() { return false; }
// l'obstacle est défini par sa position
public Obstacle(Vector3 p) {
public Obstacle(Environnement e, Vector3 p) {
env = e;
position = p;
}
......@@ -24,7 +29,7 @@ public abstract class Obstacle : Visible
public abstract Vector3 getPointContact(Agent a);
// retourne les deux tangentes au point d'impact entre l'agent et l'obstacle
public abstract (Vector3,Vector3) getTangentes(Agent a);
public abstract List<Vector3> getTangentes(Agent a);
// créer l'objet 3D relatif à cet obstacle
public abstract void createObject();
......
// Vector3
using UnityEngine;
//List
using System.Collections.Generic;
// Classe pour les obstacles qui sont des points d'impacts
public class PointObstacle : Obstacle
......@@ -7,27 +9,19 @@ public class PointObstacle : Obstacle
// Attributs
// première tangente au point
public Vector3 tangente1;
// deuxième tangente au point
public Vector3 tangente2;
// booleen décrivant les tangentes du point ont été définit à la construction
private bool defined;
// les tangentes au point
public List<Vector3> tangentes;
// Méthodes
// point d'obstacle construit par rapport à sa position et à ses tangentes
public PointObstacle(Vector3 p, Vector3 t1, Vector3 t2) : base(p) {
tangente1 = t1;
tangente2 = t2;
defined = true;
public PointObstacle(Environnement e, Vector3 p, List<Vector3> t) : base(e,p) {
tangentes = t;
}
// point d'obstacle construit par rapport à sa position
public PointObstacle(Vector3 p) : base(p) {
tangente1 = Vector3.zero;
tangente2 = Vector3.zero;
defined = false;
public PointObstacle(Environnement e, Vector3 p) : base(e,p) {
tangentes = new List<Vector3>();
}
// retourne le point de contact en l'Agent a et l'obstacle
......@@ -36,11 +30,8 @@ public class PointObstacle : Obstacle
}
// retourne les deux tangentes au point d'impact entre l'agent et l'obstacle
public override (Vector3,Vector3) getTangentes(Agent a) {
if (defined) return (tangente1,tangente2);
else {
return (tangente1,tangente2);
}
public override List<Vector3> getTangentes(Agent a) {
return tangentes;
}
// créer l'objet 3D relatif à cet obstacle
......
......@@ -10,7 +10,7 @@ public class Carre : Cube
// Méthodes
// la topologie en carre se construit à partir du visuel du carre
public Carre(GameObject c) : base(c) {
public Carre(Environnement e,GameObject c) : base(e,c) {
minZ = 0.0f;maxZ = 0.0f;
}
......@@ -21,12 +21,38 @@ public class Carre : Cube
side = convertToValidOne(side);
Vector3 haut = new Vector3(0.0f,1.0f,0.0f);
Vector3 droite = new Vector3(1.0f,0.0f,0.0f);
List<Vector3> hauts = new List<Vector3> {haut,-haut};
List<Vector3> droites = new List<Vector3> {droite,-droite};
if (side.x == minX || side.x == maxX)
return new Observation(new PointObstacle(side,haut,-haut),side-current.transform.position);
return new Observation(new PointObstacle(environnement,side,hauts),side-current.transform.position);
else
return new Observation(new PointObstacle(side,droite,-droite),side-current.transform.position);
return new Observation(new PointObstacle(environnement,side,droites),side-current.transform.position);
}
/*
// retourne le point de la topologie que l'agent current pourrait heurter
public override Observation detectEnv(Agent current) {
Vector3 pos = current.transform.position;
List<Vector3> p = getExtremPositions(current);
float dist = Utils.normVector(p[0] - pos);
float d; Vector3 res = p[0];
for(int i=1;i<p.Count;i++) {
d = Utils.normVector(p[i] - pos);
if(d<dist) {
dist = d;
res = p[i];
}
}
Vector3 haut = new Vector3(0.0f,1.0f,0.0f);
Vector3 droite = new Vector3(1.0f,0.0f,0.0f);
List<Vector3> hauts = new List<Vector3> {haut,-haut};
List<Vector3> droites = new List<Vector3> {droite,-droite};
if (res.x == minX || res.x == maxX)
return new Observation(new PointObstacle(res,hauts),res-pos);
else
return new Observation(new PointObstacle(res,droites),res-pos);
}*/
// renvoie les projections de la position de l'agent current sur les côtés du carré
protected List<Vector3> getExtremPositions(Agent current) {
Vector3 pos = current.transform.position;
......
......@@ -27,7 +27,7 @@ public class Cube : Topologie
// Méthodes
// la topologie en cube se construit à partir du visuel du cube
public Cube(GameObject c) : base() {
public Cube(Environnement e, GameObject c) : base(e) {
cube = c;
float scaleX = cube.transform.localScale.x;
float scaleY = cube.transform.localScale.y;
......@@ -64,7 +64,23 @@ public class Cube : Topologie
res = p[i];
}
}
return new Observation(new PointObstacle(res),res-pos);
//return new Observation(new PointObstacle(res),res-pos);
Vector3 XY = (new Vector3(1.0f,1.0f,0.0f)).normalized;
Vector3 XZ = (new Vector3(1.0f,0.0f,1.0f)).normalized;
Vector3 YZ = (new Vector3(0.0f,1.0f,1.0f)).normalized;
Vector3 haut = new Vector3(0.0f,1.0f,0.0f);
Vector3 droite = new Vector3(1.0f,0.0f,0.0f);
Vector3 devant = new Vector3(0.0f,0.0f,1.0f);
List<Vector3> X = new List<Vector3> {haut,-haut,devant,-devant,YZ,-YZ};
List<Vector3> Y = new List<Vector3> {droite,-droite,devant,-devant,XZ,-XZ};
List<Vector3> Z = new List<Vector3> {haut,-haut,droite,-droite,XY,-XY};
if (res.x == minX || res.x == maxX)
return new Observation(new PointObstacle(environnement,res,X),res-pos);
else if (res.y == minY || res.y == maxY)
return new Observation(new PointObstacle(environnement,res,Y),res-pos);
else
return new Observation(new PointObstacle(environnement,res,Z),res-pos);
}
// retourne une position valide dans la topologie
......
......@@ -4,11 +4,17 @@ using UnityEngine;
// Classe abstraite pour la topologie d'un environnement
public abstract class Topologie
{
// Attributs
// Environnement auquel appartient la topologie
protected Environnement environnement;
// Méthodes
// Constructeur abstrait d'une topologie d'un environnement
public Topologie() {}
public Topologie(Environnement env) {
environnement = env;
}
// retourne le GameObject de la topologie
public abstract GameObject getGameObject();
......
......@@ -23,26 +23,24 @@ public class SMA : MonoBehaviour
// Effectif de la population du système
public int population = 1;
private int oldPopulation = 1;
private static int MINPOP = 0;
private static int MAXPOP = 500;
// Booléen vérifiant si le système est en trois dimensions
public bool _3D = true;
private bool _old3D = true;
// Angle de vision des agents du système
public float angle = 180.0f;
public float angle = 250.0f;
private float oldAngle = 180.0f;
// Rayon de vision des agents du système
public float rayon = 20.0f;
private float oldRayon = 20.0f;
// Indice du Comportement à utiliser
public int currentComportement = 0;
private int oldComportement = 1;
// Coefficient k pour répulsion des Bords (+ élevé = + répulsion + loin du bord)
public float kR = 2.0f;
public float kT = 2.0f;
public float kR = 50.0f;
public float kT = 5.0f;
// Vitesse de la simulation
public float speedSimulation = 1.0f;
......@@ -50,9 +48,31 @@ public class SMA : MonoBehaviour
// test fonctionnement reynold
public bool AllReynolds = true;
// constante de distance de séparation
public float Escape = 8.0f;
// poids de la séparation
public float EscapeWeight = 1.0f;
// constante de distance de l'alignement
public float Together = 13.0f;
// poids de l'alignement
public float TogetherWeight = 1.0f;
// constante de distance de cohésion
public float Follow = 30.0f;
// poids de la cohésion
public float FollowWeight = 1.0f;
// Méthodes
private void changeReynolds() {
if(Escape != Reynolds.Escape) Reynolds.Escape = Escape;
if(EscapeWeight != Reynolds.EscapeWeight) Reynolds.EscapeWeight = EscapeWeight;
if(Together != Reynolds.Together) Reynolds.Together = Together;
if(TogetherWeight != Reynolds.TogetherWeight) Reynolds.TogetherWeight = TogetherWeight;
if(Follow != Reynolds.Follow) Reynolds.Follow = Follow;
if(FollowWeight != Reynolds.FollowWeight) Reynolds.FollowWeight = FollowWeight;
}
// renvoie l'environnement du système
public Environnement getEnvironnement() {
return env;
......@@ -94,10 +114,7 @@ public class SMA : MonoBehaviour
private void createAgent() {
GameObject a;
a = Instantiate(boid, env.validPosition(), Quaternion.identity,env.transform) as GameObject;
//a = Instantiate(boid, Vector3.zero, Quaternion.identity,environnement.transform) as GameObject;
agents.Add(a.GetComponent<Agent>());
//oldComportement++;
//changeComportement();
}
// crée un agent dans le système à la position pos
......@@ -112,6 +129,7 @@ public class SMA : MonoBehaviour
void Update()
{
changeDimension();
changeReynolds();
changePopulation();
}
......@@ -143,7 +161,6 @@ public class SMA : MonoBehaviour
changeBordConstant();
changeEffectifPopulation();
changeAngleRayonVision();
//changeComportement();
}
// mise à jour si besoin de la constante kR (repulsion) du calcul de gestion de bords
......@@ -154,8 +171,8 @@ public class SMA : MonoBehaviour
// vérifie si l'effectif voulu par le système est respecté et modifie la population s'il le faut
private void changeEffectifPopulation() {
if(population < 0) population = 0;
if(population > 100) population = 100;
if(population < MINPOP) population = MINPOP;
if(population > MAXPOP) population = MAXPOP;
if(oldPopulation != population) {
if(oldPopulation < population) createAgents(population - oldPopulation);
else {
......@@ -169,50 +186,7 @@ public class SMA : MonoBehaviour
// vérifie si l'angle et le rayon de vision des agents voulues par le système sont respectés et les modifie si besoin
private void changeAngleRayonVision() {
if (oldAngle != angle || oldRayon != rayon) {
for(int i=0; i < agents.Count; i++) agents[i].setPerception(new Perception(agents[i],angle,rayon));
}
}
// change au besoin le comportement type des agents
private void changeComportement() {
if (currentComportement != oldComportement) {
//Debug.Log("ah");
oldComportement = currentComportement;
List<Comportement> comps;
List<int> imps;
Comportement c;
if (currentComportement == 0) {
imps = new List<int> { 1,1 };
for(int i = 0; i< agents.Count; i++) {
comps = new List<Comportement> { new TangenteBord1(agents[i]), new Constant(agents[i])};
c = new CompositeSum(agents[i],comps,imps);
agents[i].setComportement(c);
}
}
else if (currentComportement == 1) {
imps = new List<int> { 1,1 };
for(int i = 0; i< agents.Count; i++) {
comps = new List<Comportement> { new TangenteBord2(agents[i]), new Constant(agents[i])};
c = new CompositeSum(agents[i],comps,imps);
agents[i].setComportement(c);
}
}
else if (currentComportement == 2) {
imps = new List<int> { 1,1 };
for(int i = 0; i< agents.Count; i++) {
comps = new List<Comportement> { new Bord(agents[i]), new Constant(agents[i])};
c = new CompositeSum(agents[i],comps,imps);
agents[i].setComportement(c);
}
}
else if (currentComportement == 3) {
imps = new List<int> { 1,1,1 };
for(int i = 0; i< agents.Count; i++) {
comps = new List<Comportement> { new Bord(agents[i]), new Constant(agents[i]), new Reynolds(agents[i])};
c = new CompositeSum(agents[i],comps,imps);
agents[i].setComportement(c);
}
}
for(int i=0; i < agents.Count; i++) agents[i].setPerception(new Perception(agents[i],rayon,angle));
}
}
......
//Vector3
using UnityEngine;
// Interface pour les objets qui peuvent être vu
public interface Visible {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment