Live data from Hacker News

Coroutines make robot code easy

bvisness.me

71–80 of 127 posts

Re: Coroutines make robot code easy

#71
Oddly, the kids I mentored in FIRST loved the command/subsystem framework. I kept trying to convince them to do some procedural code to make things simpler (they had little experience coding, even for high school robotics kids), but command/subsystem was their comfort zone and they didn't want to leave it.

Re: Coroutines make robot code easy

#72
Coroutines are covered in Knuth's first volume. And, I confess, I think I went years thinking he was just describing method calls. Yes, they were method calls that had state attached, but that felt essentially like attaching the method to an object and calling it a day.

Seeing them make an odd resurgence in recent years has been awkward. I'm not entirely clear that they make things much more readable than alternatives. Reminds me of thinking continuations were amazing, when I saw some demos. Than I saw some attempts at using them in anger, and that rarely worked out that well.

Also to the point of the article, I love being "that guy" that points out that LISP having a very easy "code as data" path makes the concerns expressed over the "command" system basically go away. You can keep the code as, essentially:

    (DriveForward 0.5 48)
    (while (NotCarryingBall)
        (Grab)
        (pause 2)) 
    (DriveBackward -0.5 48)
    (Shoot)
With god knows how much bike shedding around how you want to write the loop there.

Of course, you could go further for the "pretty" code that you want by using conditions/restarts such that you could have:

    (DriveForward 0.5 48)
    (Grab)
    (DriveBackward -0.5 48)
    (Shoot)
And then show what happens if "Grab" is unsuccessful and define a restart that is basically "sleep, then try again." Could start plugging in new restart ideas such as "turn a little, then try again." All without changing that core loop.

Re: Coroutines make robot code easy

#73

I think that developers have minimal scheduling primitives available to them, to schedule complicated work, in the order and timings you want it to have. I don't like hardcoding functions in coroutine pipelines. Depending on the ordering of your pipeline, you might have to create things and then refer to them, because of the forward reference problem. Here's my stackoverflow question for what I'm getting at: https://…

> I would like to build a rich "process api" that can fork, merge, pause, yield, yield until, drop while, synchronize, wait (latch), react according to events. I feel every distributed systems builds this again and again. Years ago I attempted to build an experimental language with first-class resumable functions. Every function can be invoked by the caller through a special reference type called "quaint". The caller…

Ha. Amazing! Someone actually implemented a variant of COME FROM of C-INTERCAL infamy in another language.

And moreover made it a reasonable and readable variant!

Re: Coroutines make robot code easy

#75
post #30

I don’t understand why doing this with normal Java is difficult. Just have a list of objectives. Each objective is a class. The autonomous loop picks the next objective from the list and each tick, asks if it has finished, if so get the next objective and so on. All the details about the actual commands to complete the objective and checking the state and so on go into the classes. If no more objectives in the list,…

It's addressed in the article... you sort of end up with a meta-programming language when you do that, which ends up being less ergonomic than your initial code. Then you have questions like how do you do control flow within that list? Can you branch or loop over multiple objectives? If you add support for that you end up even closer to a meta programming language, with worse syntax than if things were directly in the base language.

Re: Coroutines make robot code easy

#76
post #61

Earlier quoted context omitted.

> According to who? It is very natural to anyone making a GUI or anything interactive for the firs time. The people that do not make GUIs but apps with complex behaviours. Callbacks are nice and simple. Callbacks calling callbacks calling callbacks calling callbacks (because of one of worst ideas in programming ever, function coloring) stops being simple. Async/await is just a patch over that ugliness for languages t…

The people that do not make GUIs but apps with complex behaviours. I don't think there is a difference here. Callbacks are nice and simple. Callbacks calling callbacks calling callbacks calling callbacks (because of one of worst ideas in programming ever, function coloring) stops being simple. Async/await is just a patch over that ugliness for languages that can't do any better easily I agree with all of this, but th…

> I think the way to go is to have a queue of events/inputs and use that because the ordering and debugging is much better and you don't get the same web of jumping to different parts of the execution.

If you just have stream of events that need to be decided upon in order you're in a very happy place; complexity strikes when you want to run handlers for them in parallel to cut on latency, and those handles also need to do multiple things that can be done asynchronously to cut on latency.

Message passing works well here, you can just send a bunch of requests to various components then just wait for each at the moment they are needed; async/await is essentially a very bastardised version of it (and usually stuck in single thread in most implementations so no parallel computing)

Re: Coroutines make robot code easy

#77
post #5
post #2

If you want to make it easy for high schoolers, just don't use java in the first place...

The only officially supported languages for the competition are C++, Java, and LabVIEW. When those are your educational options...you stick with Java. (We've now switched to Lua, integrated with the official C++, but it's a lot more work behind the scenes.)

Why not Python? I thought that was the popular language for learning these days. My son gets quite a bit of Python in school.

Re: Coroutines make robot code easy

#78
post #77
post #5

Earlier quoted context omitted.

The only officially supported languages for the competition are C++, Java, and LabVIEW. When those are your educational options...you stick with Java. (We've now switched to Lua, integrated with the official C++, but it's a lot more work behind the scenes.)

Why not Python? I thought that was the popular language for learning these days. My son gets quite a bit of Python in school.

Python is slated to become a choice for the 2024 season: https://wpilib.org/blog/bringing-python-to-frc

Re: Coroutines make robot code easy

#79
post #2

If you want to make it easy for high schoolers, just don't use java in the first place...

We learned borland pascal and borland c in high school. Java is perfectly fine.

I went to a university where Java was the main language for most of the basic programming courses

I've been making a living coding in Java for 10+ years

I'm a strong believer in types etc etc

I still don't think Java is a great language to teach programming lol

too much pointless boilerplate and abstraction to achieve the simplest things

lots of footguns and objectively bad standard practices built into the language and the native libraries

to me Python and Kotlin seem like probably better choices (though they too have massive flaws)

Re: Coroutines make robot code easy

#80

People always say that coroutines make code easier to understand, but I've always found normal asynchronous code with callbacks much easier to understand. They're equivalent except that asynchronous callbacks is what actually happens and you have clear control and visibility on how control flow moves.

The coroutine approach shines for complex business-logic.

Consider this example algorithm, of several async steps,

1. Download a file into memory

2. Email a link to a review web page.

3. Wait for the user to review.

4. Upload the file to a partner.

5. Update a database.

You could implement this as callbacks. Callback from each step leads to the next being triggered. Downside - your business logic is spread across all the callbacks. You could mitigate this somewhat by defining a class with one method for each step, with those methods being defined in the same visual order as the algorithm. Then have each callbacks call a method. (The article shows something different but similar with its Command autoCommand pattern.)

Tricks like this only go so far. Imagine if the reviewer user had a choice of pressing 'approve' or 'reject' on the webserver interface, with the algorithm changing depending on their answer. How do you now represent the business logic so the programmer can follow it?

Such changes are easy in coroutines. Here is the algorithm with that variation in coroutine code,

    async def review(review_id, url):
      file_content = await download_large_file(url, review_id)
      ws_review_id = await create_webserver_review_page(file_content)
      await email_the_user(ws_review_id)
      result = await get_webserver_user_response(ws_review_id)
      if result: 
        await upload_to_partner(file_content)
      else:
        await alert_failure(review_id, file_content)
      await update_database(review_id, ws_review_id, result)
You state that callback code gives you easy visibility to what actually happens - yes, they do. When you read callback code, it is natural to follow business-logic to system calls. Coroutine tends towards code of layered business-logic and abstraction.
Post reply on HN