RobotLocomotion / drake

Model-based design and verification for robotics.
https://drake.mit.edu
Other
3.36k stars 1.27k forks source link

Request: Need `SystemFunction`? (related to `SystemConstraint`) #10862

Open RussTedrake opened 5 years ago

RussTedrake commented 5 years ago

The SystemConstraint seems to be playing out nicely.

I've been waiting on this request, but my use cases keep building up. I think we also need the notion of a SystemFunction? (basically the same thing, but with no upper/lower bounds) It should be transmogrifiable, too.

The simplest motivation for this is to be able to specify Costs for an optimization problem at a system/subsystem level which contribute to a mathematicalprogram. Note that I was already dancing around this last year when writing, e.g. https://github.com/RobotLocomotion/drake/blob/master/systems/controllers/dynamic_programming.h#L92

Another case that I've come up on now is representing a Lyapunov function for a system. The most natural representation of this, again, is as a function of the context. I'd like to be able to describe a candidate Lyapunov function as a function of context (which I could get a symbolic form of), and even return a certified Lyapunov function as the output of a RegionOfAttraction method.

@hongkai-dai @jwnimmer-tri --what do you think?

jwnimmer-tri commented 5 years ago

We have the SystemConstraintCalc typedef -- though it's only for a single scalar, not the ensemble of all scalars. It's vector-valued, but I assume that's what you want here as well.

So if you just need, e.g., std::function<void(const System<Expression>&, const Context<Expression>&, VectorX<Expression>* value)> as a type, we have that as SystemConstraintCalc<Expression>. We could rename it to not say "Constraint", perhaps.

Is the request here to merely have a class that denotes a functor (ensemble) of a System? (So, stores the functors for the default scalars, and the vector size -- with generic lambda sugar to instantiate it.) Or is there some interaction of that class with the System itself? What operations are of interest?

For example:

RussTedrake commented 5 years ago

Thanks @jwnimmer-tri.

In short, I'll try using ConstraintCalc/SystemConstraintCalc, and get to the PR phase so we can discuss any specific missing features/pain points more specifically. Thanks!

RussTedrake commented 5 years ago

Update: i realize now that by "ensemble" you probably meant "supporting multiple scalar types", and not "a list of functors for the same scalar type". I do have need, basically immediately, of supporting both double and Expression, but from reading system_constraint.h I think it's likely that my needs can be met and we can discuss sugar when i have my initial PR.

hongkai-dai commented 5 years ago

So SystemConstraint has a vector valued Calc function, together with bounds. SystemCost has a scalar valued Calc function, without bounds. Do we also need a middle ground, that has a vector valued Calc function without bounds?

In solvers::Constraint, we have a EvaluatorBase class, that is vector valued, but no bounds. Both solvers::Cost and solvers::Constraint inherits from this EvaluatorBase class.

jwnimmer-tri commented 5 years ago

I read Russ's reply as to mean that it would be okay to only ever have a vector-valued cost (and so sometimes / often the cost vector size == 1). Do you think we need a scalar-valued cost?

RussTedrake commented 5 years ago

@jwnimmer-tri -- i'm curious how you might architect a solution to the following. the output returned from my region of attraction code is a newly allocated object: the lyapunov function... which is a symbolic::Expression. But in order to connect the variables in the expression with the system's context, i was thinking of also using the ContextConstraintCalc. would it make sense to have ContextConstraintCalc that owns the expression? Is there a cleaner/better approach?

I think this is a case where I would want to derive from the (missing) SystemFunction base class? I could derive from SystemConstraint, but it has a lot of baggage that I don't want/need?

jwnimmer-tri commented 5 years ago

I'm not sure I understand well enough to make a suggestion. Is there an example or WIP branch you could point to?

Because ContextConstraintCalc is a std::function, you can create one using a lambda, and the lambda can capture whatever extra expression (or etc) you need. Or is the problem that the user needs to have a get_expression() method?