···44444545Cette technique est particulièrement adaptée au problèmes qui se prêtent à une modélisation type "jeu vidéo", dans le sens où l'agent représente le personnage-joueur, et le coût un certain score, qui est condition de victoire ou défaite.
46464747-En robotique, une approche similaire explore l'espace d'action (en général un courant à envoyer aux moteurs) de façon à optimiser le coût.
4747+En robotique, une approche similaire explore l'espace d'action (en général un courant à envoyer aux moteurs) de façon à optimiser le coût.
48484949En robotique, on a des correspondances claires pour ces quatres notions:
5050···139139140140Expérimentalement, on sait que des tendances "tricheuses" émergent facilement pendant l'entraînement #refneeded: l'agent découvre des séries d'actions qui causent un bug avantageux vis à vis du coût associé, soit parce qu'il y a un bug dans le calcul de l'état de l'environnement post-action, soit parce que la fonction coût ne prend pas suffisemment bien en compte toutes les possibilités de l'environnement (autrement dit, il manque de contraintes).
141141142142-Dans le cas de la robotique, cela arrive particulièrement souvent, et il faut donc un simulateur qui soit suffisamment réaliste.
142142+Dans le cas de la robotique, cela arrive particulièrement souvent, et il faut donc un simulateur qui soit suffisamment réaliste.
143143144144==== Sous-spécification de la fonction coût
145145···529529530530$
531531 argmax_(Pi') & exp_((s, a) in cal(S)) L(s, a, Pi, Pi', R) \
532532- "s.c." & top
532532+ "s.c." & top
533533$
534534535535==== Avec pénalité _(PPO-Penalty)_
+105-19
rapport/gz-unitree.typ
···235235 )[SDK d'Unitree]
236236237237238238- node(name: <gzclock>, (1, 5), subtitled(`::TickHandler`, [topic Gazebo `/clock`]))
239239- node(name: <gzimu>, (2, 5), subtitled(`::IMUHandler`, [topic Gazebo `/imu`]))
238238+ node(name: <gzclock>, (1, 5), subtitled(
239239+ `::TickHandler`,
240240+ [topic Gazebo `/clock`],
241241+ ))
242242+ node(name: <gzimu>, (2, 5), subtitled(
243243+ `::IMUHandler`,
244244+ [topic Gazebo `/imu`],
245245+ ))
240246 node(name: <lowstate>, (1, 2), `::LowStateWriter`)
241247 node(name: <lowcmd>, (2, 2), `::CmdHandler`)
242248 node(name: <statebuf>, (1, 3), subtitled("State buffer", `statebuf`))
243249 node(name: <cmdbuf>, (2, 3), subtitled("Commands buffer", `cmdbuf`))
244244- group((<lowstate>, <lowcmd>, <statebuf>, <cmdbuf>, <gzclock>, <gzimu>))[Plugin internals]
250250+ group((
251251+ <lowstate>,
252252+ <lowcmd>,
253253+ <statebuf>,
254254+ <cmdbuf>,
255255+ <gzclock>,
256256+ <gzimu>,
257257+ ))[Plugin internals]
245258246259 node(name: <policy>, (0, -1), $Pi$)
247260···275288 edge(<publisher>, "<->", <lowstate>)[`std::bind`]
276289 edge(<subscriber>, "<->", <lowcmd>)[`std::bind`]
277290 edge(<configure>, "d,d,d,r", <gzclock>, "->", label-pos: 85%)[démarre]
278278- edge(<configure>, "d,d", (0, 3.75), "r,r", <gzimu>, "->", label-pos: 75%)[démarre]
291291+ edge(
292292+ <configure>,
293293+ "d,d",
294294+ (0, 3.75),
295295+ "r,r",
296296+ <gzimu>,
297297+ "->",
298298+ label-pos: 75%,
299299+ )[démarre]
279300})
280301281302On commence par instancier un contrôleur dans le domaine DDS n°1, sur l'interface réseau `lo`#footnote[interface dite "loopback", qui est locale à l'ordinateur: ici, le simulateur et la politique de contrôle tournent sur la même machine, donc les messages DDS n'ont pas besoin de "sortir" de celle-ci]
···551572 [Etat de chaque moteur],
552573 `gz::sim::Model(…)→joints`,
553574554554- ` .mode`, ${0, 1}$, [$0$ pour "Brake" et $1$ pour "FOC#footnote[Field-Oriented Control]", deux modes de contrôle pour le moteur électrique], [0],
575575+ ` .mode`,
576576+ ${0, 1}$,
577577+ [$0$ pour "Brake" et $1$ pour "FOC#footnote[Field-Oriented Control]", deux modes de contrôle pour le moteur électrique],
578578+ [0],
555579556580 ` .q`,
557581 $RR quad ("rad")$,
···586610587611#architecture([Phase d'envoi de l'état], {
588612 edge(<preupdate>, "d", <statebuf.west>, "->", label-pos: 70%)[(1A): Joints]
589589- edge(<gz.west>, (-0.75, 1.5), (-0.75, 6), (2,6), <gzimu>, "@..>", label-pos: 25%)[(1D)]
590590- edge(<gz.east>, (0.5, 1.5), (0.5, 5), <gzclock.west>, "@..>", label-pos: 25%)[(1C)]
613613+ edge(
614614+ <gz.west>,
615615+ (-0.75, 1.5),
616616+ (-0.75, 6),
617617+ (2, 6),
618618+ <gzimu>,
619619+ "@..>",
620620+ label-pos: 25%,
621621+ )[(1D)]
622622+ edge(
623623+ <gz.east>,
624624+ (0.5, 1.5),
625625+ (0.5, 5),
626626+ <gzclock.west>,
627627+ "@..>",
628628+ label-pos: 25%,
629629+ )[(1C)]
591630 // edge(<gz>, "d,d,d,d,d,r", <gzclock>, "@..>", label-pos: 30%)[(1D)]
592631 // edge(<gz>, "d,d,d,d,d,r,r", <gzimu>, "@..>", label-pos: 30%)[(1C)]
593632 edge(<statebuf>, "@->", <lowstate>)[(1B)]
594633 edge(<lowstate>, "->", <publisher>)[(2)]
595634 edge(<publisher>, "->", (1, 0))[(3)]
596635 edge(<policy>, (1, -1), (1, 0), "<--@", label-pos: 20%)[(4) subscription]
597597- edge(<gzclock>, "@->", <statebuf>, label-pos: 30%, label-side: right)[(2C): Tick]
598598- edge(<gzimu.west>, (1.5, 5), (1.5, 3), <statebuf.east>, "->", label-pos: 40%)[(2D): IMU]
636636+ edge(
637637+ <gzclock>,
638638+ "@->",
639639+ <statebuf>,
640640+ label-pos: 30%,
641641+ label-side: right,
642642+ )[(2C): Tick]
643643+ edge(
644644+ <gzimu.west>,
645645+ (1.5, 5),
646646+ (1.5, 3),
647647+ <statebuf.east>,
648648+ "->",
649649+ label-pos: 40%,
650650+ )[(2D): IMU]
599651 edge(
600652 <policy>,
601653 (1, -1),
···631683Un cycle correspond donc à cinq boucles indépendantes, représentées ci-après:
632684633685/ Bleu: Simulation, qui doit englober l'entièreté d'un cycle
634634-/ Rouge: `ChannelPublisher`
635635-/ Rose: Politique $Pi$
636636-/ Vert: Mise à jour de l'IMU
637637-/ Orange: Mise à jour du tick de simulation
686686+/ Rouge: `ChannelPublisher`
687687+/ Rose: Politique $Pi$
688688+/ Vert: Mise à jour de l'IMU
689689+/ Orange: Mise à jour du tick de simulation
638690639691#architecture(
640692 [Cycle complet. Un cycle commence avec la flèche "update" partant de `::PreUpdate`],
···692744 policy-edge("update", <lowcmd>, "->", <cmdbuf>)
693745694746 // imu loop
695695- imu-edge("update", <gzimu>, (1.5, 5), (1.5, 3), <statebuf>, "->", label-pos: 45%)
696696- for _ in range(2) { // XXX hack to increase thickness of dotted line
697697- imu-edge("", <gz.west>, (-0.75, 1.5), (-0.75, 6), (2,6), <gzimu>, "@..>", label-pos: 45%)
747747+ imu-edge(
748748+ "update",
749749+ <gzimu>,
750750+ (1.5, 5),
751751+ (1.5, 3),
752752+ <statebuf>,
753753+ "->",
754754+ label-pos: 45%,
755755+ )
756756+ for _ in range(2) {
757757+ // XXX hack to increase thickness of dotted line
758758+ imu-edge(
759759+ "",
760760+ <gz.west>,
761761+ (-0.75, 1.5),
762762+ (-0.75, 6),
763763+ (2, 6),
764764+ <gzimu>,
765765+ "@..>",
766766+ label-pos: 45%,
767767+ )
698768 }
699769700770 // clock loop
701701- clock-edge("update", <gzclock>, <statebuf>, "->", label-pos: 25%, label-side: right)
702702- for _ in range(3) { // XXX hack to increase thickness of dotted line
703703- clock-edge("", <gz.east>, (0.5, 1.5), (0.5, 5), <gzclock.west>, "@..>", label-pos: 45%)
771771+ clock-edge(
772772+ "update",
773773+ <gzclock>,
774774+ <statebuf>,
775775+ "->",
776776+ label-pos: 25%,
777777+ label-side: right,
778778+ )
779779+ for _ in range(3) {
780780+ // XXX hack to increase thickness of dotted line
781781+ clock-edge(
782782+ "",
783783+ <gz.east>,
784784+ (0.5, 1.5),
785785+ (0.5, 5),
786786+ <gzclock.west>,
787787+ "@..>",
788788+ label-pos: 45%,
789789+ )
704790 }
705791 },
706792)