maarten-pennings / Lego-Mindstorms

Hints, tips, and tricks for the LEGO Mindstorms products (RCX, NXT, EV3, Robot Inventor).
87 stars 14 forks source link

Example program for Gelo - using generators as coroutines #1

Open dlech opened 3 years ago

dlech commented 3 years ago

Hi Maarten, I like the work you are doing with generators and iterators recently. I would like to share a program that I have been working on.

https://gist.github.com/dlech/973714729f33b67092b736f541820233

Here are some of the more interesting points:

  1. I'm using zip (built-in function) and zip_longest (from itertools in Python standard library) as some fundamental operators for running generators in parallel. This are somewhat analogous to Promise.race() and Promise.all() in JavaScript or asyncio.wait() with return_when=FIRST_COMPLETED and return_when=ALL_COMPLETED respectively in Python.

    In the future, I would like to simplify and improve these a bit. For zip, it should be modified to call generator.close() on all unfinished generators to cancel them after the first one completes. This will "cancel" them, which is useful for things like stopping motors or sound playback. zip_longest() could be simplified to not collect and return the values yielded by the generators.

  2. It is using the low level hub API to create new classes, like the Motor class that have generator versions of the methods.

  3. Along the same lines, it implements a new Timer class that has millisecond resolution since the one from LEGO only has 1 second resolution.

  4. There is a run_tasks() function that acts kind of like zip_longest(), but it takes generator functions instead of the generator returned by a generator function as arguments. This is intended for the most high-level tasks of a program. Instead of running things as fast as possible, it tries to run everything in a 10 millisecond loop. My experience has been that this time works well for most control/feedback loops. But this means timers will only have a 10 ms resolution (unless you override the default interval).