Drake
diagram.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <functional>
5 #include <limits>
6 #include <map>
7 #include <memory>
8 #include <set>
9 #include <stdexcept>
10 #include <string>
11 #include <utility>
12 #include <vector>
13 
17 #include "drake/common/symbolic.h"
26 
27 namespace drake {
28 namespace systems {
29 
30 template <typename T>
31 class Diagram;
32 template <typename T>
34 
35 namespace internal {
36 
39 template <typename U>
40 std::vector<U*> Unpack(const std::vector<std::unique_ptr<U>>& in) {
41  std::vector<U*> out(in.size());
42  std::transform(in.begin(), in.end(), out.begin(),
43  [](const std::unique_ptr<U>& p) { return p.get(); });
44  return out;
45 }
46 
47 //==============================================================================
48 // DIAGRAM OUTPUT PORT
49 //==============================================================================
54 template <typename T>
55 class DiagramOutputPort : public OutputPort<T> {
56  public:
58 
59 
60  DiagramOutputPort(const Diagram<T>& diagram,
63  const OutputPort<T>* source_output_port)
64  : OutputPort<T>(diagram, source_output_port->get_data_type(),
65  source_output_port->size()),
66  source_output_port_(source_output_port),
67  subsystem_index_(
68  diagram.GetSystemIndexOrAbort(&source_output_port->get_system())) {}
69 
70  ~DiagramOutputPort() final = default;
71 
76  return *source_output_port_;
77  }
78 
79  private:
80  // These forward to the source system output port, passing in just the source
81  // System's Context, not the whole Diagram context we're given.
82  std::unique_ptr<AbstractValue> DoAllocate(
83  const Context<T>& context) const final {
84  const Context<T>& subcontext = get_subcontext(context);
85  return source_output_port_->Allocate(subcontext);
86  }
87 
88  void DoCalc(const Context<T>& context, AbstractValue* value) const final {
89  const Context<T>& subcontext = get_subcontext(context);
90  return source_output_port_->Calc(subcontext, value);
91  }
92 
93  const AbstractValue& DoEval(const Context<T>& context) const final {
94  const Context<T>& subcontext = get_subcontext(context);
95  return source_output_port_->Eval(subcontext);
96  }
97 
98  // Dig out the right subcontext for delegation.
99  const Context<T>& get_subcontext(const Context<T>& context) const {
100  const DiagramContext<T>* diagram_context =
101  dynamic_cast<const DiagramContext<T>*>(&context);
102  DRAKE_DEMAND(diagram_context != nullptr);
103  return diagram_context->GetSubsystemContext(subsystem_index_);
104  }
105 
106  const OutputPort<T>* const source_output_port_;
107  const int subsystem_index_;
108 };
109 
110 //==============================================================================
111 // DIAGRAM OUTPUT
112 //==============================================================================
118 template <typename T>
119 class DiagramOutput : public SystemOutput<T> {
120  public:
122 
123  DiagramOutput() = default;
124 
125  int get_num_ports() const override { return static_cast<int>(ports_.size()); }
126 
128  DRAKE_DEMAND(index >= 0 && index < get_num_ports());
129  return ports_[index];
130  }
131 
132  const OutputPortValue& get_port_value(int index) const override {
133  DRAKE_DEMAND(index >= 0 && index < get_num_ports());
134  return *ports_[index];
135  }
136 
137  std::vector<OutputPortValue*>* get_mutable_port_values() { return &ports_; }
138 
139  protected:
140  // Returns a clone that has the same number of output ports, with values
141  // set to nullptr.
142  DiagramOutput<T>* DoClone() const override {
143  DiagramOutput<T>* clone = new DiagramOutput<T>();
144  clone->ports_.resize(get_num_ports());
145  return clone;
146  }
147 
148  private:
149  std::vector<OutputPortValue*> ports_;
150 };
151 
152 //==============================================================================
153 // DIAGRAM TIME DERIVATIVES
154 //==============================================================================
158 template <typename T>
160  public:
162 
164  std::vector<std::unique_ptr<ContinuousState<T>>>&& substates)
165  : DiagramContinuousState<T>(Unpack(substates)),
166  substates_(std::move(substates)) {}
167 
169 
170  private:
171  std::vector<std::unique_ptr<ContinuousState<T>>> substates_;
172 };
173 
174 //==============================================================================
175 // DIAGRAM DISCRETE VARIABLES
176 //==============================================================================
180 template <typename T>
182  public:
184 
186  std::vector<std::unique_ptr<DiscreteValues<T>>>&& subdiscretes)
187  : DiscreteValues<T>(Flatten(Unpack(subdiscretes))),
188  subdiscretes_(std::move(subdiscretes)) {}
189 
191 
192  int num_subdiscretes() const {
193  return static_cast<int>(subdiscretes_.size());
194  }
195 
197  DRAKE_DEMAND(index >= 0 && index < num_subdiscretes());
198  return subdiscretes_[index].get();
199  }
200 
201  private:
202  std::vector<BasicVector<T>*> Flatten(
203  const std::vector<DiscreteValues<T>*>& in) const {
204  std::vector<BasicVector<T>*> out;
205  for (const DiscreteValues<T>* xd : in) {
206  const std::vector<BasicVector<T>*>& xd_data = xd->get_data();
207  out.insert(out.end(), xd_data.begin(), xd_data.end());
208  }
209  return out;
210  }
211 
212  std::vector<std::unique_ptr<DiscreteValues<T>>> subdiscretes_;
213 };
214 
215 } // namespace internal
216 
217 //==============================================================================
218 // DIAGRAM
219 //==============================================================================
228 template <typename T>
229 class Diagram : public System<T>,
231  public:
232  // Diagram objects are neither copyable nor moveable.
234 
235  typedef typename std::pair<const System<T>*, int> PortIdentifier;
236 
238  template <typename U>
239  explicit Diagram(const Diagram<U>& other)
240  : Diagram(other.template ConvertScalarType<T>()) {}
241 
242  ~Diagram() override {}
243 
245  std::vector<const systems::System<T>*> GetSystems() const {
246  std::vector<const systems::System<T>*> result;
247  result.reserve(registered_systems_.size());
248  for (const auto& system : registered_systems_) {
249  result.push_back(system.get());
250  }
251  return result;
252  }
253 
254  std::multimap<int, int> GetDirectFeedthroughs() const final {
255  std::multimap<int, int> pairs;
256  for (int u = 0; u < this->get_num_input_ports(); ++u) {
257  for (int v = 0; v < this->get_num_output_ports(); ++v) {
258  if (DoHasDirectFeedthrough(u, v)) {
259  pairs.emplace(u, v);
260  }
261  }
262  }
263  return pairs;
264  };
265 
268  std::unique_ptr<CompositeEventCollection<T>>
270  const int num_systems = num_subsystems();
271  std::vector<std::unique_ptr<CompositeEventCollection<T>>> subevents(
272  num_systems);
273  for (int i = 0; i < num_systems; ++i) {
274  subevents[i] = registered_systems_[i]->AllocateCompositeEventCollection();
275  }
276 
277  return std::make_unique<DiagramCompositeEventCollection<T>>(
278  std::move(subevents));
279  }
280 
281  std::unique_ptr<Context<T>> AllocateContext() const override {
282  const int num_systems = num_subsystems();
283  // Reserve inputs as specified during Diagram initialization.
284  auto context = std::make_unique<DiagramContext<T>>(num_systems);
285 
286  // Add each constituent system to the Context.
287  for (int i = 0; i < num_systems; ++i) {
288  const System<T>* const sys = registered_systems_[i].get();
289  auto subcontext = sys->AllocateContext();
290  auto suboutput = sys->AllocateOutput(*subcontext);
291  context->AddSystem(i, std::move(subcontext), std::move(suboutput));
292  }
293 
294  // Wire up the Diagram-internal inputs and outputs.
295  for (const auto& connection : dependency_graph_) {
296  const PortIdentifier& src = connection.second;
297  const PortIdentifier& dest = connection.first;
298  context->Connect(ConvertToContextPortIdentifier(src),
299  ConvertToContextPortIdentifier(dest));
300  }
301 
302  // Declare the Diagram-external inputs.
303  for (const PortIdentifier& id : input_port_ids_) {
304  context->ExportInput(ConvertToContextPortIdentifier(id));
305  }
306 
307  context->MakeState();
308  context->MakeParameters();
309  return std::move(context);
310  }
311 
312  void SetDefaultState(const Context<T>& context,
313  State<T>* state) const override {
314  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
315  DRAKE_DEMAND(diagram_context != nullptr);
316 
317  auto diagram_state = dynamic_cast<DiagramState<T>*>(state);
318  DRAKE_DEMAND(diagram_state != nullptr);
319 
320  // Set default state of each constituent system.
321  for (int i = 0; i < num_subsystems(); ++i) {
322  auto& subcontext = diagram_context->GetSubsystemContext(i);
323  auto& substate = diagram_state->get_mutable_substate(i);
324  registered_systems_[i]->SetDefaultState(subcontext, &substate);
325  }
326  }
327 
328  void SetDefaultParameters(const Context<T>& context,
329  Parameters<T>* params) const override {
330  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
331  DRAKE_DEMAND(diagram_context != nullptr);
332 
333  int numeric_parameter_offset = 0;
334  int abstract_parameter_offset = 0;
335 
336  // Set default parameters of each constituent system.
337  for (int i = 0; i < num_subsystems(); ++i) {
338  auto& subcontext = diagram_context->GetSubsystemContext(i);
339 
340  if (!subcontext.num_numeric_parameters() &&
341  !subcontext.num_abstract_parameters()) {
342  // Then there is no work to do for this subcontext.
343  continue;
344  }
345 
346  // Make a new Parameters<T> structure with pointers to the mutable
347  // subsystem parameter values. This does not make a copy of the
348  // underlying data.
349  // TODO(russt): Consider implementing a DiagramParameters, analogous to
350  // DiagramState, to avoid these dynamic allocations if they prove
351  // expensive.
352 
353  std::vector<BasicVector<T>*> numeric_params;
354  for (int j = 0; j < subcontext.num_numeric_parameters(); ++j) {
355  numeric_params.push_back(params->get_mutable_numeric_parameter(
356  numeric_parameter_offset + j));
357  }
358  numeric_parameter_offset += subcontext.num_numeric_parameters();
359 
360  std::vector<AbstractValue*> abstract_params;
361  for (int j = 0; j < subcontext.num_abstract_parameters(); ++j) {
362  abstract_params.push_back(&params->get_mutable_abstract_parameter(
363  abstract_parameter_offset + j));
364  }
365  abstract_parameter_offset += subcontext.num_abstract_parameters();
366 
367  Parameters<T> subparameters;
368  subparameters.set_numeric_parameters(
369  std::make_unique<DiscreteValues<T>>(numeric_params));
370  subparameters.set_abstract_parameters(
371  std::make_unique<AbstractValues>(abstract_params));
372 
373  registered_systems_[i]->SetDefaultParameters(subcontext, &subparameters);
374  }
375  }
376 
377  void SetRandomState(const Context<T>& context, State<T>* state,
378  RandomGenerator* generator) const override {
379  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
380  DRAKE_DEMAND(diagram_context != nullptr);
381 
382  auto diagram_state = dynamic_cast<DiagramState<T>*>(state);
383  DRAKE_DEMAND(diagram_state != nullptr);
384 
385  // Set state of each constituent system.
386  for (int i = 0; i < num_subsystems(); ++i) {
387  auto& subcontext = diagram_context->GetSubsystemContext(i);
388  auto& substate = diagram_state->get_mutable_substate(i);
389  registered_systems_[i]->SetRandomState(subcontext, &substate, generator);
390  }
391  }
392 
393  void SetRandomParameters(const Context<T>& context, Parameters<T>* params,
394  RandomGenerator* generator) const override {
395  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
396  DRAKE_DEMAND(diagram_context != nullptr);
397 
398  int numeric_parameter_offset = 0;
399  int abstract_parameter_offset = 0;
400 
401  // Set parameters of each constituent system.
402  for (int i = 0; i < num_subsystems(); ++i) {
403  auto& subcontext = diagram_context->GetSubsystemContext(i);
404 
405  if (!subcontext.num_numeric_parameters() &&
406  !subcontext.num_abstract_parameters()) {
407  // Then there is no work to do for this subcontext.
408  continue;
409  }
410 
411  // Make a new Parameters<T> structure with pointers to the mutable
412  // subsystem parameter values. This does not make a copy of the
413  // underlying data.
414  // TODO(russt): This code is duplicated from SetDefaultParameters.
415  // Consider extracting it to a helper method (waiting for the rule of
416  // three).
417 
418  std::vector<BasicVector<T>*> numeric_params;
419  std::vector<AbstractValue*> abstract_params;
420  for (int j = 0; j < subcontext.num_numeric_parameters(); ++j) {
421  numeric_params.push_back(params->get_mutable_numeric_parameter(
422  numeric_parameter_offset + j));
423  }
424  numeric_parameter_offset += subcontext.num_numeric_parameters();
425  for (int j = 0; j < subcontext.num_abstract_parameters(); ++j) {
426  abstract_params.push_back(&params->get_mutable_abstract_parameter(
427  abstract_parameter_offset + j));
428  }
429  abstract_parameter_offset += subcontext.num_abstract_parameters();
430  Parameters<T> subparameters;
431  subparameters.set_numeric_parameters(
432  std::make_unique<DiscreteValues<T>>(numeric_params));
433  subparameters.set_abstract_parameters(
434  std::make_unique<AbstractValues>(abstract_params));
435 
436  registered_systems_[i]->SetRandomParameters(subcontext, &subparameters,
437  generator);
438  }
439  }
440 
441  std::unique_ptr<SystemOutput<T>> AllocateOutput(
442  const Context<T>& context) const override {
443  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
444  DRAKE_DEMAND(diagram_context != nullptr);
445 
446  // The output ports of this Diagram are output ports of its constituent
447  // systems. Create a DiagramOutput with that many ports.
448  auto output = std::make_unique<internal::DiagramOutput<T>>();
449  output->get_mutable_port_values()->resize(output_port_ids_.size());
450  ExposeSubsystemOutputs(*diagram_context, output.get());
451  return std::move(output);
452  }
453 
455  // The three methods below are hidden from doxygen, as described in
456  // documentation for their corresponding methods in System.
457  std::unique_ptr<EventCollection<PublishEvent<T>>>
458  AllocateForcedPublishEventCollection() const final {
459  return AllocateForcedEventCollection<PublishEvent<T>>(
461  }
462 
463  std::unique_ptr<EventCollection<DiscreteUpdateEvent<T>>>
464  AllocateForcedDiscreteUpdateEventCollection() const final {
465  return AllocateForcedEventCollection<DiscreteUpdateEvent<T>>(
467  }
468 
469  std::unique_ptr<EventCollection<UnrestrictedUpdateEvent<T>>>
470  AllocateForcedUnrestrictedUpdateEventCollection() const final {
471  return AllocateForcedEventCollection<UnrestrictedUpdateEvent<T>>(
473  }
475 
478  std::unique_ptr<ContinuousState<T>> AllocateTimeDerivatives() const override {
479  std::vector<std::unique_ptr<ContinuousState<T>>> sub_derivatives;
480  for (const auto& system : registered_systems_) {
481  sub_derivatives.push_back(system->AllocateTimeDerivatives());
482  }
483  return std::unique_ptr<ContinuousState<T>>(
484  new internal::DiagramTimeDerivatives<T>(std::move(sub_derivatives)));
485  }
486 
489  std::unique_ptr<DiscreteValues<T>> AllocateDiscreteVariables()
490  const override {
491  std::vector<std::unique_ptr<DiscreteValues<T>>> sub_discretes;
492  for (const auto& system : registered_systems_) {
493  sub_discretes.push_back(system->AllocateDiscreteVariables());
494  }
495  return std::unique_ptr<DiscreteValues<T>>(
496  new internal::DiagramDiscreteVariables<T>(std::move(sub_discretes)));
497  }
498 
499  void DoCalcTimeDerivatives(const Context<T>& context,
500  ContinuousState<T>* derivatives) const override {
501  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
502  DRAKE_DEMAND(diagram_context != nullptr);
503 
504  auto diagram_derivatives =
505  dynamic_cast<DiagramContinuousState<T>*>(derivatives);
506  DRAKE_DEMAND(diagram_derivatives != nullptr);
507  const int n = diagram_derivatives->get_num_substates();
508  DRAKE_DEMAND(num_subsystems() == n);
509 
510  // Evaluate the derivatives of each constituent system.
511  for (int i = 0; i < n; ++i) {
512  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
513  ContinuousState<T>* subderivatives =
514  diagram_derivatives->get_mutable_substate(i);
515  registered_systems_[i]->CalcTimeDerivatives(subcontext, subderivatives);
516  }
517  }
518 
524  const ContinuousState<T>& derivatives, const System<T>* subsystem) const {
525  DRAKE_DEMAND(subsystem != nullptr);
526  auto diagram_derivatives =
527  dynamic_cast<const DiagramContinuousState<T>*>(&derivatives);
528  DRAKE_DEMAND(diagram_derivatives != nullptr);
529  const int i = GetSystemIndexOrAbort(subsystem);
530  return diagram_derivatives->get_substate(i);
531  }
532 
538  const Context<T>& GetSubsystemContext(const System<T>& subsystem,
539  const Context<T>& context) const {
540  auto ret = DoGetTargetSystemContext(subsystem, &context);
541  DRAKE_DEMAND(ret != nullptr);
542  return *ret;
543  }
544 
550  Context<T>* context) const {
551  auto ret = DoGetMutableTargetSystemContext(subsystem, context);
552  DRAKE_DEMAND(ret != nullptr);
553  return *ret;
554  }
555 
561  const CompositeEventCollection<T>& events) const {
562  auto ret = DoGetTargetSystemCompositeEventCollection(subsystem, &events);
563  DRAKE_DEMAND(ret != nullptr);
564  return *ret;
565  }
566 
571  const System<T>& subsystem, CompositeEventCollection<T>* events) const {
572  auto ret = DoGetMutableTargetSystemCompositeEventCollection(
573  subsystem, events);
574  DRAKE_DEMAND(ret != nullptr);
575  return *ret;
576  }
577 
586  Context<T>* context) const {
587  Context<T>& subcontext = GetMutableSubsystemContext(subsystem, context);
588  return *subcontext.get_mutable_state();
589  }
590 
595  State<T>* state) const {
596  auto ret = DoGetMutableTargetSystemState(subsystem, state);
597  DRAKE_DEMAND(ret != nullptr);
598  return *ret;
599  }
600 
604  const State<T>& GetSubsystemState(const System<T>& subsystem,
605  const State<T>& state) const {
606  auto ret = DoGetTargetSystemState(subsystem, &state);
607  DRAKE_DEMAND(ret != nullptr);
608  return *ret;
609  }
610 
614  void GetPath(std::stringstream* output) const override {
615  return System<T>::GetPath(output);
616  }
617 
618  //----------------------------------------------------------------------------
620 
621 
624  void GetGraphvizFragment(std::stringstream* dot) const override {
625  // Open the Diagram.
626  const int64_t id = this->GetGraphvizId();
627  *dot << "subgraph cluster" << id << "diagram" " {" << std::endl;
628  *dot << "color=black" << std::endl;
629  *dot << "concentrate=true" << std::endl;
630  std::string name = this->get_name();
631  if (name.empty()) name = std::to_string(id);
632  *dot << "label=\"" << name << "\";" << std::endl;
633 
634  // Add a cluster for the input port nodes.
635  *dot << "subgraph cluster" << id << "inputports" << " {" << std::endl;
636  *dot << "rank=same" << std::endl;
637  *dot << "color=lightgrey" << std::endl;
638  *dot << "style=filled" << std::endl;
639  *dot << "label=\"input ports\"" << std::endl;
640  for (int i = 0; i < this->get_num_input_ports(); ++i) {
641  this->GetGraphvizInputPortToken(this->get_input_port(i), dot);
642  *dot << "[color=blue, label=\"u" << i << "\"];" << std::endl;
643  }
644  *dot << "}" << std::endl;
645 
646  // Add a cluster for the output port nodes.
647  *dot << "subgraph cluster" << id << "outputports" << " {" << std::endl;
648  *dot << "rank=same" << std::endl;
649  *dot << "color=lightgrey" << std::endl;
650  *dot << "style=filled" << std::endl;
651  *dot << "label=\"output ports\"" << std::endl;
652  for (int i = 0; i < this->get_num_output_ports(); ++i) {
653  this->GetGraphvizOutputPortToken(this->get_output_port(i), dot);
654  *dot << "[color=green, label=\"y" << i << "\"];" << std::endl;
655  }
656  *dot << "}" << std::endl;
657 
658  // Add a cluster for the subsystems.
659  *dot << "subgraph cluster" << id << "subsystems" << " {" << std::endl;
660  *dot << "color=white" << std::endl;
661  *dot << "label=\"\"" << std::endl;
662  // -- Add the subsystems themselves.
663  for (const auto& subsystem : registered_systems_) {
664  subsystem->GetGraphvizFragment(dot);
665  }
666  // -- Add the connections as edges.
667  for (const auto& edge : dependency_graph_) {
668  const PortIdentifier& src = edge.second;
669  const System<T>* src_sys = src.first;
670  const PortIdentifier& dest = edge.first;
671  const System<T>* dest_sys = dest.first;
672  src_sys->GetGraphvizOutputPortToken(src_sys->get_output_port(src.second),
673  dot);
674  *dot << " -> ";
675  dest_sys->GetGraphvizInputPortToken(dest_sys->get_input_port(dest.second),
676  dot);
677  *dot << ";" << std::endl;
678  }
679 
680  // -- Add edges from the input and output port nodes to the subsystems that
681  // actually service that port. These edges are higlighted in blue
682  // (input) and green (output), matching the port nodes.
683  for (int i = 0; i < this->get_num_input_ports(); ++i) {
684  const auto& port_id = input_port_ids_[i];
685  this->GetGraphvizInputPortToken(this->get_input_port(i), dot);
686  *dot << " -> ";
687  port_id.first->GetGraphvizInputPortToken(
688  port_id.first->get_input_port(port_id.second), dot);
689  *dot << " [color=blue];" << std::endl;
690  }
691 
692  for (int i = 0; i < this->get_num_output_ports(); ++i) {
693  const auto& port_id = output_port_ids_[i];
694  port_id.first->GetGraphvizOutputPortToken(
695  port_id.first->get_output_port(port_id.second), dot);
696  *dot << " -> ";
697  this->GetGraphvizOutputPortToken(this->get_output_port(i), dot);
698  *dot << " [color=green];" << std::endl;
699  }
700  *dot << "}" << std::endl;
701 
702  // Close the diagram.
703  *dot << "}" << std::endl;
704  }
705 
707  std::stringstream* dot) const override {
708  DRAKE_DEMAND(port.get_system() == this);
709  *dot << "_" << this->GetGraphvizId() << "_u" << port.get_index();
710  }
711 
713  std::stringstream* dot) const override {
714  DRAKE_DEMAND(&port.get_system() == this);
715  *dot << "_" << this->GetGraphvizId() << "_y" << port.get_index();
716  }
717 
719 
726  const Context<T>* context,
727  const InputPortDescriptor<T>& descriptor) const override {
728  DRAKE_DEMAND(context != nullptr);
729  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(context);
730  DRAKE_DEMAND(diagram_context != nullptr);
731  const PortIdentifier id{descriptor.get_system(), descriptor.get_index()};
732 
733  // Find if this input port is exported.
734  const auto external_it =
735  std::find(input_port_ids_.begin(), input_port_ids_.end(), id);
736  const bool is_exported = (external_it != input_port_ids_.end());
737 
738  // Find if this input port is connected to an output port.
739  const auto upstream_it = dependency_graph_.find(id);
740  const bool is_connected = (upstream_it != dependency_graph_.end());
741 
742  DRAKE_DEMAND(is_exported ^ is_connected);
743 
744  if (is_exported) {
745  // The upstream output port is an input of this whole Diagram; ask our
746  // parent to evaluate it.
747  const int i = external_it - input_port_ids_.begin();
748  this->EvalInputPort(*diagram_context, i);
749  } else {
750  // The upstream output port exists in this Diagram; evaluate it.
751  // TODO(david-german-tri): Add online algebraic loop detection here.
752  DRAKE_ASSERT(is_connected);
753  const PortIdentifier& prerequisite = upstream_it->second;
754  this->EvaluateOutputPort(*diagram_context, prerequisite);
755  }
756  }
757 
760  int GetSystemIndexOrAbort(const System<T>* sys) const {
761  auto it = system_index_map_.find(sys);
762  DRAKE_DEMAND(it != system_index_map_.end());
763  return it->second;
764  }
765 
766  protected:
771  Diagram() : System<T>(
773  SystemTypeTag<systems::Diagram>{},
775 
785  explicit Diagram(SystemScalarConverter converter)
786  : System<T>(std::move(converter)) {}
787 
792  T DoEvaluateWitness(const Context<T>& context,
793  const WitnessFunction<T>& witness_func) const final {
794  const System<T>& system = witness_func.get_system();
795  const Context<T>& subcontext = GetSubsystemContext(system, context);
796  return witness_func.Evaluate(subcontext);
797  }
798 
804  const WitnessFunction<T>& witness_func,
805  CompositeEventCollection<T>* events) const final {
806  DRAKE_DEMAND(events);
807  const System<T>& subsystem = witness_func.get_system();
808  CompositeEventCollection<T>& subevents =
809  GetMutableSubsystemCompositeEventCollection(subsystem, events);
810  witness_func.AddEvent(&subevents);
811  }
812 
816  void DoGetWitnessFunctions(const Context<T>& context,
817  std::vector<const WitnessFunction<T>*>* witnesses) const final {
818  // A temporary vector is necessary since the vector of witnesses is
819  // declared to be empty on entry to DoGetWitnessFunctions().
820  std::vector<const WitnessFunction<T>*> temp_witnesses;
821 
822  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
823  DRAKE_DEMAND(diagram_context != nullptr);
824 
825  int index = 0; // The subsystem index.
826 
827  for (const auto& system : registered_systems_) {
828  DRAKE_ASSERT(index == GetSystemIndexOrAbort(system.get()));
829  temp_witnesses.clear();
830  system->GetWitnessFunctions(diagram_context->GetSubsystemContext(index),
831  &temp_witnesses);
832  witnesses->insert(witnesses->end(), temp_witnesses.begin(),
833  temp_witnesses.end());
834  ++index;
835  }
836  }
837 
841  const System<T>& target_system, Context<T>* context) const final {
842  if (&target_system == this)
843  return context;
844 
845  return GetSubsystemStuff<Context<T>, DiagramContext<T>>(
846  target_system, context,
849  }
850 
854  const System<T>& target_system, const Context<T>* context) const final {
855  if (&target_system == this)
856  return context;
857 
858  return GetSubsystemStuff<const Context<T>, const DiagramContext<T>>(
859  target_system, context,
862  }
863 
867  const System<T>& target_system, State<T>* state) const final {
868  if (&target_system == this)
869  return state;
870 
871  return GetSubsystemStuff<State<T>, DiagramState<T>>(
872  target_system, state,
875  }
876 
880  const System<T>& target_system, const State<T>* state) const final {
881  if (&target_system == this)
882  return state;
883 
884  return GetSubsystemStuff<const State<T>, const DiagramState<T>>(
885  target_system, state,
888  }
889 
893  const System<T>& target_system,
894  CompositeEventCollection<T>* events) const final {
895  if (&target_system == this)
896  return events;
897 
898  return GetSubsystemStuff<CompositeEventCollection<T>,
900  target_system, events,
903  }
904 
908  const System<T>& target_system,
909  const CompositeEventCollection<T>* events) const final {
910  if (&target_system == this)
911  return events;
912 
913  return GetSubsystemStuff<const CompositeEventCollection<T>,
915  target_system, events,
918  }
919 
924  const Context<T>& context,
925  const Eigen::Ref<const VectorX<T>>& generalized_velocity,
926  VectorBase<T>* qdot) const override {
927  // Check that the dimensions of the continuous state in the context match
928  // the dimensions of the provided generalized velocity and configuration
929  // derivatives.
930  const ContinuousState<T>* xc = context.get_continuous_state();
931  DRAKE_DEMAND(xc != nullptr);
932  const int nq = xc->get_generalized_position().size();
933  const int nv = xc->get_generalized_velocity().size();
934  DRAKE_DEMAND(nq == qdot->size());
935  DRAKE_DEMAND(nv == generalized_velocity.size());
936 
937  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
938  DRAKE_DEMAND(diagram_context != nullptr);
939 
940  // Iterate over the subsystems, asking each subsystem to map its subslice of
941  // velocity to configuration derivatives. This approach is valid because the
942  // DiagramContinuousState guarantees that the subsystem states are
943  // concatenated in order.
944  int v_index = 0; // The next index to read in generalized_velocity.
945  int q_index = 0; // The next index to write in qdot.
946  for (int i = 0; i < num_subsystems(); ++i) {
947  // Find the continuous state of subsystem i.
948  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
949  const ContinuousState<T>* sub_xc = subcontext.get_continuous_state();
950  // If subsystem i is stateless, skip it.
951  if (sub_xc == nullptr) continue;
952 
953  // Select the chunk of generalized_velocity belonging to subsystem i.
954  const int num_v = sub_xc->get_generalized_velocity().size();
955  const Eigen::Ref<const VectorX<T>>& v_slice =
956  generalized_velocity.segment(v_index, num_v);
957 
958  // Select the chunk of qdot belonging to subsystem i.
959  const int num_q = sub_xc->get_generalized_position().size();
960  Subvector<T> dq_slice(qdot, q_index, num_q);
961 
962  // Delegate the actual mapping to subsystem i itself.
963  registered_systems_[i]->MapVelocityToQDot(subcontext, v_slice, &dq_slice);
964 
965  // Advance the indices.
966  v_index += num_v;
967  q_index += num_q;
968  }
969  }
970 
974  void DoMapQDotToVelocity(const Context<T>& context,
975  const Eigen::Ref<const VectorX<T>>& qdot,
976  VectorBase<T>* generalized_velocity) const override {
977  // Check that the dimensions of the continuous state in the context match
978  // the dimensions of the provided generalized velocity and configuration
979  // derivatives.
980  const ContinuousState<T>* xc = context.get_continuous_state();
981  DRAKE_DEMAND(xc != nullptr);
982  const int nq = xc->get_generalized_position().size();
983  const int nv = xc->get_generalized_velocity().size();
984  DRAKE_DEMAND(nq == qdot.size());
985  DRAKE_DEMAND(nv == generalized_velocity->size());
986 
987  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
988  DRAKE_DEMAND(diagram_context != nullptr);
989 
990  // Iterate over the subsystems, asking each subsystem to map its subslice of
991  // configuration derivatives to velocity. This approach is valid because the
992  // DiagramContinuousState guarantees that the subsystem states are
993  // concatenated in order.
994  int q_index = 0; // The next index to read in qdot.
995  int v_index = 0; // The next index to write in generalized_velocity.
996  for (int i = 0; i < num_subsystems(); ++i) {
997  // Find the continuous state of subsystem i.
998  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
999  const ContinuousState<T>* sub_xc = subcontext.get_continuous_state();
1000  // If subsystem i is stateless, skip it.
1001  if (sub_xc == nullptr) continue;
1002 
1003  // Select the chunk of qdot belonging to subsystem i.
1004  const int num_q = sub_xc->get_generalized_position().size();
1005  const Eigen::Ref<const VectorX<T>>& dq_slice =
1006  qdot.segment(q_index, num_q);
1007 
1008  // Select the chunk of generalized_velocity belonging to subsystem i.
1009  const int num_v = sub_xc->get_generalized_velocity().size();
1010  Subvector<T> v_slice(generalized_velocity, v_index, num_v);
1011 
1012  // Delegate the actual mapping to subsystem i itself.
1013  registered_systems_[i]->MapQDotToVelocity(subcontext, dq_slice, &v_slice);
1014 
1015  // Advance the indices.
1016  v_index += num_v;
1017  q_index += num_q;
1018  }
1019  }
1020 
1024  void DoCalcNextUpdateTime(const Context<T>& context,
1025  CompositeEventCollection<T>* event_info,
1026  T* time) const override {
1027  DoCalcNextUpdateTimeImpl(context, event_info, time);
1028  }
1029 
1031  const InputPortDescriptor<T>& descriptor) const override {
1032  // Ask the subsystem to perform the allocation.
1033  const PortIdentifier& id = input_port_ids_[descriptor.get_index()];
1034  const System<T>* subsystem = id.first;
1035  const int subindex = id.second;
1036  return subsystem->AllocateInputVector(subsystem->get_input_port(subindex))
1037  .release();
1038  }
1039 
1041  const InputPortDescriptor<T>& descriptor) const override {
1042  // Ask the subsystem to perform the allocation.
1043  const PortIdentifier& id = input_port_ids_[descriptor.get_index()];
1044  const System<T>* subsystem = id.first;
1045  const int subindex = id.second;
1046  return subsystem->AllocateInputAbstract(subsystem->get_input_port(subindex))
1047  .release();
1048  }
1049 
1050  private:
1051  // Returns true if there might be direct feedthrough from the given
1052  // @p input_port of the Diagram to the given @p output_port of the Diagram.
1053  bool DoHasDirectFeedthrough(int input_port, int output_port) const {
1054  DRAKE_ASSERT(input_port >= 0);
1055  DRAKE_ASSERT(input_port < this->get_num_input_ports());
1056  DRAKE_ASSERT(output_port >= 0);
1057  DRAKE_ASSERT(output_port < this->get_num_output_ports());
1058 
1059  const PortIdentifier& target_input_id = input_port_ids_[input_port];
1060 
1061  // Search the graph for a direct-feedthrough connection from the output_port
1062  // back to the input_port. Maintain a set of the output port identifiers
1063  // that are known to have a direct-feedthrough path to the output_port.
1064  std::set<PortIdentifier> active_set;
1065  active_set.insert(output_port_ids_[output_port]);
1066  while (!active_set.empty()) {
1067  const PortIdentifier current_output_id = *active_set.begin();
1068  size_t removed_count = active_set.erase(current_output_id);
1069  DRAKE_ASSERT(removed_count == 1);
1070  const System<T>* sys = current_output_id.first;
1071  for (int i = 0; i < sys->get_num_input_ports(); ++i) {
1072  if (sys->HasDirectFeedthrough(i, current_output_id.second)) {
1073  const PortIdentifier curr_input_id(sys, i);
1074  if (curr_input_id == target_input_id) {
1075  // We've found a direct-feedthrough path to the input_port.
1076  return true;
1077  } else {
1078  // We've found an intermediate input port has a direct-feedthrough
1079  // path to the output_port. Add the upstream output port (if there
1080  // is one) to the active set.
1081  auto it = dependency_graph_.find(curr_input_id);
1082  if (it != dependency_graph_.end()) {
1083  const PortIdentifier& upstream_output = it->second;
1084  active_set.insert(upstream_output);
1085  }
1086  }
1087  }
1088  }
1089  }
1090  // If there are no intermediate output ports with a direct-feedthrough path
1091  // to the output_port, there is no direct feedthrough to it from the
1092  // input_port.
1093  return false;
1094  }
1095 
1096  template <typename EventType>
1097  std::unique_ptr<EventCollection<EventType>> AllocateForcedEventCollection(
1098  std::function<
1099  std::unique_ptr<EventCollection<EventType>>(const System<T>*)>
1100  allocater_func) const {
1101  const int num_systems = num_subsystems();
1102  auto ret = std::make_unique<DiagramEventCollection<EventType>>(num_systems);
1103  for (int i = 0; i < num_systems; ++i) {
1104  std::unique_ptr<EventCollection<EventType>> subevent_collection =
1105  allocater_func(registered_systems_[i].get());
1106  ret->set_and_own_subevent_collection(i, std::move(subevent_collection));
1107  }
1108  return std::move(ret);
1109  }
1110 
1111  // For each subsystem, if there is a publish event in its corresponding
1112  // subevent collection, calls its Publish method with the appropriate
1113  // subcontext and subevent collection.
1114  void DispatchPublishHandler(
1115  const Context<T>& context,
1116  const EventCollection<PublishEvent<T>>& event_info) const final {
1117  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
1118  DRAKE_DEMAND(diagram_context);
1120  dynamic_cast<const DiagramEventCollection<PublishEvent<T>>&>(
1121  event_info);
1122 
1123  for (int i = 0; i < num_subsystems(); ++i) {
1124  const EventCollection<PublishEvent<T>>& subinfo =
1125  info.get_subevent_collection(i);
1126 
1127  if (subinfo.HasEvents()) {
1128  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
1129  registered_systems_[i]->Publish(subcontext, subinfo);
1130  }
1131  }
1132  }
1133 
1134  // For each subsystem, if there is a discrete update event in its
1135  // corresponding subevent collection, calls its CalcDiscreteVariableUpdates
1136  // method with the appropriate subcontext, subevent collection and
1137  // substate.
1138  void DispatchDiscreteVariableUpdateHandler(
1139  const Context<T>& context,
1140  const EventCollection<DiscreteUpdateEvent<T>>& event_info,
1141  DiscreteValues<T>* discrete_state) const final {
1142  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
1143  DRAKE_DEMAND(diagram_context);
1144  auto diagram_discrete =
1145  dynamic_cast<internal::DiagramDiscreteVariables<T>*>(discrete_state);
1146  DRAKE_DEMAND(diagram_discrete);
1147 
1148  // As a baseline, initialize all the discrete variables to their
1149  // current values.
1150  // TODO(siyuan): should have a API level CopyFrom for DiscreteValues.
1151  for (int i = 0; i < diagram_discrete->num_groups(); ++i) {
1152  diagram_discrete->get_mutable_vector(i)->set_value(
1153  context.get_discrete_state(i)->get_value());
1154  }
1155 
1157  dynamic_cast<const DiagramEventCollection<DiscreteUpdateEvent<T>>&>(
1158  event_info);
1159 
1160  for (int i = 0; i < num_subsystems(); ++i) {
1161  const EventCollection<DiscreteUpdateEvent<T>>& subinfo =
1162  info.get_subevent_collection(i);
1163 
1164  if (subinfo.HasEvents()) {
1165  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
1166  DiscreteValues<T>* subdiscrete =
1167  diagram_discrete->get_mutable_subdiscrete(i);
1168  DRAKE_DEMAND(subdiscrete != nullptr);
1169 
1170  registered_systems_[i]->CalcDiscreteVariableUpdates(subcontext, subinfo,
1171  subdiscrete);
1172  }
1173  }
1174  }
1175 
1176  // For each subsystem, if there is an unrestricted update event in its
1177  // corresponding subevent collection, calls its CalcUnrestrictedUpdate
1178  // method with the appropriate subcontext, subevent collection and substate.
1179  void DispatchUnrestrictedUpdateHandler(
1180  const Context<T>& context,
1181  const EventCollection<UnrestrictedUpdateEvent<T>>& event_info,
1182  State<T>* state) const final {
1183  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
1184  DRAKE_DEMAND(diagram_context);
1185  auto diagram_state = dynamic_cast<DiagramState<T>*>(state);
1186  DRAKE_DEMAND(diagram_state != nullptr);
1187 
1188  // No need to set state to context's state, since it has already been done
1189  // in System::CalcUnrestrictedUpdate().
1190 
1193  event_info);
1194 
1195  for (int i = 0; i < num_subsystems(); ++i) {
1197  info.get_subevent_collection(i);
1198 
1199  if (subinfo.HasEvents()) {
1200  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
1201  State<T>& substate = diagram_state->get_mutable_substate(i);
1202 
1203  registered_systems_[i]->CalcUnrestrictedUpdate(subcontext, subinfo,
1204  &substate);
1205  }
1206  }
1207  }
1208 
1229  template <typename BaseStuff, typename DerivedStuff>
1230  BaseStuff* GetSubsystemStuff(
1231  const System<T>& target_system, BaseStuff* my_stuff,
1232  std::function<BaseStuff* (const System<T>*, const System<T>&, BaseStuff*)>
1233  recursive_getter,
1234  std::function<BaseStuff& (DerivedStuff*, int)> get_child_stuff) const {
1235  static_assert(
1236  std::is_same<BaseStuff,
1237  typename std::remove_pointer<BaseStuff>::type>::value,
1238  "BaseStuff cannot be a pointer");
1239  static_assert(
1240  std::is_same<DerivedStuff,
1241  typename std::remove_pointer<DerivedStuff>::type>::value,
1242  "DerivedStuff cannot be a pointer");
1243 
1244  DRAKE_DEMAND(my_stuff != nullptr);
1245  DRAKE_DEMAND(&target_system != this);
1246  DerivedStuff& my_stuff_as_derived = dynamic_cast<DerivedStuff&>(*my_stuff);
1247 
1248  int index = 0;
1249  for (const auto& child : registered_systems_) {
1250  BaseStuff& child_stuff =
1251  get_child_stuff(&my_stuff_as_derived, index);
1252 
1253  BaseStuff* const target_stuff =
1254  recursive_getter(child.get(), target_system, &child_stuff);
1255 
1256  if (target_stuff != nullptr) {
1257  return target_stuff;
1258  }
1259  index++;
1260  }
1261 
1262  return nullptr;
1263  }
1264 
1269  template <typename NewType>
1270  std::unique_ptr<typename Diagram<NewType>::Blueprint> ConvertScalarType()
1271  const {
1272  std::vector<std::unique_ptr<System<NewType>>> new_systems;
1273  // Recursively convert all the subsystems.
1274  std::map<const System<T>*, const System<NewType>*> old_to_new_map;
1275  for (const auto& old_system : registered_systems_) {
1276  // Convert old_system to new_system using the old_system's converter.
1277  std::unique_ptr<System<NewType>> new_system =
1278  old_system->get_system_scalar_converter().
1279  template Convert<NewType>(*old_system);
1280  DRAKE_DEMAND(new_system != nullptr);
1281 
1282  // Update our mapping and take ownership.
1283  old_to_new_map[old_system.get()] = new_system.get();
1284  new_systems.push_back(std::move(new_system));
1285  }
1286 
1287  // Set up the blueprint.
1288  auto blueprint = std::make_unique<typename Diagram<NewType>::Blueprint>();
1289  // Make all the inputs and outputs.
1290  for (const PortIdentifier& id : input_port_ids_) {
1291  const System<NewType>* new_system = old_to_new_map[id.first];
1292  const int port = id.second;
1293  blueprint->input_port_ids.emplace_back(new_system, port);
1294  }
1295  for (const PortIdentifier& id : output_port_ids_) {
1296  const System<NewType>* new_system = old_to_new_map[id.first];
1297  const int port = id.second;
1298  blueprint->output_port_ids.emplace_back(new_system, port);
1299  }
1300  // Make all the connections.
1301  for (const auto& edge : dependency_graph_) {
1302  const PortIdentifier& old_dest = edge.first;
1303  const System<NewType>* const dest_system = old_to_new_map[old_dest.first];
1304  const int dest_port = old_dest.second;
1305  const typename Diagram<NewType>::PortIdentifier new_dest{dest_system,
1306  dest_port};
1307 
1308  const PortIdentifier& old_src = edge.second;
1309  const System<NewType>* const src_system = old_to_new_map[old_src.first];
1310  const int src_port = old_src.second;
1311  const typename Diagram<NewType>::PortIdentifier new_src{src_system,
1312  src_port};
1313 
1314  blueprint->dependency_graph[new_dest] = new_src;
1315  }
1316  // Move the new systems into the blueprint.
1317  blueprint->systems = std::move(new_systems);
1318 
1319  return blueprint;
1320  }
1321 
1322  // Aborts for scalar types that are not numeric, since there is no reasonable
1323  // definition of "next update time" outside of the real line.
1324  //
1325  // @tparam T1 SFINAE boilerplate for the scalar type. Do not set.
1326  template <typename T1 = T>
1328  DoCalcNextUpdateTimeImpl(const Context<T1>&, CompositeEventCollection<T1>*,
1329  T1*) const {
1331  "The default implementation of Diagram<T>::DoCalcNextUpdateTime "
1332  "only works with types that are drake::is_numeric.");
1333  }
1334 
1335  // Computes the next update time across all the scheduled events, for
1336  // scalar types that are numeric.
1337  //
1338  // @tparam T1 SFINAE boilerplate for the scalar type. Do not set.
1339  template <typename T1 = T>
1340  typename std::enable_if<is_numeric<T1>::value>::type DoCalcNextUpdateTimeImpl(
1341  const Context<T1>& context, CompositeEventCollection<T1>* event_info,
1342  T1* time) const {
1343  auto diagram_context = dynamic_cast<const DiagramContext<T1>*>(&context);
1344  auto info = dynamic_cast<DiagramCompositeEventCollection<T1>*>(event_info);
1345  DRAKE_DEMAND(diagram_context != nullptr);
1346  DRAKE_DEMAND(info != nullptr);
1347 
1348  *time = std::numeric_limits<T1>::infinity();
1349 
1350  // Iterate over the subsystems, and harvest the most imminent updates.
1351  std::vector<T1> times(num_subsystems());
1352  for (int i = 0; i < num_subsystems(); ++i) {
1353  const Context<T1>& subcontext = diagram_context->GetSubsystemContext(i);
1354  CompositeEventCollection<T1>& subinfo =
1355  info->get_mutable_subevent_collection(i);
1356  const T1 sub_time =
1357  registered_systems_[i]->CalcNextUpdateTime(subcontext, &subinfo);
1358  times[i] = sub_time;
1359 
1360  if (sub_time < *time) {
1361  *time = sub_time;
1362  }
1363  }
1364 
1365  // For all the subsystems whose next update time is bigger than *time,
1366  // clear their event collections.
1367  for (int i = 0; i < num_subsystems(); ++i) {
1368  if (times[i] > *time)
1369  info->get_mutable_subevent_collection(i).Clear();
1370  }
1371  }
1372 
1373  void DoGetPerStepEvents(
1374  const Context<T>& context,
1375  CompositeEventCollection<T>* event_info) const override {
1376  auto diagram_context = dynamic_cast<const DiagramContext<T>*>(&context);
1377  auto info = dynamic_cast<DiagramCompositeEventCollection<T>*>(event_info);
1378  DRAKE_DEMAND(diagram_context != nullptr);
1379  DRAKE_DEMAND(info != nullptr);
1380 
1381  for (int i = 0; i < num_subsystems(); ++i) {
1382  const Context<T>& subcontext = diagram_context->GetSubsystemContext(i);
1383  CompositeEventCollection<T>& subinfo =
1384  info->get_mutable_subevent_collection(i);
1385 
1386  registered_systems_[i]->GetPerStepEvents(subcontext, &subinfo);
1387  }
1388  }
1389 
1390  // A structural outline of a Diagram, produced by DiagramBuilder.
1391  struct Blueprint {
1392  // The ordered subsystem ports that are inputs to the entire diagram.
1393  std::vector<PortIdentifier> input_port_ids;
1394  // The ordered subsystem ports that are outputs of the entire diagram.
1395  std::vector<PortIdentifier> output_port_ids;
1396  // A map from the input ports of constituent systems to the output ports
1397  // on which they depend. This graph is possibly cyclic, but must not
1398  // contain an algebraic loop.
1399  std::map<PortIdentifier, PortIdentifier> dependency_graph;
1400  // All of the systems to be included in the diagram.
1401  std::vector<std::unique_ptr<System<T>>> systems;
1402  };
1403 
1404  // Constructs a Diagram from the Blueprint that a DiagramBuilder produces.
1405  // This constructor is private because only DiagramBuilder calls it. The
1406  // constructor takes the systems from the blueprint.
1407  explicit Diagram(std::unique_ptr<Blueprint> blueprint) : Diagram() {
1408  Initialize(std::move(blueprint));
1409  }
1410 
1411  // Validates the given @p blueprint and sets up the Diagram accordingly.
1412  void Initialize(std::unique_ptr<Blueprint> blueprint) {
1413  // We must be given something to own.
1414  DRAKE_DEMAND(!blueprint->systems.empty());
1415  // We must not already own any subsystems.
1416  DRAKE_DEMAND(registered_systems_.empty());
1417 
1418  // Copy the data from the blueprint into private member variables.
1419  dependency_graph_ = std::move(blueprint->dependency_graph);
1420  input_port_ids_ = std::move(blueprint->input_port_ids);
1421  output_port_ids_ = std::move(blueprint->output_port_ids);
1422  registered_systems_ = std::move(blueprint->systems);
1423 
1424  // Generate a map from the System pointer to its index in the registered
1425  // order.
1426  for (int i = 0; i < num_subsystems(); ++i) {
1427  system_index_map_[registered_systems_[i].get()] = i;
1428  registered_systems_[i]->set_parent(this);
1429  }
1430 
1431  // Generate constraints for the diagram from the constraints on the
1432  // subsystems.
1433  for (int i = 0; i < num_subsystems(); ++i) {
1434  const auto sys = registered_systems_[i].get();
1435  for (SystemConstraintIndex j(0); j < sys->get_num_constraints(); ++j) {
1436  const auto c = &(sys->get_constraint(j));
1437  typename SystemConstraint<T>::CalcCallback diagram_calc =
1438  [this, sys, c](const Context<T>& context, VectorX<T>* value) {
1439  c->Calc(this->GetSubsystemContext(*sys, context), value);
1440  };
1441  this->AddConstraint(std::make_unique<SystemConstraint<T>>(
1442  diagram_calc, c->size(), c->type(),
1443  sys->get_name() + ":" + c->description()));
1444  }
1445  }
1446 
1447  // Every system must appear exactly once.
1448  DRAKE_DEMAND(registered_systems_.size() == system_index_map_.size());
1449  // Every port named in the dependency_graph_ must actually exist.
1450  DRAKE_ASSERT(PortsAreValid());
1451  // Every subsystem must have a unique name.
1452  DRAKE_THROW_UNLESS(NamesAreUniqueAndNonEmpty());
1453 
1454  // Add the inputs to the Diagram topology, and check their invariants.
1455  for (const PortIdentifier& id : input_port_ids_) {
1456  ExportInput(id);
1457  }
1458  for (const PortIdentifier& id : output_port_ids_) {
1459  ExportOutput(id);
1460  }
1461 
1462  // Identify the intersection of the subsystems' scalar conversion support.
1463  // Remove all conversions that at least one subsystem did not support.
1464  SystemScalarConverter& this_scalar_converter =
1465  SystemImpl::get_mutable_system_scalar_converter(this);
1466  for (const auto& system : registered_systems_) {
1467  this_scalar_converter.RemoveUnlessAlsoSupportedBy(
1468  system->get_system_scalar_converter());
1469  }
1470 
1471  this->set_forced_publish_events(
1472  AllocateForcedEventCollection<PublishEvent<T>>(
1474  this->set_forced_discrete_update_events(
1475  AllocateForcedEventCollection<DiscreteUpdateEvent<T>>(
1477  this->set_forced_unrestricted_update_events(
1478  AllocateForcedEventCollection<UnrestrictedUpdateEvent<T>>(
1480  }
1481 
1482  // Exposes the given port as an input of the Diagram.
1483  void ExportInput(const PortIdentifier& port) {
1484  const System<T>* const sys = port.first;
1485  const int port_index = port.second;
1486  // Fail quickly if this system is not part of the diagram.
1487  GetSystemIndexOrAbort(sys);
1488 
1489  // Add this port to our externally visible topology.
1490  const auto& subsystem_descriptor = sys->get_input_port(port_index);
1491  this->DeclareInputPort(subsystem_descriptor.get_data_type(),
1492  subsystem_descriptor.size(),
1493  subsystem_descriptor.get_random_type());
1494  }
1495 
1496  // Exposes the given subsystem output port as an output of the Diagram.
1497  void ExportOutput(const PortIdentifier& port) {
1498  const System<T>* const sys = port.first;
1499  const int port_index = port.second;
1500  const auto& source_output_port = sys->get_output_port(port_index);
1501  auto diagram_port = std::make_unique<internal::DiagramOutputPort<T>>(
1502  *this, &source_output_port);
1503  this->CreateOutputPort(std::move(diagram_port));
1504  }
1505 
1506  // Evaluates the value of the output port with the given @p id in the given
1507  // @p context.
1508  //
1509  // TODO(david-german-tri): Add Diagram-level cache entries to keep track of
1510  // whether a given output port has already been evaluated. Right now, we
1511  // are recomputing every intermediate output to satisfy every system that
1512  // depends on it, recursively. This is O(N^2 * M), where M is the number of
1513  // output ports the Diagram exposes, and N is the number of intermediate
1514  // output ports the Diagram contains.
1515  void EvaluateOutputPort(const DiagramContext<T>& context,
1516  const PortIdentifier& id) const {
1517  const System<T>* const system = id.first;
1518  const OutputPortIndex port_index(id.second);
1519  const OutputPort<T>& port = system->get_output_port(port_index);
1520  const int i = GetSystemIndexOrAbort(system);
1521  SPDLOG_TRACE(log(), "Evaluating output for subsystem {}, port {}",
1522  system->GetPath(), port_index);
1523  const Context<T>& subsystem_context = context.GetSubsystemContext(i);
1524  SystemOutput<T>* subsystem_output = context.GetSubsystemOutput(i);
1525  AbstractValue* port_output = subsystem_output->GetMutableData(port_index);
1526  port.Calc(subsystem_context, port_output);
1527  }
1528 
1529  // Converts a PortIdentifier to a DiagramContext::PortIdentifier.
1530  // The DiagramContext::PortIdentifier contains the index of the System in the
1531  // the diagram, instead of an actual pointer to the System.
1532  typename DiagramContext<T>::PortIdentifier ConvertToContextPortIdentifier(
1533  const PortIdentifier& id) const {
1534  typename DiagramContext<T>::PortIdentifier output;
1535  output.first = GetSystemIndexOrAbort(id.first);
1536  output.second = id.second;
1537  return output;
1538  }
1539 
1540  // Sets up the OutputPortValue pointers in @p output to point to the subsystem
1541  // output values, found in @p context, that are the outputs of this Diagram.
1542  void ExposeSubsystemOutputs(const DiagramContext<T>& context,
1543  internal::DiagramOutput<T>* output) const {
1544  // The number of output ports of this diagram must equal the number of
1545  // ports in the provided DiagramOutput.
1546  const int num_ports = static_cast<int>(output_port_ids_.size());
1547  DRAKE_DEMAND(output->get_num_ports() == num_ports);
1548 
1549  for (int i = 0; i < num_ports; ++i) {
1550  const PortIdentifier& id = output_port_ids_[i];
1551  // For each configured output port ID, obtain from the DiagramContext the
1552  // actual OutputPortValue that supplies its value.
1553  const int sys_index = GetSystemIndexOrAbort(id.first);
1554  const int port_index = id.second;
1555  SystemOutput<T>* subsystem_output = context.GetSubsystemOutput(sys_index);
1556  OutputPortValue* output_port_value =
1557  subsystem_output->get_mutable_port_value(port_index);
1558 
1559  // Then, put a pointer to that OutputPortValue in the DiagramOutput.
1560  (*output->get_mutable_port_values())[i] = output_port_value;
1561  }
1562  }
1563 
1564  // Returns true if every port mentioned in the dependency_graph_ exists.
1565  bool PortsAreValid() const {
1566  for (const auto& entry : dependency_graph_) {
1567  const PortIdentifier& dest = entry.first;
1568  const PortIdentifier& src = entry.second;
1569  if (dest.second < 0 || dest.second >= dest.first->get_num_input_ports()) {
1570  return false;
1571  }
1572  if (src.second < 0 || src.second >= src.first->get_num_output_ports()) {
1573  return false;
1574  }
1575  }
1576  return true;
1577  }
1578 
1579  // Returns true if every subsystem has a unique, non-empty name.
1580  // O(N * log(N)) in the number of subsystems.
1581  bool NamesAreUniqueAndNonEmpty() const {
1582  std::set<std::string> names;
1583  for (const auto& system : registered_systems_) {
1584  const std::string& name = system->get_name();
1585  if (name.empty()) {
1586  // This can only happen if someone blanks out the name *after* adding
1587  // it to DiagramBuilder; if an empty name is given to DiagramBuilder,
1588  // a default non-empty name is automatically assigned.
1589  log()->error("Subsystem of type {} has no name",
1590  NiceTypeName::Get(*system));
1591  // We skip names.insert here, so that the return value will be false.
1592  continue;
1593  }
1594  if (names.find(name) != names.end()) {
1595  log()->error("Non-unique name \"{}\" for subsystem of type {}", name,
1596  NiceTypeName::Get(*system));
1597  }
1598  names.insert(name);
1599  }
1600  return names.size() == registered_systems_.size();
1601  }
1602 
1603  int num_subsystems() const {
1604  return static_cast<int>(registered_systems_.size());
1605  }
1606 
1607  // A map from the input ports of constituent systems, to the output ports of
1608  // the systems on which they depend.
1609  std::map<PortIdentifier, PortIdentifier> dependency_graph_;
1610 
1611  // The Systems in this Diagram, which are owned by this Diagram, in the order
1612  // they were registered.
1613  std::vector<std::unique_ptr<System<T>>> registered_systems_;
1614 
1615  // Map to quickly satisify "What is the subsytem index of the child system?"
1616  std::map<const System<T>*, int> system_index_map_;
1617 
1618  // The ordered inputs and outputs of this Diagram.
1619  std::vector<PortIdentifier> input_port_ids_;
1620  std::vector<PortIdentifier> output_port_ids_;
1621 
1622  // For all T, Diagram<T> considers DiagramBuilder<T> a friend, so that the
1623  // builder can set the internal state correctly.
1624  friend class DiagramBuilder<T>;
1625 
1626  // For any T1 & T2, Diagram<T1> considers Diagram<T2> a friend, so that
1627  // Diagram can provide transmogrification methods across scalar types.
1628  // See Diagram<T>::ConvertScalarType.
1629  template <typename> friend class Diagram;
1630 };
1631 
1632 } // namespace systems
1633 } // namespace drake
const EventCollection< EventType > & get_subevent_collection(int index) const
Returns a const pointer to subsystem&#39;s EventCollection at index.
Definition: event_collection.h:221
Context< T > * DoGetMutableTargetSystemContext(const System< T > &target_system, Context< T > *context) const final
Returns a pointer to mutable context if target_system is a sub system of this, nullptr is returned ot...
Definition: diagram.h:840
void DoMapQDotToVelocity(const Context< T > &context, const Eigen::Ref< const VectorX< T >> &qdot, VectorBase< T > *generalized_velocity) const override
The generalized_velocity vector must have the same size and ordering as the generalized velocity in t...
Definition: diagram.h:974
virtual int size() const =0
Returns the number of elements in the vector.
The DiscreteValues is a container for numerical but non-continuous state and parameters.
Definition: discrete_values.h:28
std::multimap< int, int > GetDirectFeedthroughs() const final
Reports all direct feedthroughs from input ports to output ports.
Definition: diagram.h:254
const SystemScalarConverter & get_system_scalar_converter() const
(Advanced) Returns the SystemScalarConverter for this object.
Definition: system.h:1267
virtual std::unique_ptr< Context< T > > AllocateContext() const =0
Allocates a context, initialized with the correct numbers of concrete input ports and state variables...
void GetGraphvizOutputPortToken(const OutputPort< T > &port, std::stringstream *dot) const override
Appends a fragment to the dot stream identifying the graphviz node representing port.
Definition: diagram.h:712
void SetDefaultState(const Context< T > &context, State< T > *state) const override
Assigns default values to all elements of the state.
Definition: diagram.h:312
int num_subdiscretes() const
Definition: diagram.h:192
OutputPortValue contains the value of a single System output port.
Definition: output_port_value.h:23
Definition: automotive_demo.cc:88
std::vector< OutputPortValue * > * get_mutable_port_values()
Definition: diagram.h:137
This file contains traits for number (scalar) types.
const DiscreteValues< T > * get_discrete_state() const
Definition: context.h:133
std::unique_ptr< SystemOutput< T > > AllocateOutput(const Context< T > &context) const override
Returns a container that can hold the values of all of this System&#39;s output ports.
Definition: diagram.h:441
const ContinuousState< T > * get_continuous_state() const
Returns a const pointer to the continuous component of the state, which may be of size zero...
Definition: context.h:118
SystemOutput< T > * GetSubsystemOutput(SystemIndex index) const
Returns the output structure for a given constituent system at index.
Definition: diagram_context.h:235
DiagramOutput< T > * DoClone() const override
The NVI implementation of Clone().
Definition: diagram.h:142
std::mt19937 RandomGenerator
Defines the implementation of the stdc++ concept UniformRandomBitGenerator to be used by the Systems ...
Definition: system.h:69
void DoCalcNextUpdateTime(const Context< T > &context, CompositeEventCollection< T > *event_info, T *time) const override
Computes the next update time based on the configured actions, for scalar types that are arithmetic...
Definition: diagram.h:1024
Diagram()
Constructs an uninitialized Diagram.
Definition: diagram.h:771
void set_numeric_parameters(std::unique_ptr< DiscreteValues< T >> numeric_params)
Definition: parameters.h:90
virtual void GetGraphvizOutputPortToken(const OutputPort< T > &port, std::stringstream *dot) const
Appends a fragment to the dot stream identifying the graphviz node representing port.
Definition: system.h:1084
void AddTriggeredWitnessFunctionToCompositeEventCollection(const WitnessFunction< T > &witness_func, CompositeEventCollection< T > *events) const final
For the subsystem associated with witness_func, gets its mutable sub composite event collection from ...
Definition: diagram.h:803
void GetPath(std::stringstream *output) const override
Returns the full path of this Diagram in the tree of Diagrams.
Definition: diagram.h:614
STL namespace.
Context is an abstract base class template that represents all the inputs to a System: time...
Definition: query_handle.h:10
const Context< T > & GetSubsystemContext(SystemIndex index) const
Returns the context structure for a given constituent system index.
Definition: diagram_context.h:245
int u
Definition: rgbd_camera_test.cc:164
~Diagram() override
Definition: diagram.h:242
void DoGetWitnessFunctions(const Context< T > &context, std::vector< const WitnessFunction< T > * > *witnesses) const final
Provides witness functions of subsystems that are active at the beginning of a continuous time interv...
Definition: diagram.h:816
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > VectorX
A column vector of any size, templated on scalar type.
Definition: eigen_types.h:46
This class represents an unrestricted update event.
Definition: event.h:326
DiagramContinuousState is a ContinuousState consisting of Supervectors over a set of constituent Cont...
Definition: diagram_continuous_state.h:19
std::unique_ptr< ContinuousState< T > > AllocateTimeDerivatives() const override
Aggregates the time derivatives from each subsystem into a DiagramTimeDerivatives.
Definition: diagram.h:478
#define DRAKE_ABORT_MSG(message)
Aborts the program (via ::abort) with a message showing at least the given message (macro argument)...
Definition: drake_assert.h:51
VectorBase is an abstract base class that real-valued signals between Systems and real-valued System ...
Definition: vector_base.h:27
symbolic::Monomial transform(const symbolic::Monomial &monomial, const map< Variable::Id, Variable > &var_id_to_var)
Definition: mathematical_program_test.cc:2279
const InputPortDescriptor< T > & get_input_port(int port_index) const
Returns the descriptor of the input port at index port_index.
Definition: system.h:918
std::unique_ptr< DiscreteValues< T > > AllocateDiscreteVariables() const override
Aggregates the discrete update variables from each subsystem into a DiagramDiscreteVariables.
Definition: diagram.h:489
#define SPDLOG_TRACE(logger,...)
Definition: text_logging.h:92
Context< T > & GetMutableSubsystemContext(const System< T > &subsystem, Context< T > *context) const
Returns the subcontext that corresponds to the system subsystem.
Definition: diagram.h:549
const OutputPort< T > & get_source_output_port() const
Obtain a reference to the subsystem output port that was exported to create this diagram port...
Definition: diagram.h:75
BasicVector< T > * get_mutable_numeric_parameter(int index)
Returns the vector-valued parameter at index.
Definition: parameters.h:82
Holds information about the subsystem output port that has been exported to become one of this Diagra...
Definition: diagram.h:55
#define DRAKE_THROW_UNLESS(condition)
Evaluates condition and iff the value is false will throw an exception with a message showing at leas...
Definition: drake_throw.h:23
DiagramTimeDerivatives is a version of DiagramContinuousState that owns the constituent continuous st...
Definition: diagram.h:159
logging::logger * log()
Retrieve an instance of a logger to use for logging; for example: drake::log()->info("potato!") ...
Definition: text_logging.cc:38
A concrete class that holds all simultaneous homogeneous events for a Diagram.
Definition: event_collection.h:158
std::string to_string(const drake::geometry::Identifier< Tag > &id)
Enables use of identifiers with to_string.
Definition: identifier.h:203
std::vector< double > vector
Definition: translator_test.cc:20
CompositeEventCollection for a Diagram.
Definition: event_collection.h:628
InputPortDescriptor is a notation for specifying the kind of input a System accepts, on a given port.
Definition: input_port_descriptor.h:21
BasicVector< T > * DoAllocateInputVector(const InputPortDescriptor< T > &descriptor) const override
Allocates an input vector of the leaf type that the System requires on the port specified by descript...
Definition: diagram.h:1030
DiagramBuilder is a factory class for Diagram.
Definition: diagram.h:33
DiagramOutput is an implementation of SystemOutput that holds unowned OutputPortValue pointers...
Definition: diagram.h:119
An OutputPort belongs to a System and represents the properties of one of that System&#39;s output ports...
Definition: output_port.h:67
std::unique_ptr< AbstractValue > AllocateInputAbstract(const InputPortDescriptor< T > &descriptor) const
Given a port descriptor, allocates the abstract storage.
Definition: system.h:119
DiagramDiscreteVariables is a version of DiscreteState that owns the constituent discrete states...
Definition: diagram.h:181
CompositeEventCollection< T > & GetMutableSubsystemCompositeEventCollection(const System< T > &subsystem, CompositeEventCollection< T > *events) const
Returns the mutable subsystem composite event collection that corresponds to subsystem.
Definition: diagram.h:570
std::vector< Number > result
Definition: ipopt_solver.cc:151
const State< T > & GetSubsystemState(const System< T > &subsystem, const State< T > &state) const
Retrieves the state for a particular subsystem from the state for the entire diagram.
Definition: diagram.h:604
DiscreteValues< T > * get_mutable_subdiscrete(int index)
Definition: diagram.h:196
virtual bool HasEvents() const =0
Returns false if and only if this collection contains no events.
std::vector< U * > Unpack(const std::vector< std::unique_ptr< U >> &in)
Returns a vector of raw pointers that correspond placewise with the unique_ptrs in the vector in...
Definition: diagram.h:40
std::vector< const systems::System< T > * > GetSystems() const
Returns the list of contained Systems.
Definition: diagram.h:245
int v
Definition: rgbd_camera_test.cc:165
#define DRAKE_ASSERT(condition)
DRAKE_ASSERT(condition) is similar to the built-in assert(condition) from the C++ system header <cas...
Definition: drake_assert.h:37
DiagramState is a State, annotated with pointers to all the mutable substates that it spans...
Definition: diagram_context.h:27
void SetRandomParameters(const Context< T > &context, Parameters< T > *params, RandomGenerator *generator) const override
Assigns random values to all parameters.
Definition: diagram.h:393
AbstractValue * GetMutableData(int index)
Returns a pointer to the data inside the port at index, and updates the version so that Contexts depe...
Definition: output_port_value.h:158
std::pair< const System< double > *, int > PortIdentifier
Definition: diagram.h:235
int value
Definition: copyable_unique_ptr_test.cc:61
void DoCalcTimeDerivatives(const Context< T > &context, ContinuousState< T > *derivatives) const override
Override this if you have any continuous state variables xc in your concrete System to calculate thei...
Definition: diagram.h:499
Provides Drake&#39;s assertion implementation.
void RemoveUnlessAlsoSupportedBy(const SystemScalarConverter &other)
Removes from this converter all pairs where other.IsConvertible<T, U> is false.
Definition: system_scalar_converter.cc:41
This is the entry point for all text logging within Drake.
State< T > & GetMutableSubsystemState(const System< T > &subsystem, Context< T > *context) const
Retrieves the state for a particular subsystem from the context for the entire diagram.
Definition: diagram.h:585
std::unique_ptr< BasicVector< T > > AllocateInputVector(const InputPortDescriptor< T > &descriptor) const
Given a port descriptor, allocates the vector storage.
Definition: system.h:106
#define DRAKE_DEMAND(condition)
Evaluates condition and iff the value is false will trigger an assertion failure with a message showi...
Definition: drake_assert.h:45
The DiagramContext is a container for all of the data necessary to uniquely determine the computation...
Definition: diagram_context.h:118
void SetRandomState(const Context< T > &context, State< T > *state, RandomGenerator *generator) const override
Assigns random values to all elements of the state.
Definition: diagram.h:377
State is a container for all the data comprising the complete state of a particular System at a parti...
Definition: state.h:27
int GetSystemIndexOrAbort(const System< T > *sys) const
Returns the index of the given sys in this diagram, or aborts if sys is not a member of the diagram...
Definition: diagram.h:760
~DiagramTimeDerivatives() override
Definition: diagram.h:168
const OutputPortValue & get_port_value(int index) const override
Definition: diagram.h:132
void SetDefaultParameters(const Context< T > &context, Parameters< T > *params) const override
Assigns default values to all parameters.
Definition: diagram.h:328
const VectorBase< T > & get_generalized_position() const
Returns the subset of the state vector that is generalized position q.
Definition: continuous_state.h:112
Diagram is a System composed of one or more constituent Systems, arranged in a directed graph where t...
Definition: diagram.h:31
A superclass template for systems that receive input, maintain state, and produce output of a given m...
Definition: input_port_descriptor.h:12
const Context< T > * DoGetTargetSystemContext(const System< T > &target_system, const Context< T > *context) const final
Returns a pointer to const context if target_system is a subsystem of this, nullptr is returned other...
Definition: diagram.h:853
bool HasDirectFeedthrough(int output_port) const
Returns true if there might be direct-feedthrough from any input port to the given output_port...
Definition: system.h:282
BasicVector is a semantics-free wrapper around an Eigen vector that satisfies VectorBase.
Definition: basic_vector.h:25
virtual State< T > * get_mutable_state()=0
OutputPortValue * get_mutable_port_value(int index) override
Definition: diagram.h:127
State< T > * DoGetMutableTargetSystemState(const System< T > &target_system, State< T > *state) const final
Returns a pointer to mutable state if target_system is a subsystem of this, nullptr is returned other...
Definition: diagram.h:866
void GetGraphvizFragment(std::stringstream *dot) const override
Returns a Graphviz fragment describing this Diagram.
Definition: diagram.h:624
DiagramOutputPort(const DiagramOutputPort &)=delete
const State< T > * DoGetTargetSystemState(const System< T > &target_system, const State< T > *state) const final
Returns a pointer to const state if target_system is a subsystem of this, nullptr is returned otherwi...
Definition: diagram.h:879
A fully type-erased container class.
Definition: value.h:99
const ContinuousState< T > * GetSubsystemDerivatives(const ContinuousState< T > &derivatives, const System< T > *subsystem) const
Retrieves the state derivatives for a particular subsystem from the derivatives for the entire diagra...
Definition: diagram.h:523
This class bundles an instance of each EventCollection<EventType> into one object that stores the het...
Definition: event.h:22
const double time
Definition: robot_plan_interpolator_test.cc:64
virtual void GetGraphvizInputPortToken(const InputPortDescriptor< T > &port, std::stringstream *dot) const
Appends a fragment to the dot stream identifying the graphviz node representing port.
Definition: system.h:1077
std::unique_ptr< CompositeEventCollection< T > > AllocateCompositeEventCollection() const final
Allocates a DiagramEventCollection for this Diagram.
Definition: diagram.h:269
std::pair< SystemIndex, PortIndex > PortIdentifier
Definition: diagram_context.h:124
const CompositeEventCollection< T > * DoGetTargetSystemCompositeEventCollection(const System< T > &target_system, const CompositeEventCollection< T > *events) const final
Returns a pointer to const composite event collection if target_system is a subsystem of this...
Definition: diagram.h:907
void set_abstract_parameters(std::unique_ptr< AbstractValues > abstract_params)
Definition: parameters.h:126
void DoMapVelocityToQDot(const Context< T > &context, const Eigen::Ref< const VectorX< T >> &generalized_velocity, VectorBase< T > *qdot) const override
The generalized_velocity vector must have the same size and ordering as the generalized velocity in t...
Definition: diagram.h:923
Parameters is a container for variables that parameterize a System so that it can represent a family ...
Definition: parameters.h:26
PortDataType get_data_type() const
Gets the port data type specified at port construction.
Definition: output_port.h:111
An abstract base class template for the values of the output ports of a System.
Definition: output_port_value.h:123
void error(const char *, const Args &...)
Definition: text_logging.h:78
void EvaluateSubsystemInputPort(const Context< T > *context, const InputPortDescriptor< T > &descriptor) const override
Evaluates the value of the subsystem input port with the given id in the given context.
Definition: diagram.h:725
virtual std::unique_ptr< SystemOutput< T > > AllocateOutput(const Context< T > &context) const =0
Returns a container that can hold the values of all of this System&#39;s output ports.
AbstractValue & get_mutable_abstract_parameter(int index)
Returns the abstract-valued parameter at index.
Definition: parameters.h:104
virtual OutputPortValue * get_mutable_port_value(int index)=0
~DiagramDiscreteVariables() override
Definition: diagram.h:190
CompositeEventCollection< T > * DoGetMutableTargetSystemCompositeEventCollection(const System< T > &target_system, CompositeEventCollection< T > *events) const final
Returns a pointer to mutable composite event collection if target_system is a subsystem of this...
Definition: diagram.h:892
Subvector is a concrete class template that implements VectorBase by providing a sliced view of a Vec...
Definition: subvector.h:20
std::vector< std::string > names
Definition: translator_test.cc:19
const Context< T > & GetSubsystemContext(const System< T > &subsystem, const Context< T > &context) const
Returns a constant reference to the subcontext that corresponds to the system subsystem.
Definition: diagram.h:538
const VectorBase< T > & get_generalized_velocity() const
Returns the subset of the continuous state vector that is generalized velocity v. ...
Definition: continuous_state.h:124
T DoEvaluateWitness(const Context< T > &context, const WitnessFunction< T > &witness_func) const final
For the subsystem associated with witness_func, gets its subcontext from context, passes the subconte...
Definition: diagram.h:792
AbstractValue * DoAllocateInputAbstract(const InputPortDescriptor< T > &descriptor) const override
Allocates an abstract input of the leaf type that the System requires on the port specified by descri...
Definition: diagram.h:1040
This class represents a publish event.
Definition: event.h:194
const System< T > * get_system() const
Definition: input_port_descriptor.h:69
The argument to Convert need not be the exact type S that was used to populate the SystemScalarConver...
void Calc(const Context< T > &context, AbstractValue *value) const
Unconditionally computes the value of this output port with respect to the given context, into an already-allocated AbstractValue object whose concrete type must be exactly the same as the type returned by this port&#39;s allocator.
Definition: output_port.cc:29
Provides public header files of Drake&#39;s symbolic library.
InputPortEvaluatorInterface is implemented by classes that are able to evaluate the OutputPortValue c...
Definition: input_port_evaluator_interface.h:26
A SystemConstraint is a generic base-class for constraints on Systems.
Definition: system_constraint.h:55
void GetPath(std::stringstream *output) const
Writes the full path of this System in the tree of Systems to output.
Definition: system.h:891
ContinuousState is a container for all the continuous state variables xc.
Definition: continuous_state.h:44
Diagram(SystemScalarConverter converter)
(Advanced) Constructs an uninitialized Diagram.
Definition: diagram.h:785
Helper class to convert a System<U> into a System<T>, intended for internal use by the System framewo...
Definition: system_scalar_converter.h:35
int get_index() const
Definition: input_port_descriptor.h:70
const OutputPort< T > & get_output_port(int port_index) const
Returns the output port at index port_index.
Definition: system.h:929
std::unique_ptr< Context< T > > AllocateContext() const override
Allocates a context, initialized with the correct numbers of concrete input ports and state variables...
Definition: diagram.h:281
int get_num_ports() const override
Definition: diagram.h:125
static const std::string & Get()
Attempts to return a nicely demangled and canonicalized type name that is the same on all platforms...
Definition: nice_type_name.h:53
#define DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(Classname)
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN deletes the special member functions for copy-construction, copy-assignment, move-construction, and move-assignment.
Definition: drake_copyable.h:33
A tag object that denotes a System subclass S in function signatures.
Definition: system_type_tag.h:27
const System< T > & get_system() const
Returns a reference to the System that owns this output port.
Definition: output_port.h:101
Abstract class that describes a function that is able to help determine the time and state at which a...
Definition: witness_function.h:89
int size() const
Returns the fixed size expected for a vector-valued output port.
Definition: output_port.h:115
int size() const
Definition: system_constraint.h:119
void GetGraphvizInputPortToken(const InputPortDescriptor< T > &port, std::stringstream *dot) const override
Appends a fragment to the dot stream identifying the graphviz node representing port.
Definition: diagram.h:706
A type-safe non-negative index class.
Definition: type_safe_index.h:144
const CompositeEventCollection< T > & GetSubsystemCompositeEventCollection(const System< T > &subsystem, const CompositeEventCollection< T > &events) const
Returns the const subsystem composite event collection from events that corresponds to subsystem...
Definition: diagram.h:560
std::string GetPath() const
Definition: system.h:901
std::function< void(const Context< T > &context, VectorX< T > *value)> CalcCallback
This is the signature of a stateless function that evaluates the value of the constraint function f: ...
Definition: system_constraint.h:66
There are three concrete event types for any System: publish, discrete state update, and unrestricted state update, listed in order of increasing ability to change the state (i.e., zero to all).
Definition: event.h:16
int get_num_input_ports() const
Returns the number of input ports of the system.
Definition: system.h:908
State< T > & GetMutableSubsystemState(const System< T > &subsystem, State< T > *state) const
Retrieves the state for a particular subsystem from the state for the entire diagram.
Definition: diagram.h:594
OutputPortIndex get_index() const
Returns the index of this output port within the owning System.
Definition: output_port.h:106
This class represents a discrete update event.
Definition: event.h:257
Provides careful macros to selectively enable or disable the special member functions for copy-constr...