Comment configurer un moteur supplémentaire en mode "wheel" dans un Poppy torso?

J’ai un Poppy torso qui possède un MX-28 supplémentaire qui doit tourner de plusieurs tours…
J’ai instancié un poppy torso custom avec import_json :

from pypot.robot import from_json
poppy = from_json(“path_to_custom_json_file”)

jusque là tout va bien et je vois bien le moteur supplémentaire. Mais je voudrais le faire passer en mode “wheel” pour pouvoir lui faire faire plusiers tours, ce qui se fait dans la doc dynamixel “low level” avec la méthode set_wheel_mode(motor_ids) de la classe pypot.dynamixel.DxlIO → ma question est “comment je fais pour récupérer un objet DxlIO avec mon objet poppy” ?

C’est un peu caché, il faudra que je trouve une manière plus élégante de donner accès. Pour l’instant tu peux faire :

dxl_io = poppy._controllers[0].io

Merci Pierre je vais essayer cela tout de suite… j’imagine que ça pourra devenir une property par la suite ?

Oui absolument. On pourrait tout simplement imaginer poppy.dxl_ios pour accéder à la liste des connection dynamixel.

Alors ça marche impect !
Par contre pour régler la vitesse de rotation du moteur en mode “wheel”, j’ai l’impression que dxl_io.set_moving_speed({numéro_moteur: vitesse_degré_par-seconde}) n’est pas pris en compte en temps réel ?
Donc ma question est : comment peut-on fixer le sens de rotation et la vitesse avec le low-level Dynamixel ?

Cela devrait fonctionner pourtant ! C’est la bonne méthode pour contrôler un moteur en wheel mode. Nous n’avons pas beaucoup d’expériences là dessus, je n’ai passé que quelques minutes simplement pour tester que cela “fonctionnait”.

La méthode set_moving_speed prend une vitesse en degré par seconde et le signe permet de choisir le sens de rotation. Précision importante c’est une vitesse maximale que tu demandes.

OK pour l’info sur le signe.
Mais ce qui m’interpelle c’est que quand j’éxécute ça avec un mX-28 numéroté 10 :

print(“moving_speed before:”,dxl_io.get_moving_speed((10,))[0])
dxl_io.set_moving_speed({10: 100})
print(“immediately after :”,dxl_io.get_moving_speed((10,))[0])
time.sleep(1)
print(“one seconde later :”,dxl_io.get_moving_speed((10,))[0])

j’obtient :

moving_speed before: 7.524
immediately after : 99.864
one seconde later : 7.524

Et du coup, quand je passe le moteur en mode “wheel” avec set_control_mode({10 : “wheel”}) il tourne tout doucement ??? Any idea ?

Étrange, je ne suis pas sûr de comprendre.

Est-ce que ton moteur 10 est aussi présent dans le fichier de config ? Autrement dit, est-ce qu’il est aussi dans la liste poppy.motors ? Auquel cas il y a sans doute un problème de boucle de synchronisation qui ré-écrit ta vitesse à une autre valeur.

Oui, tout à, fait ce moteur est mentionné dans le fichier json : effectivement tout se passe comme si la bloucle de synchro le remettait à jour avec sa config à elle… je n’avais pas pensé à cela.
Je vais faire l’essai en enlevant ce moteur de la config json… merci de ta réponse.

Ca marche, tiens moi au courant si c’était bien ça !

bon ça y est, ça marche : il faut effectivement ne pas déclarer dans le json le motor que l’on veut piloter par dxlio.

Voici le détail d’une manip test que j’ai faite avec une Raspberry pi 2 et 2 moteurs : le moteur numéro 10 est déclaré dans le json et le moteur numéro 11 (celui avec un étrier plastique gris) est piloté low-level par dxlio.

Le json est :

 {
  "controllers": {
    "upper_body_controller": {
      "sync_read": true,
      "attached_motors": ["one"],
      "port": "auto"
    }
  },
  "motorgroups": {"one": ["m11"]},
  "motors": {
    "m11": {
      "offset": 0.0,
      "type": "MX-28",
      "id": 11,
      "angle_limit": [-180,180],
      "orientation": "direct"
    }      
  }
}

donc uniquement le moteur 10 !!!

J’ai fait un jupyter notebook pour faire tourner le moteur en mode “wheel” à 80 degrés par seconde, et si je tente de l’empêcher de tourner en bloquant l’étrier en plastique, la charge du moteur augmente et on sort de la boucle avec le moteur arrété et non compliant :

from __future__ import print_function
import time, 
import pypot
pypot.__version__
'2.11.7'
from pypot.robot import from_json
jsonFile = "wheel.json"
poppy = from_json(jsonFile)
poppy.motors
[<DxlMotor name=m11 id=11 pos=-37.49>]
dxl_io = poppy._controllers[0].io     # LA ligne qui permet d'attraper le contrôleur dxl
dxl_io.scan(range(15))
[10, 11]
dxl_io.set_max_torque({10: 90})
dxl_io.enable_torque((10,))
dxl_io.set_moving_speed({10: 100})        # 100 degrés par seconde
dxl_io.set_control_mode({10: "wheel"})    # fait tourner le moteur en continu
                                          # tant qu'on ne met pas la vitesse à zéro...
dxl_io.set_moving_speed({10: 0})           # ici le moteur s'arrête !
#
# moteur tourne en free wheel et s'arrête quand la charge devient supérieure
# à un pourcentage donné (entre 0 et 100%) de la charge de démarrage...
#
import time
motor   = 10   # motor number
percent = 10   # percent [0-100] of startLoad that will trigger a "motor stop"

dxl_io.enable_torque((motor,))
dxl_io.set_control_mode({motor: "wheel"})  # make motor go in "wheel" mode to make many turns
dxl_io.set_moving_speed({motor: 80})     # rotation speed in degree/seconde
time.sleep(0.2)
startLoad = abs(dxl_io.get_present_load((motor,))[0])
print("startLoad:", startLoad)
while True:
    load = abs(dxl_io.get_present_load((10,))[0])
    print(load, end=" ")
    if load - startLoad > startLoad*(1 + percent/100) : 
        dxl_io.set_moving_speed({motor: 0})    # stop the motor and leave the loop
        time.sleep(0.1)
        break
    time.sleep(.5)
print("\n out with startLoad:{} and load:{}".format(startLoad,load))
startLoad: 4.4
3.7 4.4 3.7 4.4 4.4 3.7 7.5 28.3 
 out with startLoad:4.4 and load:28.3
poppy.close()

Et hop !

3 Likes

Super merci !

J’essaierai de regarder si cela peut être intégré facilement directement dans le json.

Est-ce qu’on peut commander ou récupérer les enregistrements d’un moteur en mode “wheel mode” depuis l’API REST? Car dans cet exemple le moteur n’est pas déclaré dans la configuration donc je ne sait pas comment le commander depuis l’API…