diff --git a/comptes-rendus/journal-de-bord/media/rdv1.jpg b/comptes-rendus/journal-de-bord/media/rdv1.jpg new file mode 100755 index 0000000000000000000000000000000000000000..f9cca305ab04a426ad19c869da3e92f818280181 Binary files /dev/null and b/comptes-rendus/journal-de-bord/media/rdv1.jpg differ diff --git a/comptes-rendus/journal-de-bord/media/rdv2-1.jpg b/comptes-rendus/journal-de-bord/media/rdv2-1.jpg new file mode 100755 index 0000000000000000000000000000000000000000..69fa16f02c8ccf9cb935209a2f193873c1bebe1e Binary files /dev/null and b/comptes-rendus/journal-de-bord/media/rdv2-1.jpg differ diff --git a/comptes-rendus/journal-de-bord/media/rdv2-2.jpg b/comptes-rendus/journal-de-bord/media/rdv2-2.jpg new file mode 100755 index 0000000000000000000000000000000000000000..94147bcf3ead5156fdef5c946e5a52ae2069ff39 Binary files /dev/null and b/comptes-rendus/journal-de-bord/media/rdv2-2.jpg differ diff --git a/comptes-rendus/journal-de-bord/media/rdv2.jpg b/comptes-rendus/journal-de-bord/media/rdv2.jpg new file mode 100755 index 0000000000000000000000000000000000000000..aa0d010bcfbd97e9fa0627679d3e69feb3f8f587 Binary files /dev/null and b/comptes-rendus/journal-de-bord/media/rdv2.jpg differ diff --git a/comptes-rendus/journal-de-bord/semaines/semaine2.md b/comptes-rendus/journal-de-bord/semaines/semaine2.md index 61eb940c24e164e1f8ba4ed9321a2ee6a2eff673..021d8d7201cf59029af1632b68f624359abcc44d 100755 --- a/comptes-rendus/journal-de-bord/semaines/semaine2.md +++ b/comptes-rendus/journal-de-bord/semaines/semaine2.md @@ -41,12 +41,23 @@ Voici ici le descriptif du travail effectué lors de la journée du 24/05/2022. ### De 8h30 à 10h +* Rendez vous avec l'encadrant + ### de 10h à 12h +* Rendez vous avec l'encadrant +* Organisation du travail +* Correction du comportement de Reynolds + ### de 14h à 16h +* Correction du comportement de Reynolds +* Changement de direction*speed à speed + ### de 16h à 18h +* Gestion détection bord + <h2 id="mercredi"> <strong> 🧠 Journal de Bord - Jour 8</strong> <a href="#menu">↩️</a> </h2> diff --git a/src/Packages/v4.unitypackage b/src/Packages/v4.unitypackage new file mode 100755 index 0000000000000000000000000000000000000000..3d7b9bb620b26eaf0ae760c637a83fb5ae84ed42 Binary files /dev/null and b/src/Packages/v4.unitypackage differ diff --git a/src/Packages/v5.unitypackage b/src/Packages/v5.unitypackage new file mode 100755 index 0000000000000000000000000000000000000000..595383eb0e67f3e6752078be9e15f210f586a190 Binary files /dev/null and b/src/Packages/v5.unitypackage differ diff --git a/src/Scripts/Agent.cs b/src/Scripts/Agent.cs index 83cc5e2bfb2c6ab4d17ff826ead15bc20719239a..43137379f99897ddb2533488918ba1636728afde 100755 --- a/src/Scripts/Agent.cs +++ b/src/Scripts/Agent.cs @@ -1,84 +1,121 @@ -using System; -using System.Collections; -using System.Collections.Generic; +// Monobehaviour + Vector3 using UnityEngine; +// List +using System.Collections.Generic; - +// Classe correspondant à un agent boïd public class Agent : MonoBehaviour, Visible { - public SMA system; + // Attributs + + // système auquel l'agent appartient + private SMA system; + // comportement de l'agent private Comportement comportement; + // perception de l'agent private Perception perception; - public Vector3 direction; - private float speed; - private List<Vector3> oldDirections; - private int Taille_Memoire = 5; - private int angle = 180; + // deplacement courant de l'agent + public Vector3 deplacement; + // mémoire des anciens déplacements + private List<Vector3> oldDeplacement; + // taille mémoire + private int Taille_Memoire = 5; + + // nombre d'Agents créés private static int count = 0; - public int id; + // identifiant de l'agent; + private int id; + + + // Méthodes + + // renvoie le système auquel l'agent appartient + public SMA getSystem() { + return system; + } - // Start is called before the first frame update + // indique s'il est un Visible mobile + public bool isAlive() { return true; } + + // utilise la perception p en tant que nouvelle perception de l'agent + public void setPerception(Perception p) { + perception = p; + } + + // utilise le comportement c en tant que nouveau comportement de l'agent + public void setComportement(Comportement c) { + comportement = c; + } + + // Start est appelé avant la première image affichée void Start() { system = GameObject.Find("SMA").GetComponent<SMA>(); - //List<Comportement> comps = new List<Comportement> { new Reynolds(this), new Bord(this), new Aleatoire(this)}; - List<Comportement> comps = new List<Comportement> { new Paper(this), new Bord(this), new Aleatoire(this)}; - List<int> imps = new List<int> { 5,5,2 }; - Comportement c = new CompositeSeq(this,comps,imps); + //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 }; + Comportement c = new CompositeSum(this,comps,imps); if(system._3D) comportement = c; else comportement = new Constrain2D(this,c); perception = new Perception180(this,20.0f); - direction = Vector3.zero; - speed = 0.7f; - oldDirections = new List<Vector3>(); + + deplacement = Utils.randomDirection(); + //deplacement = new Vector3(0.5f,0.5f,0.0f); + oldDeplacement = new List<Vector3>(); id = Agent.count; Agent.count++; } - // Update is called once per frame + // Update est appelée à chaque affichage void Update() { - if(angle != system.angle) { - angle = system.angle; - perception = new Perception(this,20.0f,(float) angle); - } reagir(voir()); memoire(); } - public List<Observation> voir() { return perception.voir(); } + // renvoie les observations effectuées par l'agent + private List<Observation> voir() { return perception.voir(); } - public void reagir(List<Observation> observation) {direction = comportement.reagir(observation); move(); } + // réaction de l'agent en fonction de ses observations + private void reagir(List<Observation> observation) { + float norm = Utils.normVector(deplacement); + deplacement = comportement.reagir(observation); + deplacement = deplacement.normalized * norm; + move(); + } - void move() { - transform.position += speed*direction; - transform.LookAt(transform.position + speed*direction); + // déplacement de l'agent + private void move() { + transform.position += (deplacement * system.speedSimulation); + transform.LookAt(transform.position + deplacement); } - void memoire() { - oldDirections.Add(direction); - if (oldDirections.Count > Taille_Memoire) oldDirections.RemoveAt(0); + // gestion de la mémoire des précédents déplacements + private void memoire() { + oldDeplacement.Add(deplacement); + if (oldDeplacement.Count > Taille_Memoire) oldDeplacement.RemoveAt(0); } - public bool isAlive() { return true; } - + // appelé lors qu'il rentre en contact avec un autre Collider void OnTriggerEnter(Collider other) { - direction = Vector3.zero; //Debug.Log("enter trigger"); } + // appelé lors qu'il sort de contact avec un autre Collider void OnTriggerExit(Collider other) { - direction = Utils.meanVector(oldDirections); //Debug.Log("exit trigger"); } + // méthode de test d'égalité si l'agent est égal à l'objet obj public override bool Equals(object obj) { // If the passed object is null @@ -93,6 +130,7 @@ public class Agent : MonoBehaviour, Visible return (this.id == ((Agent) obj).id); } + // renvoie le hashCode de l'agent public override int GetHashCode() { return id; diff --git a/src/Scripts/Comportement/Aleatoire.cs b/src/Scripts/Comportement/Base/Aleatoire.cs similarity index 56% rename from src/Scripts/Comportement/Aleatoire.cs rename to src/Scripts/Comportement/Base/Aleatoire.cs index 782a799b7b242f22e71d63f7e5da2d2e1a14dda5..0481366ec01f9741951c0a798b2fbecb31e7329e 100755 --- a/src/Scripts/Comportement/Aleatoire.cs +++ b/src/Scripts/Comportement/Base/Aleatoire.cs @@ -1,12 +1,16 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe pour le comportement aleatoire public class Aleatoire : Comportement { + // Le comportement est construit par rapport à un proprietaire public Aleatoire(Agent proprietaire) : base(proprietaire) {} + // retourne le vecteur déplacement en réaction aux observations public override Vector3 reagir(List<Observation> observation) { return Utils.randomDirection(); } diff --git a/src/Scripts/Comportement/Base/Comportement.cs b/src/Scripts/Comportement/Base/Comportement.cs new file mode 100755 index 0000000000000000000000000000000000000000..c505789cf06c37a04914eacd736c25c2616120f2 --- /dev/null +++ b/src/Scripts/Comportement/Base/Comportement.cs @@ -0,0 +1,25 @@ +// List +using System.Collections.Generic; +// Vector3 +using UnityEngine; + +// Classe abstraite pour les comportements d'agent +public abstract class Comportement +{ + + // Attributs + + // le proprietaire du comportement + protected Agent proprietaire; + + // Méthodes + + // Le comportement est construit par rapport à un proprietaire + public Comportement(Agent a) { + proprietaire = a; + } + + // retourne le vecteur déplacement en réaction aux observations + public abstract Vector3 reagir(List<Observation> observation) ; + +} diff --git a/src/Scripts/Comportement/Base/Constant.cs b/src/Scripts/Comportement/Base/Constant.cs new file mode 100755 index 0000000000000000000000000000000000000000..f822febcf02f29f96ba9077b4c54102fe7c974b7 --- /dev/null +++ b/src/Scripts/Comportement/Base/Constant.cs @@ -0,0 +1,16 @@ +// List +using System.Collections.Generic; +// Vector3 +using UnityEngine; + +// Classe pour le comportement constant +public class Constant : Comportement +{ + // Le comportement est construit par rapport à un proprietaire + public Constant(Agent proprietaire) : base(proprietaire) {} + + // retourne le vecteur déplacement en réaction aux observations + public override Vector3 reagir(List<Observation> observation) { + return proprietaire.deplacement; + } +} diff --git a/src/Scripts/Comportement/Bord.cs b/src/Scripts/Comportement/Bord.cs deleted file mode 100755 index 1a68f62112d0297246c6556e484608225e222297..0000000000000000000000000000000000000000 --- a/src/Scripts/Comportement/Bord.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class Bord : Comportement -{ - static public float Urgent = 5.0f; - static public float Preoccuppant = 8.0f; - static public float Intrigant = 10.0f; - private Vector3 currentGoal; - - public Bord(Agent proprietaire) : base(proprietaire) { currentGoal = proprietaire.direction;} - - public override Vector3 reagir(List<Observation> observation) { - List<Vector3> vectors = new List<Vector3>(); - vectors.Add(proprietaire.direction); - foreach(Observation o in observation) { - if (!o.objet.isAlive()) { - - - if(grandDanger(o)) for(int i=0;i<8;i++) vectors.Add(fuir(o.distance)); - else if(moyenDanger(o)) for(int i=0;i<5;i++) vectors.Add(fuir(o.distance)); - else if(petitDanger(o)) for(int i=0;i<3;i++) vectors.Add(fuir(o.distance)); - - - /* - if(grandDanger(o)) for(int i=0;i<8;i++) vectors.Add(fuir(proprietaire.direction)); - else if(moyenDanger(o)) for(int i=0;i<5;i++) vectors.Add(fuir(proprietaire.direction)); - else if(petitDanger(o)) for(int i=0;i<3;i++) vectors.Add(fuir(proprietaire.direction)); - */ - } - } - Vector3 res = Utils.meanVector(vectors); - //currentGoal = res; - return Utils.meanVector(new List<Vector3> {res,proprietaire.direction}); - //return res; - //return Utils.noiseVector(res,nbBruit,bruit); - } - - private bool grandDanger(Observation o) { - return (Utils.normVector(o.distance) < Urgent); - } - - private bool moyenDanger(Observation o) { - return (Utils.normVector(o.distance) < Preoccuppant); - } - - private bool petitDanger(Observation o) { - return (Utils.normVector(o.distance) < Intrigant); - } - - private Vector3 fuir(Vector3 d) { return -d.normalized; } -} diff --git a/src/Scripts/Comportement/Bord/Bord.cs b/src/Scripts/Comportement/Bord/Bord.cs new file mode 100755 index 0000000000000000000000000000000000000000..c90425b7f05114f1d6df5fb06ae90488d7d96389 --- /dev/null +++ b/src/Scripts/Comportement/Bord/Bord.cs @@ -0,0 +1,42 @@ +// List +using System.Collections.Generic; +// Vector3 +using UnityEngine; + +// Classe pour le comportement de gestion de bord +public class Bord : Comportement +{ + + // Attributs + + // constante de force de répulsion + static public float kR = 1.0f; + + // Méthodes + + // Le comportement est construit par rapport à un proprietaire + public Bord(Agent proprietaire) : base(proprietaire) {} + + // retourne le vecteur déplacement en réaction aux observations + public override Vector3 reagir(List<Observation> observation) { + List<Vector3> vectors = new List<Vector3>(); + foreach(Observation o in observation) { + if (!o.objet.isAlive()) { + vectors.Add(delta(o.distance) * answer(o)); + } + } + Vector3 res = Utils.meanVector(vectors); + return res; + } + + // force de répulsion en fonction de la distance d + protected virtual float delta(Vector3 d) { + return kR/Utils.pow(Utils.normVector(d),2); + } + + // vecteur réponse à l'observation + protected virtual Vector3 answer(Observation o) { + return -proprietaire.deplacement; + } + +} diff --git a/src/Scripts/Comportement/Bord/TangenteBord1.cs b/src/Scripts/Comportement/Bord/TangenteBord1.cs new file mode 100755 index 0000000000000000000000000000000000000000..33e5a6cf04a6c8cbf4b62c2065fb6caf2f3868af --- /dev/null +++ b/src/Scripts/Comportement/Bord/TangenteBord1.cs @@ -0,0 +1,40 @@ +// Vector3 +using UnityEngine; +// list +using System.Collections.Generic; + +// 1ere classe pour comportement de bord qui répond en tangente +public class TangenteBord1 : Bord +{ + + // Le comportement est construit par rapport à un proprietaire + public TangenteBord1(Agent proprietaire) : base(proprietaire) {} + + // retourne le vecteur déplacement en réaction aux observations + public override Vector3 reagir(List<Observation> observation) { + List<Vector3> vectors = new List<Vector3>(); + foreach(Observation o in observation) { + if (!o.objet.isAlive()) { + vectors.Add(delta(o.distance) * answer(o)); + vectors.Add(deltaTan(o.distance) * answerTan(o)); + } + } + Vector3 res = Utils.meanVector(vectors); + return res; + } + + // retourne l'intensité du vecteur réponse selon une distance + protected virtual float deltaTan(Vector3 d) { + return kR/Utils.normVector(d); + } + + // 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; + } + +} diff --git a/src/Scripts/Comportement/Bord/TangenteBord2.cs b/src/Scripts/Comportement/Bord/TangenteBord2.cs new file mode 100755 index 0000000000000000000000000000000000000000..aef3037fd86e5d2998b0f43cb4c23ffa7151a1ec --- /dev/null +++ b/src/Scripts/Comportement/Bord/TangenteBord2.cs @@ -0,0 +1,24 @@ +// Vector3 +using UnityEngine; +// list +using System.Collections.Generic; + +// 2eme classe pour comportement de bord qui répond en tangente +public class TangenteBord2 : TangenteBord1 +{ + // Attributs + + // constante de force de tangente + public static float kT = 1.0f; + + // Méthodes + + // Le comportement est construit par rapport à un proprietaire + public TangenteBord2(Agent proprietaire) : base(proprietaire) {} + + // retourne l'intensité du vecteur réponse selon une distance + protected override float deltaTan(Vector3 d) { + return kT/Utils.normVector(d); + } + +} diff --git a/src/Scripts/Comportement/Comportement.cs b/src/Scripts/Comportement/Comportement.cs deleted file mode 100755 index 7b4b4d2d2b079699fb1cfc38e0d52817676b804f..0000000000000000000000000000000000000000 --- a/src/Scripts/Comportement/Comportement.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public abstract class Comportement -{ - - protected Agent proprietaire; - - protected int nbBruit = 10; - protected float bruit = 0.05f; - - public Comportement(Agent a) { - proprietaire = a; - } - - public abstract Vector3 reagir(List<Observation> observation) ; - -} diff --git a/src/Scripts/Comportement/Composite/CompositeMean.cs b/src/Scripts/Comportement/Composite/CompositeMean.cs new file mode 100755 index 0000000000000000000000000000000000000000..d8639c37bbd8da684c1a1042ac4d9796fe5b7202 --- /dev/null +++ b/src/Scripts/Comportement/Composite/CompositeMean.cs @@ -0,0 +1,27 @@ +// List +using System.Collections.Generic; +// Vector3 +using UnityEngine; + +// Classe pour le comportement composé et moyennant +public class CompositeMean : CompositeSum +{ + + // Le comportement est construit par rapport à un proprietaire, une liste de comportement et une liste d'importance + public CompositeMean(Agent proprietaire,List<Comportement> c,List<int> i) : base(proprietaire,c,i) {} + + // Le comportement est construit par rapport à un proprietaire + public CompositeMean(Agent proprietaire) : base(proprietaire) {} + + // retourne le vecteur déplacement en réaction aux observations + public override Vector3 reagir(List<Observation> observation) { + List<Vector3> vectors = new List<Vector3>(); + Vector3 add; + for(int i=0;i<comportements.Count;i++) { + add = comportements[i].reagir(observation); + for(int j=0; j<importances[i];j++) vectors.Add(add); + } + return Utils.meanVector(vectors); + } + +} diff --git a/src/Scripts/Comportement/Composite/CompositeSum.cs b/src/Scripts/Comportement/Composite/CompositeSum.cs new file mode 100755 index 0000000000000000000000000000000000000000..4a66b59200f95e2be5f58289334312896c92068c --- /dev/null +++ b/src/Scripts/Comportement/Composite/CompositeSum.cs @@ -0,0 +1,48 @@ +// List +using System.Collections.Generic; +// Vector3 +using UnityEngine; + +// Classe pour le comportement composé et additionnant +public class CompositeSum : Comportement +{ + + // Attributs + + // liste des comportements qui compose notre comportement + protected List<Comportement> comportements; + // liste des poids d'importances des comportements + protected List<int> importances; + + // Méthodes + + // Le comportement est construit par rapport à un proprietaire, une liste de comportement et une liste d'importance + public CompositeSum(Agent proprietaire,List<Comportement> c,List<int> i) : base(proprietaire) { + comportements = c; + importances = i; + } + + // Le comportement est construit par rapport à un proprietaire + public CompositeSum(Agent proprietaire) : base(proprietaire) { + comportements = new List<Comportement>(); + importances = new List<int>(); + } + + // enlève le ieme comportement de la liste des comportements + public void removeComportement(int i) { comportements.RemoveAt(i);importances.RemoveAt(i); } + + // rajoute le comportement c avoir un poids d'importance i dans la liste des comportements + public void AddComportement(Comportement c, int i) { comportements.Add(c); importances.Add(i);} + + // retourne le vecteur déplacement en réaction aux observations + public override Vector3 reagir(List<Observation> observation) { + Vector3 res = Vector3.zero; + Vector3 add; + for(int i=0;i<comportements.Count;i++) { + add = comportements[i].reagir(observation); + for(int j=0; j<importances[i];j++) res += add; + } + return res; + } + +} diff --git a/src/Scripts/Comportement/CompositeSeq.cs b/src/Scripts/Comportement/CompositeSeq.cs deleted file mode 100755 index 96aa24c5c8fa8d52c3b9ed91f40ca27b378cfc7a..0000000000000000000000000000000000000000 --- a/src/Scripts/Comportement/CompositeSeq.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class CompositeSeq : Comportement -{ - - protected List<Comportement> comportements; - protected List<int> importances; - - public CompositeSeq(Agent proprietaire,List<Comportement> c,List<int> i) : base(proprietaire) { - comportements = c; - importances = i; - } - - public CompositeSeq(Agent proprietaire) : base(proprietaire) { - comportements = new List<Comportement>(); - importances = new List<int>(); - } - - public void removeComportement(int i) { comportements.RemoveAt(i);importances.RemoveAt(i); } - - public void AddComportement(Comportement c, int i) { comportements.Add(c); importances.Add(i);} - - public override Vector3 reagir(List<Observation> observation) { - List<Vector3> vectors = new List<Vector3>(); - vectors.Add(proprietaire.direction); - Vector3 add; - for(int i=0;i<comportements.Count;i++) { - add = comportements[i].reagir(observation); - for(int j=0; j<importances[i];j++) vectors.Add(add); - } - return Utils.meanVector(vectors); - } - -} diff --git a/src/Scripts/Comportement/Constrain2D.cs b/src/Scripts/Comportement/Contrainte/Constrain2D.cs similarity index 52% rename from src/Scripts/Comportement/Constrain2D.cs rename to src/Scripts/Comportement/Contrainte/Constrain2D.cs index 5ec58ccf0cf2819051943ae831e05608d05dbf99..065e67c8163001aa3752552df8a7befd9732e4e6 100755 --- a/src/Scripts/Comportement/Constrain2D.cs +++ b/src/Scripts/Comportement/Contrainte/Constrain2D.cs @@ -1,20 +1,29 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe pour le comportement qui contraint en 2D public class Constrain2D : Comportement { + + // Attributs + + // le comportement qui est contraint protected Comportement comportement; + // Méthodes + + // Le comportement est construit par rapport à un proprietaire et un comportement à contraindre public Constrain2D(Agent proprietaire,Comportement c) : base(proprietaire) { comportement = c; } + // retourne le vecteur déplacement en réaction aux observations public override Vector3 reagir(List<Observation> observation) { Vector3 res = comportement.reagir(observation); - res *= 2; res.z = 0.0f; - return res.normalized; + return res; } } diff --git a/src/Scripts/Comportement/Paper.cs b/src/Scripts/Comportement/Papers/Paper.cs similarity index 80% rename from src/Scripts/Comportement/Paper.cs rename to src/Scripts/Comportement/Papers/Paper.cs index 2c76e86aaa8ad964db8d2a1330646285f76a710c..0190195d86a1f5c29ce5961cb46b56e29ff97b38 100755 --- a/src/Scripts/Comportement/Paper.cs +++ b/src/Scripts/Comportement/Papers/Paper.cs @@ -1,27 +1,41 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 using UnityEngine; +// Serializable using System; +// Classe pour le comportement du papier scientifique qu'on veut tester public class Paper : Comportement { + // Classe interne correspondant à une mémoire dyadic [Serializable] public class Memory { + // agent en mémoire public Agent agent; + // la distance idéale courante public float idealDistance; + // la distance prévue public float predictDistance; + // l'intention de déplacement public float predictAttempt; + // la stagnation courante public float stagnation; + // l'exilation courante public float exilation; + // la mémoire se contruit en fonction d'un agent, une distance idéale, une distance prévue et une attention public Memory(Agent a, float ideal, float predict, float attempt) { agent = a; idealDistance = ideal; predictDistance = predict; predictAttempt = attempt; stagnation = stagnationTolerance; exilation = exileTolerance; } }; + // Attributs + + // liste des vecteurs déplacements possibles private static List<Vector3> moves = new List<Vector3> { (new Vector3(-1.0f,1.0f,0.0f)).normalized, (new Vector3(0.0f,1.0f,0.0f)).normalized, (new Vector3(1.0f,1.0f,0.0f)).normalized, @@ -36,7 +50,7 @@ public class Paper : Comportement }; // Critical real distance at which the FSRs are activated - private static float activeSeuil = 8.0f; + private static float activeSeuil = 10.0f; // Change rate (0 < P_C < 1) for increasing and decreasing ideal distances, and stagnation and exile tolerance times private static float changeRate = 0.2f; // Initial value of the stagnation tolerance time @@ -44,21 +58,21 @@ public class Paper : Comportement // Initial value of the exile tolerance time private static float exileTolerance = 30.0f; + // liste des mémoires courantes private List<Memory> memories = new List<Memory>(); + // Le comportement est construit par rapport à un proprietaire + public Paper(Agent proprietaire) : base(proprietaire) {} - public Paper(Agent proprietaire) : base(proprietaire) { - - } - + // retourne le vecteur déplacement en réaction aux observations public override Vector3 reagir(List<Observation> observation) { - List<Vector3> candidatesVectors = getTheMoves(observation); Vector3 themove = getTheMove(candidatesVectors); assumeTheMove(themove,observation); return themove; } + // retourne les déplacements à la dissatisfaction minimale selon les observations private List<Vector3> getTheMoves(List<Observation> observation) { List<Vector3> candidatesVectors = new List<Vector3>(); float disatifaction = 1000.0f; float d; @@ -73,13 +87,15 @@ public class Paper : Comportement } return candidatesVectors; } + + // retourne le déplacement qui perturbe le moins la direction courante de l'agent parmi les déplacements candidats private Vector3 getTheMove(List<Vector3> candidatesVectors) { - Vector3 themove = proprietaire.direction; + Vector3 themove = proprietaire.deplacement; float d = 1000.0f; float sum; for(int i=0;i<candidatesVectors.Count;i++) { - sum = Utils.abs(proprietaire.direction.x - candidatesVectors[i].x); - sum += Utils.abs(proprietaire.direction.y - candidatesVectors[i].y); - sum += Utils.abs(proprietaire.direction.z - candidatesVectors[i].z); + sum = Utils.abs(proprietaire.deplacement.x - candidatesVectors[i].x); + sum += Utils.abs(proprietaire.deplacement.y - candidatesVectors[i].y); + sum += Utils.abs(proprietaire.deplacement.z - candidatesVectors[i].z); if (sum < d) { d = sum; themove = candidatesVectors[i]; @@ -88,6 +104,7 @@ public class Paper : Comportement return themove; } + // conséquence du choix du déplacement choisi private void assumeTheMove(Vector3 themove,List<Observation> observation) { Vector3 futurPos = proprietaire.transform.position + themove; List<Observation> agentObservations = observation.FindAll(isAgent); @@ -105,11 +122,13 @@ public class Paper : Comportement } } + // retourne si l'objet observé est un agent private bool isAgent(Observation o) {return o.objet.isAlive();} + // renvoie la dissatisfaction d'un déplacement selon les private float computeDisatisfaction(Vector3 move, List<Observation> observation) { float d = 0.0f; int nb = 0; - float m = proprietaire.system.environnement.getMaxDistance(); + float m = proprietaire.getSystem().getEnvironnement().getMaxDistance(); Vector3 possiblePos = proprietaire.transform.position + move; Vector3 reachPoint; float reachDist; Agent concerned; float dist; @@ -130,6 +149,7 @@ public class Paper : Comportement else return d/(nb*m); } + // ajout de l'agent dans la liste de mémoires private void addAgentInMemory(Agent concerned,float dist,float max, float reachDist) { bool hasToBeAdd = true; int i = 0; @@ -143,6 +163,7 @@ public class Paper : Comportement } } + // calcul de la distance idéale private float idealDistance(Agent other) { int i = 0; while(memories[i].agent != other) i++; @@ -163,6 +184,8 @@ public class Paper : Comportement float ideal = (1 + k*changeRate) * memories[i].idealDistance; memories[i].idealDistance = ideal; return 5.0f; + + //return ideal; /* if(Utils.abs(ideal - memories[i].idealDistance) < changeRate && memories[i].stagnation > 1) { diff --git a/src/Scripts/Comportement/Papers/Reynolds.cs b/src/Scripts/Comportement/Papers/Reynolds.cs new file mode 100755 index 0000000000000000000000000000000000000000..6eb622ba732588b5fc8eb78b50cf69d80d653c9c --- /dev/null +++ b/src/Scripts/Comportement/Papers/Reynolds.cs @@ -0,0 +1,88 @@ +// List +using System.Collections.Generic; +// Vector3 +using UnityEngine; + +// Classe pour le comportement du papier de Reynolds +public class Reynolds : Comportement +{ + + // Attributs + + // constante de distance de séparation + static public float Escape = 10.0f; + // poids de la séparation + static public float EscapeWeight = 3.0f; + // constante de distance de l'alignement + static public float Together = 20.0f; + // poids de l'alignement + static public float TogetherWeight = 1.0f; + // constante de distance de cohésion + static public float Follow = 25.0f; + // poids de la cohésion + static public float FollowWeight = 2.0f; + + // Méthodes + + // Le comportement est construit par rapport à un proprietaire + public Reynolds(Agent proprietaire) : base(proprietaire) {} + + // retourne le vecteur déplacement en réaction aux observations + public override Vector3 reagir(List<Observation> observation) { + List<Vector3> vectorsFuir = new List<Vector3>(); + List<Vector3> vectorsSuivre = new List<Vector3>(); + List<Vector3> vectorsRapprocher = new List<Vector3>(); + foreach(Observation o in observation) { + if (o.objet.isAlive()) { + if(proprietaire.getSystem().AllReynolds) { + if(danger(o)) vectorsFuir.Add(fuir(o.distance)); + if(normal(o)) vectorsSuivre.Add(suivre(o.objet)); + if(isolement(o)) vectorsRapprocher.Add(rapprocher(o.distance)); + } + else { + if(danger(o)) vectorsFuir.Add(fuir(o.distance)); + else if(normal(o)) vectorsSuivre.Add(suivre(o.objet)); + else if(isolement(o)) vectorsRapprocher.Add(rapprocher(o.distance)); + } + } + } + float security = 1.0f; + if(vectorsRapprocher.Count == 0) security = 0.0f; + Vector3 res = EscapeWeight * Utils.meanVector(vectorsFuir).normalized + + TogetherWeight * Utils.meanVector(vectorsSuivre).normalized + + FollowWeight * security * + (Utils.meanVector(vectorsRapprocher) - proprietaire.transform.position).normalized; + + return res.normalized; + } + + // renvoie s'il faut s'éloigner + private bool danger(Observation o) { + return (Utils.normVector(o.distance) <= Escape); + } + + // renvoie le vecteur d'eloignement + private Vector3 fuir(Vector3 d) { return -d; } + + // renvoie s'il faut s'aligner + private bool normal(Observation o) { + return Utils.normVector(o.distance) <= Together; + } + + // renvoie le vecteur d'alignement + private Vector3 suivre(Visible a) { + Agent agent = (Agent) a; + return agent.deplacement; + } + + // renvoie s'il faut se rapprocher + private bool isolement(Observation o) { + return Utils.normVector(o.distance) <= Follow; + } + + // renvoie le vecteur de cohésion + private Vector3 rapprocher(Vector3 d) { + return proprietaire.transform.position + d; + } + +} diff --git a/src/Scripts/Comportement/Reynolds.cs b/src/Scripts/Comportement/Reynolds.cs deleted file mode 100755 index 4d414db40d785944c02ba15ce54ffe7235044b1b..0000000000000000000000000000000000000000 --- a/src/Scripts/Comportement/Reynolds.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class Reynolds : Comportement -{ - - static public float Escape = 5.0f; - static public float Together = 10.0f; - static public float Follow = 15.0f; - - public Reynolds(Agent proprietaire) : base(proprietaire) {} - - public override Vector3 reagir(List<Observation> observation) { - List<Vector3> vectors = new List<Vector3>(); - vectors.Add(proprietaire.direction); - foreach(Observation o in observation) { - if (o.objet.isAlive()) { - if(danger(o)) vectors.Add(fuir(o.distance)); - else if(normal(o)) vectors.Add(suivre(o.objet)); - else if(isolement(o)) vectors.Add(rapprocher(o.distance)); - } - } - Vector3 res = Utils.meanVector(vectors); - return res; - //return Utils.noiseVector(res,nbBruit,bruit); - } - - private bool danger(Observation o) { - return (Utils.normVector(o.distance) < Escape); - } - - private Vector3 fuir(Vector3 d) { return -d.normalized; } - - private bool normal(Observation o) { - return Utils.normVector(o.distance) < Together; - } - - private Vector3 suivre(Visible a) { - Agent agent = (Agent) a; - return agent.direction.normalized; - } - - private bool isolement(Observation o) { - return Utils.normVector(o.distance) <= Follow; - } - - private Vector3 rapprocher(Vector3 d) { return d.normalized; } - -} diff --git a/src/Scripts/Comportement/Player.cs b/src/Scripts/Comportement/Role/Player.cs similarity index 55% rename from src/Scripts/Comportement/Player.cs rename to src/Scripts/Comportement/Role/Player.cs index 6e16e35097d8eba081cd6cf2523774406aab1425..630b84392cb8b02135a1b20786cf1b67a928da9a 100755 --- a/src/Scripts/Comportement/Player.cs +++ b/src/Scripts/Comportement/Role/Player.cs @@ -1,11 +1,15 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe pour le comportement de joueur public class Player : Comportement { + // Le comportement est construit par rapport à un proprietaire public Player(Agent proprietaire) : base(proprietaire) {} + // retourne le vecteur déplacement en réaction aux observations public override Vector3 reagir(List<Observation> observation) { return Utils.randomDirection(); } diff --git a/src/Scripts/Comportement/Predator.cs b/src/Scripts/Comportement/Role/Predator.cs similarity index 55% rename from src/Scripts/Comportement/Predator.cs rename to src/Scripts/Comportement/Role/Predator.cs index 600118f2a2c536ad872827afa8dee1cf8c59d527..f8e05331a21c7a0d30b59f34d6f0f7fdc1134783 100755 --- a/src/Scripts/Comportement/Predator.cs +++ b/src/Scripts/Comportement/Role/Predator.cs @@ -1,11 +1,16 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe pour le comportement de predateur public class Predator : Comportement { + + // Le comportement est construit par rapport à un proprietaire public Predator(Agent proprietaire) : base(proprietaire) {} + // retourne le vecteur déplacement en réaction aux observations public override Vector3 reagir(List<Observation> observation) { return Utils.randomDirection(); } diff --git a/src/Scripts/Comportement/Prey.cs b/src/Scripts/Comportement/Role/Prey.cs similarity index 55% rename from src/Scripts/Comportement/Prey.cs rename to src/Scripts/Comportement/Role/Prey.cs index e2eee6545925ecead972d720e4b8a1fdbfeeb8e7..33ab16bc7436736b2143a10bf6906f21192b8498 100755 --- a/src/Scripts/Comportement/Prey.cs +++ b/src/Scripts/Comportement/Role/Prey.cs @@ -1,11 +1,16 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe pour le comportement de proie public class Prey : Comportement { + + // Le comportement est construit par rapport à un proprietaire public Prey(Agent proprietaire) : base(proprietaire) {} + // retourne le vecteur déplacement en réaction aux observations public override Vector3 reagir(List<Observation> observation) { return Utils.randomDirection(); } diff --git a/src/Scripts/Environnement/Environnement.cs b/src/Scripts/Environnement/Environnement.cs index b0e15a2ab4dab3ceebf8025532419df4ac98e836..5504f6cb53357bfd297da0e44521ac6bce160165 100755 --- a/src/Scripts/Environnement/Environnement.cs +++ b/src/Scripts/Environnement/Environnement.cs @@ -1,59 +1,90 @@ -using System.Collections; -using System.Collections.Generic; +// Monobehaviour + Vector3 using UnityEngine; +// List +using System.Collections.Generic; +// Classe correpondant à l'environnement du système public class Environnement : MonoBehaviour { - private SMA system; - private Topologie topologie; + // Attributs + + // Les GameObjects pour crée le visuel de l'environnement + // Visuel environnement en cube public GameObject cube; + // Visuel environnement en carré public GameObject carre; - private List<Obstacle> obstacles; + // Visuel test + public GameObject test; - // Start is called before the first frame update - void Start() - { - system = GameObject.Find("SMA").GetComponent<SMA>(); - obstacles = new List<Obstacle>(); - topologie = new Cube(cube); - //topologie = new Carre(carre); - Instantiate(topologie.getGameObject(), Vector3.zero, Quaternion.identity,transform); - } + // système utilisant l'environnement + private SMA system; + // actuel dimension de l'environnement + private bool _3D; + // topologie de l'environnement + private Topologie topologie; + // liste des obstacles dans l'environnement + private List<Obstacle> obstacles = new List<Obstacle>(); - public List<Observation> voisinage(Agent current, float rayon, float angle) { - Vector3 dist; float l; float a; - List<Observation> res = new List<Observation>(); - for(int i = 0; i<system.agents.Count;i++) { - dist = system.agents[i].transform.position - current.transform.position; - l = Utils.normVector(dist); - a = Vector3.Angle(current.direction,dist); - if (system.agents[i] != current && l <= rayon && a <= angle/2.0f) res.Add(new Observation(system.agents[i],dist)); - } - Observation bord = topologie.detectEnv(current); - l = Utils.normVector(bord.distance); a = Vector3.Angle(current.direction,bord.distance); - if(l <= rayon && a <= angle/2.0f) res.Add(bord); - return res; + + // Méthodes + + // renvoie la topologie de l'environnement + public Topologie getTopologie() { + return topologie; } + // renvoie une position valide dans l'environnement public Vector3 validPosition() { return topologie.validPosition(); } + // renvoie la distance maximale mesurable dans l'environnement public float getMaxDistance() { return topologie.getMaxDistance(); } - public void changeTo3D(bool _3D) { + // change l'environnement en 3D ou non selon le système + public void notify() { + if(_3D != system._3D) { + _3D = system._3D; + if(_3D) topologie = new Cube(cube); + else topologie = new Carre(carre); + setTheTopologie(); + } + } + + // Initialise l'environnement avec seulement son contour + private void setTheTopologie() { foreach (Transform child in transform) Destroy(child.gameObject); - if(_3D) topologie = new Cube(cube); - else topologie = new Carre(carre); Instantiate(topologie.getGameObject(), Vector3.zero, Quaternion.identity,transform); } - // Update is called once per frame - void Update() + // 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) { + Vector3 dist; float l; float a; + List<Observation> res = new List<Observation>(); + List<Agent> agents = system.getAgents(); + for(int i = 0; i<agents.Count;i++) { + dist = agents[i].transform.position - current.transform.position; + 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)); + } + 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); + } + return res; + } + + // Start est appelé avant la première image affichée + void Start() { - + system = GameObject.Find("SMA").GetComponent<SMA>(); + _3D = !system._3D; + notify(); } + } diff --git a/src/Scripts/Environnement/Obstacle.cs b/src/Scripts/Environnement/Obstacle.cs deleted file mode 100755 index 8e63bc1295a382e858d8128538a036455958d86d..0000000000000000000000000000000000000000 --- a/src/Scripts/Environnement/Obstacle.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class Obstacle : Visible -{ - - Vector3 position; - - public bool isAlive() { return false; } - - public Obstacle(Vector3 p) { - position = p; - } -} diff --git a/src/Scripts/Environnement/Obstacle/Obstacle.cs b/src/Scripts/Environnement/Obstacle/Obstacle.cs new file mode 100755 index 0000000000000000000000000000000000000000..31bd9d09721eed06fc31521466196ac70e292645 --- /dev/null +++ b/src/Scripts/Environnement/Obstacle/Obstacle.cs @@ -0,0 +1,31 @@ +// Vector3 +using UnityEngine; + +// Classe pour les objets obstacles (environnement ou objet) +public abstract class Obstacle : Visible +{ + + // Attributs + + // position de l'objet + public Vector3 position; + + // Méthodes + + // indique s'il est un Visible mobile + public bool isAlive() { return false; } + + // l'obstacle est défini par sa position + public Obstacle(Vector3 p) { + position = p; + } + + // retourne le point de contact en l'Agent a et l'obstacle + 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); + + // créer l'objet 3D relatif à cet obstacle + public abstract void createObject(); +} diff --git a/src/Scripts/Environnement/Obstacle/PointObstacle.cs b/src/Scripts/Environnement/Obstacle/PointObstacle.cs new file mode 100755 index 0000000000000000000000000000000000000000..8987c4bf5f91048e9e6d76ad78c992840943359a --- /dev/null +++ b/src/Scripts/Environnement/Obstacle/PointObstacle.cs @@ -0,0 +1,49 @@ +// Vector3 +using UnityEngine; + +// Classe pour les obstacles qui sont des points d'impacts +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; + + // 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; + } + + // point d'obstacle construit par rapport à sa position + public PointObstacle(Vector3 p) : base(p) { + tangente1 = Vector3.zero; + tangente2 = Vector3.zero; + defined = false; + } + + // retourne le point de contact en l'Agent a et l'obstacle + public override Vector3 getPointContact(Agent a) { + return position; + } + + // 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); + } + } + + // créer l'objet 3D relatif à cet obstacle + public override void createObject() {} + +} diff --git a/src/Scripts/Environnement/Topologie/Carre.cs b/src/Scripts/Environnement/Topologie/Carre.cs index e8a74935ac41be39eaa69d4adef5ce724affcd27..106ce0737561021e957aae14163c341945b56c33 100755 --- a/src/Scripts/Environnement/Topologie/Carre.cs +++ b/src/Scripts/Environnement/Topologie/Carre.cs @@ -1,35 +1,100 @@ -using System.Collections; +// List using System.Collections.Generic; +// GameObject + Vector3 using UnityEngine; +// Classe pour une topologie d'environnement en forme de carre public class Carre : Cube { - public Carre(GameObject c) : base(c) { - float scaleX = cube.transform.localScale.x; - float scaleY = cube.transform.localScale.y; - minX = -scaleX/2.0f;maxX = scaleX/2.0f; - minY = -scaleY/2.0f;maxY = scaleY/2.0f; + // Méthodes + + // la topologie en carre se construit à partir du visuel du carre + public Carre(GameObject c) : base(c) { minZ = 0.0f;maxZ = 0.0f; - } + } + + // retourne le point de la topologie que l'agent current pourrait heurter public override Observation detectEnv(Agent current) { + Vector3 side = goingToHit(current); + side = convertToValidOne(side); + Vector3 haut = new Vector3(0.0f,1.0f,0.0f); + Vector3 droite = new Vector3(1.0f,0.0f,0.0f); + if (side.x == minX || side.x == maxX) + return new Observation(new PointObstacle(side,haut,-haut),side-current.transform.position); + else + return new Observation(new PointObstacle(side,droite,-droite),side-current.transform.position); + } + + // 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; List<Vector3> p = new List<Vector3> { new Vector3(minX,pos.y,0.0f), new Vector3(maxX,pos.y,0.0f), new Vector3(pos.x,minY,0.0f), new Vector3(pos.x,maxY,0.0f) }; - 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]; - } + return p; + } + + // renvoie la position du point d'impact selon la direction unidirectionnel décrite par les composantes x, y et z + protected Vector3 basicAnswer(List<Vector3> p, float x, float y, float z) { + if(x < 0.0f) return p[0]; + else if(x > 0.0f) return p[1]; + else if(y < 0.0f) return p[2]; + else return p[3]; + } + + // renvoie la position du point d'impact entre l'environnement et l'agent current + protected Vector3 goingToHit(Agent current) { + + Vector3 pos = current.transform.position; + List<Vector3> p = getExtremPositions(current); + + float x = current.deplacement.x; float y = current.deplacement.y;float z = current.deplacement.z; + Vector3 res = basicAnswer(p,x,y,z); + if(onlyOneDirection(x,y,z)) return res; + + List<(Vector3,Vector3)> move = choiceMove(p,x,y,z); + Vector3 adjacentPoint, deplacement, currentRes; + + Vector3 adjacent; float adjacentDist, angle, oppose; + + for (int i=0;i<move.Count;i++) { + adjacentPoint = move[i].Item1; + deplacement = move[i].Item2; + adjacent = adjacentPoint-pos; + adjacentDist = Utils.normVector(adjacent); + angle = Vector3.Angle(current.deplacement,adjacent); + oppose = (float) Utils.tan(angle) * adjacentDist; + currentRes = adjacentPoint + deplacement * oppose; + res = bestOne(current,currentRes,res); + } + + return res; + } + + // retourne les points des côtés ainsi que le déplacement trivial induit par le déplacement en x, y et z + private List<(Vector3,Vector3)> choiceMove(List<Vector3> p, float x, float y,float z) { + List<(Vector3,Vector3)> res = new List<(Vector3,Vector3)>(); + if (x > 0.0f && y > 0.0f) { + res.Add((p[1],new Vector3(0.0f,1.0f,0.0f))); + res.Add((p[3],new Vector3(1.0f,0.0f,0.0f))); + } + else if(x > 0.0f && y < 0.0f) { + res.Add((p[1],new Vector3(0.0f,-1.0f,0.0f))); + res.Add((p[2],new Vector3(1.0f,0.0f,0.0f))); + } + else if(x < 0.0f && y > 0.0f) { + res.Add((p[0],new Vector3(0.0f,1.0f,0.0f))); + res.Add((p[3],new Vector3(-1.0f,0.0f,0.0f))); + } + else { + res.Add((p[0],new Vector3(0.0f,-1.0f,0.0f))); + res.Add((p[2],new Vector3(-1.0f,0.0f,0.0f))); } - return new Observation(new Obstacle(res),res-pos); + return res; } } diff --git a/src/Scripts/Environnement/Topologie/Cube.cs b/src/Scripts/Environnement/Topologie/Cube.cs index 230e02a7dcd6c01239426ba0f7e5b6b5fa5beb27..c3e5594d5cc729ee26fa2702cb78886e0d333767 100755 --- a/src/Scripts/Environnement/Topologie/Cube.cs +++ b/src/Scripts/Environnement/Topologie/Cube.cs @@ -1,19 +1,32 @@ -using System.Collections; +// List using System.Collections.Generic; +// Vector3 + GameObject using UnityEngine; +// Classe pour une topologie d'environnement en forme de cube public class Cube : Topologie { - public float minX; - public float maxX; - public float minY; - public float maxY; - public float minZ; - public float maxZ; - public GameObject cube; + // Attributs + // borne inférieur en x + protected float minX; + // borne maximum en x + protected float maxX; + // borne inférieur en y + protected float minY; + // borne maximum en y + protected float maxY; + // borne inférieur en z + protected float minZ; + // borne maximum en z + protected float maxZ; + // visuel du cube + protected GameObject cube; + // Méthodes + + // la topologie en cube se construit à partir du visuel du cube public Cube(GameObject c) : base() { cube = c; float scaleX = cube.transform.localScale.x; @@ -22,10 +35,18 @@ public class Cube : Topologie minX = -scaleX/2.0f;maxX = scaleX/2.0f; minY = -scaleY/2.0f;maxY = scaleY/2.0f; minZ = -scaleZ/2.0f;maxZ = scaleZ/2.0f; - } + + } + + // retourne la liste des limites du cube dans cet ordre [minX,maxX,minY,maxY,minZ,maxZ] + public List<float> getExtremums() { + return new List<float> {minX,maxX,minY,maxY,minZ,maxZ}; + } + // retourne le GameObject de la topologie public override GameObject getGameObject() { return cube;} + // 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 = new List<Vector3> @@ -43,26 +64,49 @@ public class Cube : Topologie res = p[i]; } } - return new Observation(new Obstacle(res),res-pos); - } - - protected List<List<Vector3>> getFaces() { - List<List<Vector3>> res = new List<List<Vector3>>(); - res.Add(new List<Vector3> {new Vector3(minX,minY,minZ),new Vector3(minX,maxY,minZ), new Vector3(minX,maxY,maxZ), new Vector3(minX,minY,maxZ)}); - res.Add(new List<Vector3> {new Vector3(maxX,minY,minZ),new Vector3(maxX,maxY,minZ), new Vector3(maxX,maxY,maxZ), new Vector3(maxX,minY,maxZ)}); - res.Add(new List<Vector3> {new Vector3(minX,minY,minZ),new Vector3(maxX,minY,minZ), new Vector3(maxX,minY,maxZ), new Vector3(minX,minY,maxZ)}); - res.Add(new List<Vector3> {new Vector3(minX,maxY,minZ),new Vector3(maxX,maxY,minZ), new Vector3(maxX,maxY,maxZ), new Vector3(minX,maxY,maxZ)}); - res.Add(new List<Vector3> {new Vector3(minX,minY,minZ),new Vector3(maxX,minY,minZ), new Vector3(maxX,maxY,minZ), new Vector3(minX,maxY,minZ)}); - res.Add(new List<Vector3> {new Vector3(minX,minY,maxZ),new Vector3(maxX,minY,maxZ), new Vector3(maxX,maxY,maxZ), new Vector3(minX,maxY,maxZ)}); - return res; + return new Observation(new PointObstacle(res),res-pos); } + // retourne une position valide dans la topologie public override Vector3 validPosition() { return Utils.randomVector(minX, maxX, minY, maxY, minZ, maxZ); } + // indique si la position est valide dans la topologie + public override bool isValidPosition(Vector3 pos) { + bool x = (minX <= pos.x) && (pos.x <= maxX); + bool y = (minY <= pos.y) && (pos.y <= maxY); + bool z = (minZ <= pos.z) && (pos.z <= maxZ); + return (x && y) && z; + } + + // retourne la distance maximale mesurable dans la topologie public override float getMaxDistance() { return Utils.normVector(minX,maxX,minY,maxY,minZ,maxZ); } + + // renvoie la position v de tel sorte à ce qu'elle soit valide dans le cube + protected Vector3 convertToValidOne(Vector3 v) { + Vector3 res = v; + if (v.x > maxX) res.x = maxX; + else if (v.x < minX) res.x = minX; + if (v.y > maxY) res.y = maxY; + else if (v.y < minY) res.y = minY; + if (v.z > maxZ) res.z = maxZ; + else if (v.z < minZ) res.z = minZ; + return res; + } + + // indique si le déplacement en x, y et z est unidirectionnel + protected bool onlyOneDirection(float x, float y, float z) { + return (x == 0.0f && z== 0.0f) || (y == 0.0f && z== 0.0f) || (x== 0.0f && y==0.0f); + } + + // indique quel position d'impact d'environnement entre p1 et p2 est le plus adapté pour l'agent current + protected Vector3 bestOne(Agent current,Vector3 p1,Vector3 p2) { + Vector3 pos = current.transform.position; + if(Utils.normVector(p1-pos) < Utils.normVector(p2-pos)) return p1; + else return p2; + } } diff --git a/src/Scripts/Environnement/Topologie/Topologie.cs b/src/Scripts/Environnement/Topologie/Topologie.cs index bfb4ecc6e96e715a26146d8fe2bed7abc8ba6e87..88a0deda82a13d98c44ba2a67c96fb25a38376ea 100755 --- a/src/Scripts/Environnement/Topologie/Topologie.cs +++ b/src/Scripts/Environnement/Topologie/Topologie.cs @@ -1,18 +1,28 @@ -using System.Collections; -using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe abstraite pour la topologie d'un environnement public abstract class Topologie { + // Méthodes + + // Constructeur abstrait d'une topologie d'un environnement public Topologie() {} + // retourne le GameObject de la topologie public abstract GameObject getGameObject(); + // retourne le point de la topologie que l'agent current pourrait heurter public abstract Observation detectEnv(Agent current); + // retourne une position valide dans la topologie public abstract Vector3 validPosition(); + // indique si la position est valide dans la topologie + public abstract bool isValidPosition(Vector3 pos); + + // retourne la distance maximale mesurable dans la topologie public abstract float getMaxDistance(); } diff --git a/src/Scripts/Perception/Perception.cs b/src/Scripts/Perception/Perception.cs index ce872e4552476670f39925c158d600dc0bf1a111..27edc07af6d4d816e1b1f66155b94a9aa0604a1b 100755 --- a/src/Scripts/Perception/Perception.cs +++ b/src/Scripts/Perception/Perception.cs @@ -1,22 +1,30 @@ -using System.Collections; using System.Collections.Generic; -using UnityEngine; +// Classe correspondant à une perception public class Perception { + // Attributs + + // L'agent propriétaire de la perception protected Agent proprietaire; + // Le rayon de vision protected float rayon; + // l'angle de vision protected float angle; + // Méthodes + + // Une perception se construit avec son proprietaire, de son rayon et angle de vue public Perception(Agent agent, float r, float a) { proprietaire = agent; rayon = r; angle = a; } + // retourne les observations effectuées par la perception public List<Observation> voir() { - return proprietaire.system.environnement.voisinage(proprietaire, rayon, angle); + return proprietaire.getSystem().getVoisinage(proprietaire, rayon, angle); } } diff --git a/src/Scripts/Perception/Perception180.cs b/src/Scripts/Perception/Perception180.cs index 8d77ca26229311bc6c6ec90b3b96a1cf062748e0..4c7ea00fba94ec262dd94d5f6e6214f5c33ab909 100755 --- a/src/Scripts/Perception/Perception180.cs +++ b/src/Scripts/Perception/Perception180.cs @@ -1,8 +1,6 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - +// Classe correspondant à une perception 180° public class Perception180 : Perception { + // Une perception se construit avec son proprietaire, de son rayon et angle de vue public Perception180(Agent agent, float r) : base(agent, r, 180.0f) {} } diff --git a/src/Scripts/Perception/Perception360.cs b/src/Scripts/Perception/Perception360.cs index 0c4878f7c70ff5fde5a33866f062cdb695d11193..a57dfadff11e9adf3389cb2d21bb2f23b76c15da 100755 --- a/src/Scripts/Perception/Perception360.cs +++ b/src/Scripts/Perception/Perception360.cs @@ -1,10 +1,7 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - +// Classe correspondant à une perception 360° public class Perception360 : Perception { - + // Une perception se construit avec son proprietaire, de son rayon et angle de vue public Perception360(Agent agent, float r) : base(agent, r, 360.0f) {} } diff --git a/src/Scripts/Perception/Perception90.cs b/src/Scripts/Perception/Perception90.cs index 237e5ab0fae7e95e6a210290136068c097ec70c2..131d7cbffcd00803861ffc9fab76991557e8ce17 100755 --- a/src/Scripts/Perception/Perception90.cs +++ b/src/Scripts/Perception/Perception90.cs @@ -1,8 +1,6 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - +// Classe correspondant à une perception 90° public class Perception90 : Perception { + // Une perception se construit avec son proprietaire, de son rayon et angle de vue public Perception90(Agent agent, float r) : base(agent, r, 90.0f) {} } diff --git a/src/Scripts/SMA.cs b/src/Scripts/SMA.cs index 43679786129334e7c979b5796baa7513aa809acc..870572bef27ee9ac8d2e97c11d531c5eaad4c3a7 100755 --- a/src/Scripts/SMA.cs +++ b/src/Scripts/SMA.cs @@ -1,48 +1,219 @@ -using System.Collections; -using System.Collections.Generic; +// pour le Monobehaviour + Vector3 using UnityEngine; +// pour utiliser List +using System.Collections.Generic; +// Classe correspondant au Système public class SMA : MonoBehaviour { - public List<Agent> agents; - public Environnement environnement; - public int population = 80; + + // Attributs + + // GameObject donnant la forme aux Agents public GameObject boid; + + // Environnement prédéfini + //public GameObject environnement; + + // Liste des agents du système + private List<Agent> agents = new List<Agent>(); + // Environnement du système + private Environnement env; + + // Effectif de la population du système + public int population = 1; + private int oldPopulation = 1; + + // Booléen vérifiant si le système est en trois dimensions public bool _3D = true; private bool _old3D = true; - public int angle = 180; + // Angle de vision des agents du système + public float angle = 180.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; + + // Vitesse de la simulation + public float speedSimulation = 1.0f; + + // test fonctionnement reynold + public bool AllReynolds = true; - // Start is called before the first frame update + + // Méthodes + + // renvoie l'environnement du système + public Environnement getEnvironnement() { + return env; + } + + // renvoie le voisinage de l'agent current dans l'environnement du système selon un rayon et un angle de vue + public List<Observation> getVoisinage(Agent current, float rayon, float angle) { + return env.getVoisinage(current,rayon,angle); + } + + // renvoie la liste des agents du système + public List<Agent> getAgents() { + return agents; + } + + // Start est appelé avant la première image affichée void Start() { createEnvironnement(); createAgents(); } - // Update is called once per frame + // associe l'environnement du système + private void createEnvironnement() { + env = GameObject.Find("Environnement").GetComponent<Environnement>(); + } + + // crée autant d'agents que l'effectif voulu par le système + private void createAgents() { + createAgents(population); + } + + // crée n agents dans le système + private void createAgents(int n) { + for(int i=0; i<n; i++) createAgent(); + } + + // crée un agent dans le système + 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 + private void createAgent(Vector3 pos) { + GameObject a; Agent agent; + a = Instantiate(boid, pos, Quaternion.identity,env.transform) as GameObject; + agent = a.GetComponent<Agent>(); + agents.Add(agent); + } + + // Update est appelée à chaque affichage void Update() { + changeDimension(); + changePopulation(); + } + + // Change la dimension de l'environnement du système pour correspondre au booléen _3D + private void changeDimension() { if (_3D != _old3D) { _old3D = _3D; - environnement.changeTo3D(_3D); - createAgents(); + resetAgents(); + } + } + + // supprime puis recrée les agents du système + private void resetAgents() { + removeAgents(); + createAgents(); + } + + // supprime les agents du système + private void removeAgents() { + agents.Clear(); + for(int i = 0; i<2; i++) { + _3D = !_3D; + env.notify(); } } - void createEnvironnement() { - //environnement = new Environnement(); - //environnement = gameObject.AddComponent<Environnement>() as Environnement; - environnement = GameObject.Find("Environnement").GetComponent<Environnement>(); + // verifie les changement sur les agents + private void changePopulation() { + changeBordConstant(); + changeEffectifPopulation(); + changeAngleRayonVision(); + //changeComportement(); + } + + // mise à jour si besoin de la constante kR (repulsion) du calcul de gestion de bords + private void changeBordConstant() { + if (kR != Bord.kR) Bord.kR = kR; + if (kT != TangenteBord2.kT) TangenteBord2.kT = kT; } - void createAgents() { - GameObject a;agents.Clear(); - for(int i=0; i<population; i++) { - a = Instantiate(boid, environnement.validPosition(), Quaternion.identity,environnement.transform) as GameObject; - agents.Add(a.GetComponent<Agent>()); + // 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(oldPopulation != population) { + if(oldPopulation < population) createAgents(population - oldPopulation); + else { + removeAgents(); + createAgents(population); + } + oldPopulation = population; } + } + // 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); + } + } + } } } \ No newline at end of file diff --git a/src/Scripts/Utils.cs b/src/Scripts/Utils.cs index 30282261223519054f0b35e321ac16dec7bf0130..d9afbecb8781961e4859f0a59ccbf409cb092cbd 100755 --- a/src/Scripts/Utils.cs +++ b/src/Scripts/Utils.cs @@ -1,22 +1,17 @@ +// Vector3 +using UnityEngine; +// Math using System; -using System.Collections; +// List using System.Collections.Generic; -using UnityEngine; +// Classe contenant des méthodes utiles à toutes les autres classes public class Utils { - // Start is called before the first frame update - void Start() - { - - } + // Méthodes - // Update is called once per frame - void Update() - { - - } + // renvoie un vecteur aleatoire normalisé public static Vector3 randomDirection() { float x = 0.0f; @@ -29,67 +24,64 @@ public class Utils else if (r == 1) y += 1.0f; else z += 1.0f; } - if(random(1,3) > 1) x = -x; - if(random(1,3) > 1) y = -y; - if(random(1,3) > 1) z = -z; + x = randomPosOrNeg(x); + y = randomPosOrNeg(y); + z = randomPosOrNeg(z); return normalizedVector(x,y,z); } + // retourne un vecteur normalisé selon un mouvement en x, y et z public static Vector3 normalizedVector(float x, float y, float z) { return (new Vector3(x,y,z)).normalized; } + // renvoie le vecteur moyennant la liste de vecteurs entrée en paramètre public static Vector3 meanVector(List<Vector3> vectors) { Vector3 res = Vector3.zero; for(int i = 0; i<vectors.Count; i++) { res += vectors[i]; } - res = res/vectors.Count; - return res.normalized; + if(vectors.Count != 0) res = res/vectors.Count; + return res; } + // renvoie un vecteur aleatoire avec des composantes x, y et z comprises respectivements entre minX et maxX, minY et maxY et minZ et maxZ public static Vector3 randomVector(float minX, float maxX, float minY, float maxY, float minZ, float maxZ) { return new Vector3(random(minX,maxX), random(minY,maxY), random(minZ,maxZ)); } + // renvoie la norme d'un vecteur public static float normVector(Vector3 v) { return (float) Math.Sqrt(Math.Pow(v.x,2) + Math.Pow(v.y,2) + Math.Pow(v.z,2)); } + // renvoie la norme d'un vecteur allant d'un point aux coordonnées (minX,minY,minZ) jusqu'à un point aux coordonnées (maxX,maxY,maxZ) public static float normVector(float minX, float maxX, float minY, float maxY, float minZ, float maxZ) { return (float) Math.Sqrt(Math.Pow(maxX-minX,2) + Math.Pow(maxY-minY,2) + Math.Pow(maxZ-minZ,2)); } - public static Vector3 noiseVector(Vector3 v, int nbBruit, float bruit ) { - int coin1; int coin2; float x = v.x; float y = v.y; float z = v.z; - for(int i=0;i<nbBruit;i++) { - coin1 = random(1,3); - coin2 = random(1,4); - if(coin2 == 1) { - if(coin1 == 1) x+=bruit; - else x-= bruit; - } - else if(coin2 == 2) { - if(coin1 == 1) y+=bruit; - else y-= bruit; - } - else { - if(coin1 == 1) z+=bruit; - else z-= bruit; - } - } - return normalizedVector(x,y,z); - } - + // renvoie la valeur absolue du flottant n public static float abs(float n) {return (float) Math.Sqrt(Math.Pow(n,2));} + // renvoie le flottant n à la puissance p + public static float pow(float n,int p) {return (float) Math.Pow(n,p);} + + // renvoie un flottant aléatoire entre min (inclus) et max (inclus) public static float random(float min, float max) {return UnityEngine.Random.Range(min,max);} + + // renvoie un entier aléatoire entre min (inclus) et max (exclus) public static int random(int min, int max) {return UnityEngine.Random.Range(min,max);} + // renvoie un flottant n aléatoirement positif ou négatif public static float randomPosOrNeg(float n) { return n * ((float) Math.Pow(-1,random(0,2))); } + + // renvoie un entier n aléatoirement positif ou négatif public static int randomPosOrNeg(int n) { return n * ((int) Math.Pow(-1,random(0,2))); } + // renvoie la tangente de l'angle angle + public static float tan(float angle) {return (float) Math.Tan(angle);} + } diff --git a/src/Scripts/Vision/Observation.cs b/src/Scripts/Vision/Observation.cs index bb1dc10f3d8938f7f679089f9b7d796e4d652021..4735ae52da7ab868e70c1705f9cbaee44cb19038 100755 --- a/src/Scripts/Vision/Observation.cs +++ b/src/Scripts/Vision/Observation.cs @@ -1,30 +1,24 @@ -using System.Collections; -using System.Collections.Generic; +// Vector3 using UnityEngine; +// Classe correspondant à une observation public class Observation { + // attributs + + // Objet qui a été observé public Visible objet; + // Le vecteur reliant l'observeur à l'observé public Vector3 distance; + // méthodes + // Une observation se construit à partir de l'observé et de la direction observeur-observé public Observation(Visible o, Vector3 d) { objet = o; distance = d; } - - // Start is called before the first frame update - void Start() - { - - } - - // Update is called once per frame - void Update() - { - - } } diff --git a/src/Scripts/Vision/Visible.cs b/src/Scripts/Vision/Visible.cs index 8b2a211f98402a7de51cfa70fdb7c22d203a3a59..13f012ec0b8f56e0535f35432cd02f520c29fab4 100755 --- a/src/Scripts/Vision/Visible.cs +++ b/src/Scripts/Vision/Visible.cs @@ -1,5 +1,7 @@ +// Interface pour les objets qui peuvent être vu public interface Visible { + // renvoie si l'objet visible est mobile ou non public bool isAlive(); } \ No newline at end of file