Open sherm1 opened 3 years ago
Here is an alternative that would allow GetContinuousState() to return a reference rather than a copy. But is it too weird to live?
const VectorX<T>& GetContinuousState() const;
Nice signature, but here's how it would have to work:
diagram_context.GetContinuousState()
would actually be an "Eval" that would make sure the cache entry had an up to date copy of the continuous state, then it would return a reference to that cache entryleaf_context.GetContinuousState()
would simply return a reference to the live continuous state without copyingIn many cases this would silently produce the optimal behavior but the weird thing is that the referenced state would be live in some cases and a dead copy in others. OTOH the proposal in the issue description above is similar in that the continuous state comes back as a copy while the rest return live references.
Some weirdness is unavoidable because of our attempt to hide that a Diagram's continuous state comprises multiple independent VectorX's. For discrete state we didn't attempt that illusion and consequently we can always return references to the live state as a VectorX. (The proposed reengineering of state in #9171 treats continuous and discrete state similarly as collections of VectorX's.)
The current approach of returning a drake::VectorBase<T>&
rather than an Eigen::VectorX<T>&
avoids some of this weirdness in exchange for API awkwardness that @RussTedrake says is a pedagogical impediment.
Note: for advanced users we will still have access to the actual underlying types (State, ContinousState, VectorBase, etc.). The question here is how should the beginner's SetContinuousState()/GetContinuousState() pair behave?
(I'm working on a PR that will show how the call sites are changed by the new APIs.)
The proposed API above looks great. I guess SetTime()
and time()
violate your principle of providing matching case setters and getters? Same for SetAccuracy()
and accuracy
?
Re: VectorX<T>
or const VectorX<T>&
, I really do think there is value in having the simple version look simple. I don't have a strong preference between these, too. Keep in mind that the python versions are going to do the copy in either case, (if I understand correctly), since it will convert to the numpy array, and honestly it's the python API that will be used the most by the non-experts.
Background
The current API for setting & getting values from the Context has several problems in practice as discussed in issue #11346. Among those:
Proposal summary
Main features:
Proposal
Pseudocode for brevity: brackets for optional parameter; left off template declaration for V and Overlay † means method already exists (for plain VectorX).
SetContinuousState(
_vectorspec)
VectorX GetContinuousState() const
// copiesSetContinuousStateAt(int index,
_vectorspec)
const T& GetContinousStateAt(int index) const
SetContinuousStateAs<Overlay>(const Overlay&)
const Overlay& GetContinuousStateAs<Overlay>() const
SetDiscreteState([which,]
_vectorspec)
const VectorX& GetDiscreteState([which]) const
SetDiscreteStateAt([which,] int index,
_vectorspec)
const T& GetDiscreteStateAt([which,] int index) const
SetDiscreteStateAs<Overlay>([which,] const Overlay&)
const Overlay& GetDiscreteStateAs<Overlay>([which]) const
SetAbstractState<V>([which,] const V&)
const V& GetAbstractState<V>([which]) const
SetNumericParameter([which,]
_vectorspec)
const VectorX& GetNumericParameter([which]) const
SetAbstractParameter<V>([which,] const V&)
const V& GetAbstractParameter<V>([which]) const
SetTime(const T&)
const T& time() const
SetAccuracy(optional<double>)
const optional<double>& accuracy() const
const Eigen::Ref<const VectorX<T>>&
|initializer_list<T>
|const T&
(allows e.g.SetContinuousState({1, 2, 3})
)which
is optional if0
is the only possible valuetime()
const T&
accuracy()
const optional<double>&
state()
const State<T>&
parameters()
const Parameters<T>&
There are more details but I want to stop there to solicit initial thoughts. cc @RussTedrake