def test_dériver(self): a = Antenne() self.assertEqual(a.position, Vec3(1, 2, 3)) a.activer() self.assertNotEqual(a.position, Vec3(1, 2, 3)) print(a.position)
def test_fonctionnement(self): a = Antenne() for i in range(10): a.activer() a.objectif = Vec3(-4, 8, -9) while a.objectif != a.position: a.activer() a.objectif = None for i in range(10): a.activer() self.assertNotEqual(a.position, Vec3(1, 2, 3)) print(a)
def test_aligner(self): a = Antenne() o = Vec3(10.0, -200.0, 3000.0) a.objectif = o while a.position != o: a.activer() print(a.position)
class Gestionnaire(metaclass=MétaActeur): # L'objectif visé par l'Antenne ne peut pas être représenté par une seule # et même donnée système. Sinon, le Gestionnaire ne sert à rien : une # mise-à-jour de l'objectif se ferait via le cadriciel sans passer par le # Gestionnaire. cible = recv_msg( "Commande de position à atteindre par l'antenne, ou 'None'") objectif = send_msg("Position à atteindre par l'antenne, ou 'None'") état = send_msg("État de l'Antenne gérée", État()) position = recv_msg("Position publiée par l'Antenne", Vec3(0, 0, 0)) _TOLÉRANCE = 10.0 _PREMIER_ALIGNEMENT = 5 _CONSERVATION = 3 def __init__(self): self._compteur = 0 @entry(cible) def commander(self): self.objectif = self.cible self.état.est_aligné = False if self.objectif is None: self.état.statut = StatutAlignement.REPOS else: self.état.statut = StatutAlignement.EN_COURS @entry(position) def maj_position(self): self.état.position = self.position if self.objectif is not None: d = self.état_antenne.position.distance(self.objectif) if d <= Gestionnaire._TOLÉRANCE: self.état.est_aligné = True self._compteur = 0 else: self._compteur += 1 if ((self.état.est_aligné and self._compteur > Gestionnaire._CONSERVATION) or (not self.état.est_aligné and self._compteur > Gestionnaire._PREMIER_ALIGNEMENT)): self._état.est_aligné = False self._objectif = None
def activer(self): """Activation périodique """ if self.état is StatutAlignement.ACTIF: # Convergence écart = self.objectif - self.position écart.x = self._converger(écart.x) écart.y = self._converger(écart.y) écart.z = self._converger(écart.z) self.position = self.objectif - écart else: # Dérive delta = Vec3(x=self._dériver(), y=self._dériver(), z=self._dériver()) self.position += delta print("Position : {}".format(self.position))
class Antenne(metaclass=MétaActeur): """Simulateur d'une antenne L'Équipement émet périodiquement un message de statut. L'absence répétée d'une telle émission peut être un indicateur de son non-fonctionnement. """ _PAS = 1.45 objectif = recv_msg("Position à atteindre, ou 'None' sinon") position = send_msg("Direction actuelle de l'Antenne", Vec3(1, 2, 3)) tic = recv_msg("Heure, en nombre de tics d'horloge", 0) def __init__(self): """Meilleur constructeur de la terre """ pass def __str__(self): retour = "Antenne(objectif={}, position={})".format( self.objectif, self.position) return retour @property def état(self): """Synthèse """ retour = StatutAlignement.ACTIF if self.objectif is None: retour = StatutAlignement.REPOS return retour @entry(tic) def activer(self): """Activation périodique """ if self.état is StatutAlignement.ACTIF: # Convergence écart = self.objectif - self.position écart.x = self._converger(écart.x) écart.y = self._converger(écart.y) écart.z = self._converger(écart.z) self.position = self.objectif - écart else: # Dérive delta = Vec3(x=self._dériver(), y=self._dériver(), z=self._dériver()) self.position += delta print("Position : {}".format(self.position)) def _converger(self, valeur): """Assure la convergence vers 0 en respectant un nombre maximal de pas """ if -Antenne._PAS <= valeur <= Antenne._PAS: retour = 0.0 elif valeur >= 0: retour = math.pow(valeur, 1 / Antenne._PAS) else: retour = -math.pow(-valeur, 1 / Antenne._PAS) return retour def _dériver(self): retour = random.uniform(-Antenne._PAS, Antenne._PAS) return retour
def __init__(self): self.position = Vec3(0, 0, 0) self.est_aligné = False self.statut = StatutAlignement.REPOS