The recommendation now is to not call CalcTimeDerivatives, but to instead call EvalTimeDerivatives. But there is no comparable API for discrete updates; I think we still call CalcDiscreteVariableUpdates. The lack of parallelism is jarring.
Hmmm. This is much trickier than it sounds. CalcDiscreteVariableUpdates() is mostly useless at this point because it generates "Forced Event" triggers and then invokes the discrete variable event dispatcher. Unless the dispatcher has been overridden (not recommended) that's essentially a no-op. Most of our discrete event handlers respond to periodic event triggers (potentially with many different periods in a Diagram). (Per-step, witness function, etc. triggers can also cause discrete variable updates.) Users _could_ make discrete event handlers respond to forced event triggers also, but rarely do.
Probably a better approach here would be to deprecate CalcDiscreteVariableUpdates() or at least rename it to something less tempting like IssueForcedTriggersForDiscreteUpdates().
Any thoughts @edrumwri ?
The periodic triggering is good for our hybrid simulation framework, though
I could imagine one building a discrete system and just wanting it to
iterate through calculating the discrete variable updates. Though that
would take some additional work to make that application smooth.
We'd need to consider how to readily make discrete systems respond to
forced updates (i.e., rather than making users declare two kinds of
triggers), for example.
I'd be curious to hear what Russ thinks about intended uses. Some polishing
is in order, but it's yet unclear that EvalDiscreteVariableUpdates(.) is
what we want.
Evan Drumwright
Senior Research Scientist
http://positronicslab.github.io
Toyota Research Institute
Palo Alto, CA
On Wed, Mar 13, 2019 at 9:52 AM Michael Sherman notifications@github.com
wrote:
Hmmm. This is much trickier than it sounds. CalcDiscreteVariableUpdates()
is mostly useless at this point because it generates "Forced Event"
triggers and then invokes the discrete variable event dispatcher. Unless
the dispatcher has been overridden (not recommended) that's essentially a
no-op. Most of our discrete event handlers respond to periodic event
triggers (potentially with many different periods in a Diagram). (Per-step,
witness function, etc. triggers can also cause discrete variable updates.)
Users could make discrete event handlers respond to forced event
triggers also, but rarely do.Probably a better approach here would be to deprecate
CalcDiscreteVariableUpdates() or at least rename it to something less
tempting like IssueForcedTriggersForDiscreteUpdates().Any thoughts @edrumwri https://github.com/edrumwri ?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/RobotLocomotion/drake/issues/10909#issuecomment-472510085,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACHwz5rpKbG8UgJiEBbn1TmAUTAYIfBwks5vWSzqgaJpZM4btiy4
.
--
Confidential or protected information may be contained in this email
and/or attachment. Unless otherwise marked, all TRI email communications
are considered "PROTECTED" and should not be shared or distributed. Thank
you.
The intended use here is not for simulation. It's for trajectory optimization (at least that's why I want it). Consider this portion of the dynamics constraint in systems::trajectory_optimization::DirectTranscription: https://github.com/RobotLocomotion/drake/blob/82ae060eea9c2f1e6b9fa79c8574e1464d6dff8e/systems/trajectory_optimization/direct_transcription.cc#L83-L86
@edrumwri and I currently favor the following solution to the problem of advancing a discrete system outside of Simulator (by force-triggering its event handlers):
(trigger, handler) pair, also register (forced, handler).This will have no effect under normal simulator operation, but manual triggering of forced events (which is what CalcDiscreteVariableUpdates() actually does) will cause all the handlers to execute. A Diagram that has been engineered to operate like a simple discrete system will have only a single periodic-triggered handler, or several handlers on the same period, so will behave as expected. Diagrams with many handlers with a variety of triggers will get them all executed, which is the same behavior we're currently getting with the common-but-discouraged overloading of the DoCalcDiscreteVariableUpdates() dispatcher.
Thoughts?
attn: @RussTedrake @avalenzu
(Note: @edrumwri, if we implement this I think we should not generate multiple forced events for the same handler.)
A few points of clarification, per f2f discussion with @sherm1:
MySystem() {
this->DeclarePerStepPublishEvent(&MySystem::HandlePublish);
this->DeclarePeriodicPublishEvent(period, offset, &MySystem::HandlePublish);
}
We do not want MySystem::Publish() to call MySystem::HandlePublish() twice (which it would if we followed Sherm's initial prescription verbatim).
Would we then continue calling CalcDiscreteVariableUpdates() to advance the system? Or would there be an additional EvalDiscreteVariableUpdates() method?
CalcDiscreteVariableUpdates() would work as before. We can also add EvalDiscreteVariableUpdates() (which would return a reference to a cached version of the usual output from CalcDiscreteVariableUpdates()), although that's a separate issue. It's not immediately clear to me what the advantage would be of caching that computation though -- typically you want that computation performed due to an external event, not due to changing inputs. How would you envision that working?
I was mostly thinking of the lack of parallelism that Russ mentioned in the original post.
@avalenzu, I'm not sure I see the parallelism yet (except for the names). Possibly I'm not understanding the intended use. Let me see if I can formulate my confusion:
xₙ₊₁ ← Calc(contextₙ), that is, unconditionally compute xₙ₊₁ from xₙ. Presumably the application then does something with xₙ₊₁.An Eval method would work as follows (by analogy with all other Eval methods):
x̂ ← Calc(contextₙ)What's unclear to me is the meaning of "out of date" in this case. Normally we don't update discrete variables because they are "out of date"; we update them when it's time to move from n to n+1. So what would cause EvalDiscreteVariableUpdates() to actually call Calc() in the application you have in mind?
Sorry for the confusion. I think (correct me if I'm wrong, @RussTedrake) that the original complaint of missing parallelism was entirely about the names.
Personally, I don't have any objection to only having CalcDiscreteVariableUpdates().