Live data from Hacker News

Coroutines make robot code easy

bvisness.me

121–127 of 127 posts

Re: Coroutines make robot code easy

#121

Yes. The callback is not a natural construct (i.e. it does not map well to our intuitive understanding of X is doing something while Y is doing something else). I'm annoyed when coroutines are reserved for use only in high performance, c10k-type of situations. For example, the KJ library's doc says: "Because of this, fibers should not be used just to make code look nice (C++20's co_await, described below, is a better…

Yes. What question are you answering 'yes' to? The callback is not a natural construct According to who? It is very natural to anyone making a GUI or anything interactive for the firs time. Eventually I would try to move people to queueing up events and handling them all at the same time so that the order is easier to debug. Coroutines are the latest silver bullet syndrome. Fundamentally you still need to synchronize…

The callbacks (as in a chain of callbacks) are not natural to a beginner, like a student trying to program a robot. For a GUI, where you set up a callback in response to user input, it is also easy to understand because the program's control flow does not progress as a chain of callbacks.

The input-update-output loop is fine, but you cannot easily combine and nest such loops. For example, in a robot you may have a speed control inner loop, then a path following loop and on top of that a high-level behavior loop. Nesting one inside the others you end up with a hand-baked implementation of a coroutine.

Re: Coroutines make robot code easy

#122

As always when this topic comes up, I have to plug Ceu[0] (formerly Céu) and the programming paradigm it represents. It doesn't use coroutines but synchronous concurrency. On top of that it's a reactive language: // an external input event channel input int KEY; // par/or concurrently executes two // or more blocks (called "trails") // if one of them terminates, the // other trails are aborted. // Compare: par/and, w…

Right, imperative synchronous programming simplifies real time processing a lot.

Somehow it does not get the attention it should, which is IMHO due to the fact that it is not available in common programming languages.

This is why I tried to create DSLs for C and Swift so that more people could potentially play around with that.

https://github.com/frameworklabs/proto_activities

Re: Coroutines make robot code easy

#123
post #117
post #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 alternative…

With these examples I think the author would still be stuck with stepping through the state machines with the students. Unless what you wrote would allow for the "autonomousPeriodic function to keep ticking" another way?

Apologies for not making that more explicit. My point was that that isn't necessarily code, but also data. Literally, you can turn that into a list and instead of evaluating it with the standard runtime, you can send it to another place that turns it into the "command" style from the example java.

You can /kind/ of do this with java, of course. Just make sure to not use "new FooCommand" and instead change the "foo" function to return a the command object. No reason that couldn't be done; but, and this is the big difference, it requires building a ton of scaffolding in the java program to support both ideas at the same time. In lisp, it is fairly easy to wrap in a macro. Still somewhat magical, I suppose, but no more so than the rest of the compilation/build process.

That make sense? I'm somewhat interested in this, so more than happy to try and do a blog post on the idea, if that would help.

Re: Coroutines make robot code easy

#124

Coroutines (or the concept of saving context to come back to) is already heavily explored in robotics in recent years. Behaviour Trees [1] approximates what coroutines do in system level controlled ticks mainly to avoid pitfalls of state machines. They are also extensively used in game development too. ROS2 have Nav2[2] package which is based on BTCpp library [3]. Not surprisingly BTCpp library uses boost coroutines…

Given your expertise, why use behaviour trees when coroutines are available? What value do they provide in languages like javascript where generators work well?

I'm writing a game that uses both behavior trees and coroutines (via C# generators), and I have found that they are not quite interchangeable.

The main thing is that the execution model is different. I think of the behavior tree as being evaluated from the root on every tick, whereas with coroutines, you are moving linearly through a sequence of steps, with interruptions. When you resume a coroutine, it picks up exactly where it left off. The program does not attempt to re-evaluate any preceding code in the coroutine in order to determine whether it's still the right thing to be executing. By contrast, a behavior tree will stop in the middle of a task if some logic higher up in the tree decides that you need to be on a different branch.

What we end up doing is composing behavior trees with coroutines as leaf nodes. It works quite nicely, although I wish there was a way to express the structure of the behavior tree in a more elegant way. We do the obvious thing: each node in the tree is some subclass of a Node base class, representing a logical operation like "if" or "do these in parallel".

I very much feel OP's angst about creating a pseudo-programming language-within-a-language by creating what are basically ad hoc AST nodes, but I haven't come up with a better solution. Maybe something like React, where you use basically imperative code to describe a structure, and there is some ambient state that gets properly reconciled by a runtime that you don't touch directly.

Re: Coroutines make robot code easy

#125

Earlier quoted context omitted.

Yes. What question are you answering 'yes' to? The callback is not a natural construct According to who? It is very natural to anyone making a GUI or anything interactive for the firs time. Eventually I would try to move people to queueing up events and handling them all at the same time so that the order is easier to debug. Coroutines are the latest silver bullet syndrome. Fundamentally you still need to synchronize…

The callbacks (as in a chain of callbacks) are not natural to a beginner, like a student trying to program a robot. For a GUI, where you set up a callback in response to user input, it is also easy to understand because the program's control flow does not progress as a chain of callbacks. The input-update-output loop is fine, but you cannot easily combine and nest such loops. For example, in a robot you may have a sp…

as in a chain of callbacks

That's not what you said at first and there is no reason to assume that callbacks automatically mean a chain of callbacks.

The input-update-output loop is fine, but you cannot easily combine and nest such loops.

So don't, where is this assumption that a technique is bad because it might ignore what makes it good and warp it into something terrible?

For example, in a robot you may have a speed control inner loop, then a path following loop and on top of that a high-level behavior loop. Nesting one inside the others you end up with a hand-baked implementation of a coroutine.

Then don't do that. You have a loop, do what you need inside of it. If you don't need to do something every time, skip it most of the time. This isn't rocket science. If a certain architecture doesn't work, don't do it like that. A car doesn't work well if you drive it backwards either.

Re: Coroutines make robot code easy

#126
post #111
post #28

Earlier quoted context omitted.

I want to add to the callback vs coroutines and async/serial discussion that it all depends on how you treat errors. Are errors mere exceptions or do you want to handle errors in the control flow ? For example turndeg(90), Move(10), PickupItem(), turndeg(180), Move(10) you treat errors as exceptions, if the robot fail to pickup the item, or if it ends up at the wrong place it's an exception. Now if you put all these…

I have a gopher server written in Lua [1] that uses coroutines to handle each connection. This bit of code is executed as the main menu page [2] is being displayed (with comments) -- ------------------- -- Load in some modules. -- The first makes a gopher menu item of type link -- The second allows us to do a TCP connection -- -------------------------- local mklink = require "port70.mklink" local tcp = require "org.…

tip: In order to flatten those if-statements you can return early, so if you start with if not ios then return - you get rid of one if..else.

Re: Coroutines make robot code easy

#127

As always when this topic comes up, I have to plug Ceu[0] (formerly Céu) and the programming paradigm it represents. It doesn't use coroutines but synchronous concurrency. On top of that it's a reactive language: // an external input event channel input int KEY; // par/or concurrently executes two // or more blocks (called "trails") // if one of them terminates, the // other trails are aborted. // Compare: par/and, w…

Right, imperative synchronous programming simplifies real time processing a lot. Somehow it does not get the attention it should, which is IMHO due to the fact that it is not available in common programming languages. This is why I tried to create DSLs for C and Swift so that more people could potentially play around with that. https://github.com/frameworklabs/proto_activities

Oooh, this is delightful, thank you for sharing!
Post reply on HN