Simbody  3.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Assembler.h
Go to the documentation of this file.
1 #ifndef SimTK_SIMBODY_ASSEMBLER_H_
2 #define SimTK_SIMBODY_ASSEMBLER_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm) *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2010-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
27 #include "SimTKcommon.h"
31 
32 #include <set>
33 #include <map>
34 #include <cassert>
35 #include <cmath>
36 
37 namespace SimTK {
38 
39 SimTK_DEFINE_UNIQUE_INDEX_TYPE(AssemblyConditionIndex);
40 
41 class AssemblyCondition;
42 
149  typedef std::set<MobilizedBodyIndex> LockedMobilizers;
150  typedef std::set<MobilizerQIndex> QSet;
151  typedef std::map<MobilizedBodyIndex, QSet> LockedQs;
152  typedef std::map<MobilizerQIndex, Vec2> QRanges;
153  typedef std::map<MobilizedBodyIndex, QRanges> RestrictedQs;
154 public:
155 
158 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Assembler,FreeQIndex);
159 
163 class AssembleFailed;
167 class TrackFailed;
168 
186 explicit Assembler(const MultibodySystem& system);
187 
197 Assembler& setErrorTolerance(Real tolerance=0) {
198  SimTK_ERRCHK1_ALWAYS(0 <= tolerance,
199  "Assembler::setTolerance()", "The requested error tolerance %g"
200  " is illegal; we require 0 <= tolerance, with 0 indicating that"
201  " the default tolerance (accuracy/10) is to be used.", tolerance);
202  this->tolerance = tolerance;
203  return *this;
204 }
209 Real getErrorToleranceInUse() const {
210  return tolerance > 0 ? tolerance
211  : (accuracy > 0 ? accuracy/10 : Real(0.1)/OODefaultAccuracy);
212 }
213 
223 Assembler& setAccuracy(Real accuracy=0) {
224  SimTK_ERRCHK2_ALWAYS(0 <= accuracy && accuracy < 1,
225  "Assembler::setAccuracy()", "The requested accuracy %g is illegal;"
226  " we require 0 <= accuracy < 1, with 0 indicating that the default"
227  " accuracy (%g) is to be used.", Real(1)/OODefaultAccuracy, accuracy);
228  this->accuracy = accuracy;
229  return *this;
230 }
233 Real getAccuracyInUse() const
234 { return accuracy > 0 ? accuracy : Real(1)/OODefaultAccuracy; }
235 
236 
244 { assert(systemConstraints.isValid());
245  setAssemblyConditionWeight(systemConstraints,weight);
246  return *this; }
247 
252 { assert(systemConstraints.isValid());
253  return getAssemblyConditionWeight(systemConstraints); }
254 
261 Assembler& setAssemblyConditionWeight(AssemblyConditionIndex condition,
262  Real weight) {
263  SimTK_INDEXCHECK_ALWAYS(condition, conditions.size(),
264  "Assembler::setAssemblyConditionWeight()");
265  SimTK_ERRCHK1_ALWAYS(weight >= 0, "Assembler::setAssemblyConditionWeight()",
266  "Illegal weight %g; weight must be nonnegative.", weight);
267  uninitialize();
268  weights[condition] = weight;
269  return *this;
270 }
271 
278 Real getAssemblyConditionWeight(AssemblyConditionIndex condition) const {
279  SimTK_INDEXCHECK_ALWAYS(condition, conditions.size(),
280  "Assembler::getAssemblyConditionWeight()");
281  return weights[condition];
282 }
283 
288 AssemblyConditionIndex
289  adoptAssemblyError(AssemblyCondition* p);
298 AssemblyConditionIndex
299  adoptAssemblyGoal(AssemblyCondition* p, Real weight=1);
300 
301 
308  uninitialize();
309  getMatterSubsystem().convertToEulerAngles(state, internalState);
310  system.realizeModel(internalState);
311  return *this;
312 }
319 void initialize() const;
322 void initialize(const State& state)
323 { setInternalState(state); initialize(); }
330 
337 Real assemble();
338 
347 Real track(Real frameTime = -1);
348 
355 Real assemble(State& state) {
356  setInternalState(state);
357  Real achievedCost = assemble(); // throws if it fails
358  updateFromInternalState(state);
359  return achievedCost;
360 }
361 
362 
366 Real calcCurrentGoal() const;
375 Real calcCurrentErrorNorm() const;
376 
377 
382 void updateFromInternalState(State& state) const {
383  system.realizeModel(state); // allocates q's if they haven't been yet
384  if (!getMatterSubsystem().getUseEulerAngles(state)) {
385  State tempState;
386  getMatterSubsystem().convertToQuaternions(getInternalState(),
387  tempState);
388  state.updQ() = tempState.getQ();
389  } else
390  state.updQ() = getInternalState().getQ();
391 }
401 
406 { uninitialize(); userLockedMobilizers.insert(mbx); }
413 { uninitialize(); userLockedMobilizers.erase(mbx); }
414 
427 { uninitialize(); userLockedQs[mbx].insert(qx); }
428 
434 { LockedQs::iterator p = userLockedQs.find(mbx);
435  if (p == userLockedQs.end()) return;
436  QSet& qs = p->second;
437  if (qs.erase(qx)) { // returns 0 if nothing erased
438  uninitialize();
439  if (qs.empty())
440  userLockedQs.erase(p); // remove the whole mobilized body
441  }
442 }
443 
450  Real lowerBound, Real upperBound)
451 { SimTK_ERRCHK2_ALWAYS(lowerBound <= upperBound, "Assembler::restrictQ()",
452  "The given range [%g,%g] is illegal because the lower bound is"
453  " greater than the upper bound.", lowerBound, upperBound);
454  if (lowerBound == -Infinity && upperBound == Infinity)
455  { unrestrictQ(mbx,qx); return; }
456  uninitialize();
457  userRestrictedQs[mbx][qx] = Vec2(lowerBound,upperBound);
458 }
459 
460 
466 { RestrictedQs::iterator p = userRestrictedQs.find(mbx);
467  if (p == userRestrictedQs.end()) return;
468  QRanges& qranges = p->second;
469  if (qranges.erase(qx)) { // returns 0 if nothing erased
470  uninitialize();
471  if (qranges.empty())
472  userRestrictedQs.erase(p); // remove the whole mobilized body
473  }
474 }
487 int getNumGoalEvals() const;
489 int getNumErrorEvals() const;
491 int getNumGoalGradientEvals() const;
493 int getNumErrorJacobianEvals() const;
496 int getNumAssemblySteps() const;
499 int getNumInitializations() const;
503 void resetStats() const;
511 
515 { forceNumericalGradient = yesno; }
519 { forceNumericalJacobian = yesno; }
520 
526 void setUseRMSErrorNorm(bool yesno)
527 { useRMSErrorNorm = yesno; }
531 bool isUsingRMSErrorNorm() const {return useRMSErrorNorm;}
532 
537 void uninitialize() const;
540 bool isInitialized() const {return alreadyInitialized;}
541 
548 const State& getInternalState() const {return internalState;}
549 
553 void addReporter(const EventReporter& reporter) {
554  reporters.push_back(&reporter);
555 }
556 
560 int getNumFreeQs() const
561 { return freeQ2Q.size(); }
562 
566 QIndex getQIndexOfFreeQ(FreeQIndex freeQIndex) const
567 { return freeQ2Q[freeQIndex]; }
568 
573 FreeQIndex getFreeQIndexOfQ(QIndex qx) const
574 { return q2FreeQ[qx]; }
575 
578 Vec2 getFreeQBounds(FreeQIndex freeQIndex) const {
579  if (!lower.size()) return Vec2(-Infinity, Infinity);
580  else return Vec2(lower[freeQIndex], upper[freeQIndex]);
581 }
582 
587 { return system; }
591 { return system.getMatterSubsystem(); }
596 ~Assembler();
597 
598 
599 
600 //------------------------------------------------------------------------------
601  private: // methods
602 //------------------------------------------------------------------------------
603 void setInternalStateFromFreeQs(const Vector& freeQs) {
604  assert(freeQs.size() == getNumFreeQs());
605  Vector& q = internalState.updQ();
606  for (FreeQIndex fx(0); fx < getNumFreeQs(); ++fx)
607  q[getQIndexOfFreeQ(fx)] = freeQs[fx];
608  system.realize(internalState, Stage::Position);
609 }
610 
611 Vector getFreeQsFromInternalState() const {
612  Vector freeQs(getNumFreeQs());
613  const Vector& q = internalState.getQ();
614  for (FreeQIndex fx(0); fx < getNumFreeQs(); ++fx)
615  freeQs[fx] = q[getQIndexOfFreeQ(fx)];
616  return freeQs;
617 }
618 
619 void reinitializeWithExtraQsLocked
620  (const Array_<QIndex>& toBeLocked) const;
621 
622 
623 
624 //------------------------------------------------------------------------------
625  private: // data members
626 //------------------------------------------------------------------------------
627 const MultibodySystem& system;
628 Array_<const EventReporter*> reporters; // just references; don't delete
629 
630 // These members affect the behavior of the assembly algorithm.
631 static const int OODefaultAccuracy = 1000; // 1/accuracy if acc==0
632 Real accuracy; // 0 means use 1/OODefaultAccuracy
633 Real tolerance; // 0 means use accuracy/10
634 bool forceNumericalGradient; // ignore analytic gradient methods
635 bool forceNumericalJacobian; // ignore analytic Jacobian methods
636 bool useRMSErrorNorm; // what norm defines success?
637 
638 // Changes to any of these data members set isInitialized()=false.
639 State internalState;
640 
641 // These are the mobilizers that were set in lockMobilizer(). They are
642 // separate from those involved in individually-locked q's.
643 LockedMobilizers userLockedMobilizers;
644 // These are locks placed on individual q's; they are independent of the
645 // locked mobilizer settings.
646 LockedQs userLockedQs;
647 // These are range restrictions placed on individual q's.
648 RestrictedQs userRestrictedQs;
649 
650 // These are (condition,weight) pairs with weight==Infinity meaning
651 // constraint; weight==0 meaning currently ignored; and any other
652 // positive weight meaning a goal.
653 Array_<AssemblyCondition*,AssemblyConditionIndex>
654  conditions;
655 Array_<Real,AssemblyConditionIndex> weights;
656 
657 // We always have an assembly condition for the Constraints which are
658 // enabled in the System; this is the index which can be used to
659 // retrieve that condition. The default weight is Infinity.
660 AssemblyConditionIndex systemConstraints;
661 
662 
663 // These are filled in when the Assembler is initialized.
664 mutable bool alreadyInitialized;
665 
666 // These are extra q's we removed for numerical reasons.
667 mutable Array_<QIndex> extraQsLocked;
668 
669 // These represent restrictions on the independent variables (q's).
670 mutable std::set<QIndex> lockedQs;
671 mutable Array_<FreeQIndex,QIndex> q2FreeQ; // nq of these
672 mutable Array_<QIndex,FreeQIndex> freeQ2Q; // nfreeQ of these
673 // 0 length if no bounds; otherwise, index by FreeQIndex.
674 mutable Vector lower, upper;
675 
676 // These represent the active assembly conditions.
677 mutable Array_<AssemblyConditionIndex> errors;
678 mutable Array_<int> nTermsPerError;
679 mutable Array_<AssemblyConditionIndex> goals;
680 
681 class AssemblerSystem; // local class
682 mutable AssemblerSystem* asmSys;
683 mutable Optimizer* optimizer;
684 
685 mutable int nAssemblySteps; // count assemble() and track() calls
686 mutable int nInitializations; // # times we had to reinitialize
687 
688 friend class AssemblerSystem;
689 };
690 
691 
692 
693 //------------------------------------------------------------------------------
694 // ASSEMBLY CONDITION
695 //------------------------------------------------------------------------------
703 public:
704 
707 explicit AssemblyCondition(const String& name)
708 : name(name), assembler(0) {}
709 
711 virtual ~AssemblyCondition() {}
712 
719 virtual int initializeCondition() const {return 0;}
720 
723 virtual void uninitializeCondition() const {}
724 
733 virtual int calcErrors(const State& state, Vector& err) const
734 { return -1; }
735 
745 virtual int calcErrorJacobian(const State& state, Matrix& jacobian) const
746 { return -1; }
747 
755 virtual int getNumErrors(const State& state) const
756 { Vector err;
757  const int status = calcErrors(state, err);
758  if (status == 0)
759  return err.size();
760  SimTK_ERRCHK1_ALWAYS(status != -1, "AssemblyCondition::getNumErrors()",
761  "The default implementation of getNumErrors() depends on"
762  " calcErrors() but that method was not implemented for assembly"
763  " condition '%s'.", name.c_str());
764  SimTK_ERRCHK2_ALWAYS(status == 0, "AssemblyCondition::getNumErrors()",
765  "The default implementation of getNumErrors() uses calcErrors()"
766  " which returned status %d (assembly condition '%s').",
767  status, name.c_str());
768  return -1; // NOTREACHED
769 }
770 
775 virtual int calcGoal(const State& state, Real& goal) const
776 { static Vector err;
777  const int status = calcErrors(state, err);
778  if (status == 0)
779  { goal = err.normSqr() / std::max(1,err.size());
780  return 0; }
781  SimTK_ERRCHK1_ALWAYS(status != -1, "AssemblyCondition::calcGoal()",
782  "The default implementation of calcGoal() depends on calcErrors()"
783  " but that method was not implemented for assembly condition '%s'.",
784  name.c_str());
785  SimTK_ERRCHK2_ALWAYS(status == 0, "AssemblyCondition::calcGoal()",
786  "The default implementation of calcGoal() uses calcErrors() which"
787  " returned status %d (assembly condition '%s').",
788  status, name.c_str());
789  return -1; // NOTREACHED
790 }
791 
798 virtual int calcGoalGradient(const State& state, Vector& gradient) const
799 { return -1; }
800 
802 const char* getName() const {return name.c_str();}
803 
806 bool isInAssembler() const {return assembler != 0;}
810 const Assembler& getAssembler() const
811 { assert(assembler); return *assembler;}
815 AssemblyConditionIndex getAssemblyConditionIndex() const
816 { return myAssemblyConditionIndex; }
817 
818 //------------------------------------------------------------------------------
819  protected:
820 //------------------------------------------------------------------------------
821 // These are useful when writing concrete AssemblyConditions.
822 
825 int getNumFreeQs() const {return getAssembler().getNumFreeQs();}
829 QIndex getQIndexOfFreeQ(Assembler::FreeQIndex fx) const
830 { return getAssembler().getQIndexOfFreeQ(fx); }
834 Assembler::FreeQIndex getFreeQIndexOfQ(QIndex qx) const
835 { return getAssembler().getFreeQIndexOfQ(qx); }
838 { return getAssembler().getMultibodySystem(); }
842 { return getMultibodySystem().getMatterSubsystem(); }
843 
846 void initializeAssembler() const {
847  // The Assembler will in turn invoke initializeCondition().
848  if (isInAssembler()) getAssembler().initialize();
849  else initializeCondition();
850 }
851 
855 void uninitializeAssembler() const {
856  // The Assembler will in turn invoke uninitializeCondition().
857  if (isInAssembler()) getAssembler().uninitialize();
858  else uninitializeCondition();
859 }
860 
861 //------------------------------------------------------------------------------
862  private:
863 //------------------------------------------------------------------------------
864 // This method is used by the Assembler when the AssemblyCondition object
865 // is adopted.
866 friend class Assembler;
867 void setAssembler(const Assembler& assembler, AssemblyConditionIndex acx) {
868  assert(!this->assembler);
869  this->assembler = &assembler;
870  this->myAssemblyConditionIndex = acx;
871 }
872 
873 String name; // assembly condition name
874 const Assembler* assembler;
875 AssemblyConditionIndex myAssemblyConditionIndex;
876 };
877 
878 
879 
880 //------------------------------------------------------------------------------
881 // Q VALUE
882 //------------------------------------------------------------------------------
886 class QValue : public AssemblyCondition {
887 public:
892  Real value)
893  : AssemblyCondition("QValue"),
894  mobodIndex(mbx), qIndex(qx), value(value) {}
895 
898  Real getValue() const {return value;}
901  void setValue(Real newValue) {value=newValue;}
902 
903  // For constraint:
904  int getNumEquations(const State&) const {return 1;}
905  int calcErrors(const State& state, Vector& error) const {
906  const SimbodyMatterSubsystem& matter = getMatterSubsystem();
907  const MobilizedBody& mobod = matter.getMobilizedBody(mobodIndex);
908  error.resize(1);
909  error[0] = mobod.getOneQ(state, qIndex) - value;
910  return 0;
911  }
912  // Error jacobian is a zero-row except for a 1 in this q's entry (if
913  // this q is free).
914  int calcErrorJacobian(const State& state, Matrix& J) const {
915  const SimbodyMatterSubsystem& matter = getMatterSubsystem();
916  const MobilizedBody& mobod = matter.getMobilizedBody(mobodIndex);
917  J.resize(1, getNumFreeQs());
918  J = 0; // will have at most one non-zero
919 
920  // Find the FreeQIndex corresponding to this q.
921  const QIndex thisIx = QIndex(mobod.getFirstQIndex(state)+qIndex);
922  const Assembler::FreeQIndex thisFreeIx = getFreeQIndexOfQ(thisIx);
923 
924  // If this q isn't free then there is no way to affect the error
925  // so the Jacobian stays all-zero.
926  if (thisFreeIx.isValid())
927  J(0,thisFreeIx) = 1;
928 
929  return 0;
930  }
931 
932  // For goal: goal = (q-value)^2 / 2 (the /2 is for gradient beauty)
933  int calcGoal(const State& state, Real& goal) const {
934  const SimbodyMatterSubsystem& matter = getMatterSubsystem();
935  const MobilizedBody& mobod = matter.getMobilizedBody(mobodIndex);
936  goal = square(mobod.getOneQ(state, qIndex) - value) / 2;
937  return 0;
938  }
939  // Return a gradient with only this q's entry non-zero (if
940  // this q is free).
941  int calcGoalGradient(const State& state, Vector& grad) const {
942  const SimbodyMatterSubsystem& matter = getMatterSubsystem();
943  const MobilizedBody& mobod = matter.getMobilizedBody(mobodIndex);
944  grad.resize(getNumFreeQs());
945  grad = 0; // will have at most one non-zero
946 
947  // Find the FreeQIndex corresponding to this q.
948  const QIndex thisIx = QIndex(mobod.getFirstQIndex(state)+qIndex);
949  const Assembler::FreeQIndex thisFreeIx = getFreeQIndexOfQ(thisIx);
950 
951  // If this q isn't free then there is no way to affect the goal
952  // so the gradient stays all-zero.
953  if (thisFreeIx.isValid())
954  grad[thisFreeIx] = mobod.getOneQ(state, qIndex) - value;
955 
956  return 0;
957  }
958 
959 private:
960  MobilizedBodyIndex mobodIndex;
961  MobilizerQIndex qIndex;
962  Real value;
963 };
964 
965 
966 
967 //------------------------------------------------------------------------------
968 // MARKERS
969 //------------------------------------------------------------------------------
1013 
1014 // This is a private class used in the implementation below but not
1015 // accessible through the API.
1016 struct Marker {
1017  Marker(const String& name, MobilizedBodyIndex bodyB,
1018  const Vec3& markerInB, Real weight = 1)
1019  : name(name), bodyB(bodyB), markerInB(markerInB), weight(weight)
1020  { assert(weight >= 0); }
1021 
1022  Marker(MobilizedBodyIndex bodyB, const Vec3& markerInB, Real weight=1)
1023  : name(""), bodyB(bodyB), markerInB(markerInB), weight(weight)
1024  { assert(weight >= 0); }
1025 
1026  String name;
1027  MobilizedBodyIndex bodyB;
1028  Vec3 markerInB;
1029  Real weight;
1030 };
1031 
1032 public:
1033 
1035 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Markers,MarkerIx);
1037 SimTK_DEFINE_UNIQUE_LOCAL_INDEX_TYPE(Markers,ObservationIx);
1038 
1039 
1040 
1041 //------------------------------------------------------------------------------
1047 
1051 Markers() : AssemblyCondition("Markers") {}
1052 
1072 MarkerIx addMarker(const String& name, MobilizedBodyIndex bodyB,
1073  const Vec3& markerInB, Real weight=1)
1074 { SimTK_ERRCHK1_ALWAYS(isFinite(weight) && weight >= 0,
1075  "Markers::addMarker()", "Illegal marker weight %g.", weight);
1076  uninitializeAssembler();
1077  // Forget any previously-established observation/marker correspondence.
1078  observation2marker.clear(); marker2observation.clear();
1079  observations.clear();
1080  const MarkerIx ix(markers.size());
1081  String nm = String::trimWhiteSpace(name);
1082  if (nm.empty())
1083  nm = String("_UNNAMED_") + String(ix);
1084 
1085  std::pair< std::map<String,MarkerIx>::iterator, bool >
1086  found = markersByName.insert(std::make_pair(nm,ix));
1087  SimTK_ERRCHK2_ALWAYS(found.second, // true if insertion was done
1088  "Markers::addMarker()",
1089  "Marker name '%s' was already use for Marker %d.",
1090  nm.c_str(), (int)found.first->second);
1091 
1092  markers.push_back(Marker(nm,bodyB,markerInB,weight));
1093  return ix;
1094 }
1095 
1100 MarkerIx addMarker(MobilizedBodyIndex bodyB, const Vec3& markerInB,
1101  Real weight=1)
1102 { return addMarker("", bodyB, markerInB, weight); }
1103 
1104 
1125 void defineObservationOrder(const Array_<MarkerIx>& observationOrder) {
1126  uninitializeAssembler();
1127  if (observationOrder.empty()) {
1128  observation2marker.resize(markers.size());
1129  for (MarkerIx mx(0); mx < markers.size(); ++mx)
1130  observation2marker[ObservationIx(mx)] = mx;
1131  } else
1132  observation2marker = observationOrder;
1133  marker2observation.clear();
1134  // We might need to grow this more, but this is an OK starting guess.
1135  marker2observation.resize(observation2marker.size()); // all invalid
1136  for (ObservationIx ox(0); ox < observation2marker.size(); ++ox) {
1137  const MarkerIx mx = observation2marker[ox];
1138  if (!mx.isValid()) continue;
1139 
1140  if (marker2observation.size() <= mx)
1141  marker2observation.resize(mx+1);
1142  SimTK_ERRCHK4_ALWAYS(!marker2observation[mx].isValid(),
1143  "Markers::defineObservationOrder()",
1144  "An attempt was made to associate Marker %d (%s) with"
1145  " Observations %d and %d; only one Observation per Marker"
1146  " is permitted.",
1147  (int)mx, getMarkerName(mx).c_str(),
1148  (int)marker2observation[mx], (int)ox);
1149 
1150  marker2observation[mx] = ox;
1151  }
1152  // Make room for marker observations.
1153  observations.clear();
1154  observations.resize(observation2marker.size(),Vec3(NaN));
1155 }
1156 
1162 void defineObservationOrder(const Array_<String>& observationOrder)
1163 { Array_<MarkerIx> markerIxs(observationOrder.size());
1164  for (ObservationIx ox(0); ox < observationOrder.size(); ++ox)
1165  markerIxs[ox] = getMarkerIx(observationOrder[ox]);
1166  defineObservationOrder(markerIxs); }
1167 
1169 // no copy required
1170 void defineObservationOrder(const std::vector<String>& observationOrder)
1171 { defineObservationOrder(ArrayViewConst_<String>(observationOrder)); }
1172 
1173 
1175 // must copy
1176 void defineObservationOrder(const Array_<std::string>& observationOrder)
1177 { const Array_<String> observations(observationOrder); // copy
1178  defineObservationOrder(observations); }
1179 
1181 // must copy
1182 void defineObservationOrder(const std::vector<std::string>& observationOrder)
1183 { const Array_<String> observations(observationOrder); // copy
1184  defineObservationOrder(observations); }
1185 
1187 void defineObservationOrder(int n, const char* const observationOrder[])
1188 { Array_<MarkerIx> markerIxs(n);
1189  for (ObservationIx ox(0); ox < n; ++ox)
1190  markerIxs[ox] = getMarkerIx(String(observationOrder[ox]));
1191  defineObservationOrder(markerIxs); }
1196 //------------------------------------------------------------------------------
1203 
1206 int getNumMarkers() const {return markers.size();}
1207 
1211 const String& getMarkerName(MarkerIx ix)
1212 { return markers[ix].name; }
1216 const MarkerIx getMarkerIx(const String& name)
1217 { std::map<String,MarkerIx>::const_iterator p = markersByName.find(name);
1218  return p == markersByName.end() ? MarkerIx() : p->second; }
1219 
1222 Real getMarkerWeight(MarkerIx mx)
1223 { return markers[mx].weight; }
1224 
1227 { return markers[mx].bodyB; }
1228 
1230 const Vec3& getMarkerStation(MarkerIx mx) const
1231 { return markers[mx].markerInB; }
1232 
1238 int getNumObservations() const {return observation2marker.size();}
1239 
1245 ObservationIx getObservationIxForMarker(MarkerIx mx) const
1246 { return marker2observation[mx]; }
1247 
1250 bool hasObservation(MarkerIx mx) const
1251 { return getObservationIxForMarker(mx).isValid(); }
1252 
1258 MarkerIx getMarkerIxForObservation(ObservationIx ox) const
1259 { return observation2marker[ox]; }
1260 
1263 bool hasMarker(ObservationIx ox) const
1264 { return getMarkerIxForObservation(ox).isValid();}
1265 
1271  static const Array_<MarkerIx> empty;
1272  SimTK_ERRCHK_ALWAYS(isInAssembler(), "Markers::getMarkersOnBody()",
1273  "This method can't be called until the Markers object has been"
1274  " adopted by an Assembler.");
1275  initializeAssembler();
1276  PerBodyMarkers::const_iterator bodyp = bodiesWithMarkers.find(mbx);
1277  return bodyp == bodiesWithMarkers.end() ? empty : bodyp->second;
1278 }
1283 //------------------------------------------------------------------------------
1289 
1293 void moveOneObservation(ObservationIx ox, const Vec3& observation)
1294 { SimTK_ERRCHK_ALWAYS(!observations.empty(), "Assembler::moveOneObservation()",
1295  "There are currently no observations defined. Either the Assembler"
1296  " needs to be initialized to get the default observation order, or you"
1297  " should call defineObservationOrder() explicitly.");
1298  SimTK_ERRCHK2_ALWAYS(ox.isValid() && ox < observations.size(),
1299  "Assembler::moveOneObservation()", "ObservationIx %d is invalid or"
1300  " out of range; there are %d observations currently defined. Use"
1301  " defineObservationOrder() to specify the set of observations and how"
1302  " they correspond to markers.",
1303  (int)ox, (int)observations.size());
1304  observations[ox] = observation;
1305 }
1306 
1316 void moveAllObservations(const Array_<Vec3>& observations)
1317 { SimTK_ERRCHK2_ALWAYS((int)observations.size() == (int)observation2marker.size(),
1318  "Markers::moveAllObservations()",
1319  "Number of observations provided (%d) differs from the number of"
1320  " observations (%d) last defined with defineObservationOrder().",
1321  observations.size(), observation2marker.size());
1322  this->observations = observations; }
1323 
1333 void changeMarkerWeight(MarkerIx mx, Real weight) {
1334  SimTK_ERRCHK1_ALWAYS(isFinite(weight) && weight >= 0,
1335  "Markers::changeMarkerWeight()", "Illegal marker weight %g.", weight);
1336 
1337  Marker& marker = markers[mx];
1338  if (marker.weight == weight)
1339  return;
1340 
1341  if (marker.weight == 0 || weight == 0)
1342  uninitializeAssembler(); // qualitative change
1343 
1344  marker.weight = weight;
1345 }
1346 
1351 const Vec3& getObservation(ObservationIx ox) const {return observations[ox];}
1359 { return observations; }
1360 
1364 Vec3 findCurrentMarkerLocation(MarkerIx mx) const;
1365 
1375 Real findCurrentMarkerError(MarkerIx mx) const
1376 { return std::sqrt(findCurrentMarkerErrorSquared(mx)); }
1377 
1385 Real findCurrentMarkerErrorSquared(MarkerIx mx) const {
1386  const ObservationIx ox = getObservationIxForMarker(mx);
1387  if (!ox.isValid()) return 0; // no observation for this marker
1388  const Vec3& loc = getObservation(ox);
1389  if (!loc.isFinite()) return 0; // NaN in observation; error is ignored
1390  return (findCurrentMarkerLocation(mx) - loc).normSqr();
1391 }
1396 //------------------------------------------------------------------------------
1400 int calcErrors(const State& state, Vector& err) const;
1401 int calcErrorJacobian(const State& state, Matrix& jacobian) const;
1402 int getNumErrors(const State& state) const;
1403 int calcGoal(const State& state, Real& goal) const;
1404 int calcGoalGradient(const State& state, Vector& grad) const;
1405 int initializeCondition() const;
1406 void uninitializeCondition() const;
1409 //------------------------------------------------------------------------------
1410  private:
1411 //------------------------------------------------------------------------------
1412 const Marker& getMarker(MarkerIx i) const {return markers[i];}
1413 Marker& updMarker(MarkerIx i) {uninitializeAssembler(); return markers[i];}
1414 
1415  // data members
1416 
1417 // Marker definition. Any change here except a quantitative change to the
1418 // marker's weight uninitializes the Assembler.
1419 Array_<Marker,MarkerIx> markers;
1420 std::map<String,MarkerIx> markersByName;
1421 
1422 // Observation-marker corresondence specification. Any change here
1423 // uninitializes the Assembler.
1424 Array_<MarkerIx,ObservationIx> observation2marker;
1425 
1426 // For convience in mapping from a marker to its corresponding observation.
1427 // ObservationIx will be invalid if a particular marker has no associated
1428 // observation.
1429 Array_<ObservationIx,MarkerIx> marker2observation;
1430 
1431 // This is the current set of marker location observations, one per entry in
1432 // the observation2marker array. Changing the values here does not uninitialize
1433 // the Assembler.
1434 Array_<Vec3,ObservationIx> observations;
1435 
1436 // After initialize, this groups the markers by body and weeds out
1437 // any zero-weighted markers. TODO: skip low-weighted markers, at
1438 // least at the start of the assembly.
1439 typedef std::map<MobilizedBodyIndex,Array_<MarkerIx> > PerBodyMarkers;
1440 mutable PerBodyMarkers bodiesWithMarkers;
1441 };
1442 
1443 } // namespace SimTK
1444 
1445 #endif // SimTK_SIMBODY_ASSEMBLER_H_
void unlockQ(MobilizedBodyIndex mbx, MobilizerQIndex qx)
Unlock one of this mobilizer's q's if it was locked.
Definition: Assembler.h:433
const Vec3 & getMarkerStation(MarkerIx mx) const
Get the station (fixed location in its body frame) of the given marker.
Definition: Assembler.h:1230
Vector & updQ(SubsystemIndex)
bool isFinite() const
Return true if no element of this Vec contains an Infinity or a NaN anywhere.
Definition: Vec.h:887
Real getOneQ(const State &state, int which) const
Return one of the generalized coordinates q from this mobilizer's partition of the matter subsystem's...
void lockQ(MobilizedBodyIndex mbx, MobilizerQIndex qx)
Lock one of this mobilizer's q's at its initial value.
Definition: Assembler.h:426
#define SimTK_ERRCHK2_ALWAYS(cond, whereChecked, fmt, a1, a2)
Definition: ExceptionMacros.h:289
void unlockMobilizer(MobilizedBodyIndex mbx)
Unlock this mobilizer as a whole; some of its q's may remain locked if they were locked individually...
Definition: Assembler.h:412
This is for arrays indexed by mobilized body number within a subsystem (typically the SimbodyMatterSu...
SimTK_DEFINE_UNIQUE_INDEX_TYPE(AssemblyConditionIndex)
void initializeAssembler() const
Call this method before doing anything that logically requires the Assembler, or at least this Assemb...
Definition: Assembler.h:846
QIndex getFirstQIndex(const State &state) const
Return the global QIndex of the first q for this mobilizer; all the q's range from getFirstQIndex() t...
void initialize(const State &state)
Set the internal State and initialize.
Definition: Assembler.h:322
Assembler & setErrorTolerance(Real tolerance=0)
Set the assembly error tolerance.
Definition: Assembler.h:197
QIndex getQIndexOfFreeQ(Assembler::FreeQIndex fx) const
Ask the assembler where to find the actual q in the State that corresponds to a given free q; only va...
Definition: Assembler.h:829
int getNumEquations(const State &) const
Definition: Assembler.h:904
const SimbodyMatterSubsystem & getMatterSubsystem() const
Real findCurrentMarkerErrorSquared(MarkerIx mx) const
Using the current value of the internal state, calculate the (unweighted) square of the distance betw...
Definition: Assembler.h:1385
This AssemblyCondition specifies a correspondence between stations on mobilized bodies ("markers") an...
Definition: Assembler.h:1012
#define SimTK_ERRCHK1_ALWAYS(cond, whereChecked, fmt, a1)
Definition: ExceptionMacros.h:285
Real getMarkerWeight(MarkerIx mx)
Get the weight currently in use for the specified marker; this can be changed dynamically via changeM...
Definition: Assembler.h:1222
void addReporter(const EventReporter &reporter)
Given a reference to an EventReporter, use this Reporter to provide progress reporting.
Definition: Assembler.h:553
ScalarNormSq normSqr() const
This is the scalar Frobenius norm, and its square.
Definition: BigMatrix.h:899
bool isInAssembler() const
Test whether this AssemblyCondition has already been adopted by an Assembler.
Definition: Assembler.h:806
void updateFromInternalState(State &state) const
Given an existing State that is suitable for the Assembler's System, update its q's from those found ...
Definition: Assembler.h:382
void defineObservationOrder(const std::vector< std::string > &observationOrder)
Define observation order using an std::vector of std::string.
Definition: Assembler.h:1182
void changeMarkerWeight(MarkerIx mx, Real weight)
Change the weight associated with a particular marker.
Definition: Assembler.h:1333
void realize(const State &state, Stage stage=Stage::HighestRuntime) const
Realize the given state to the indicated stage.
MobilizedBodyIndex getMarkerBody(MarkerIx mx) const
Get the MobilizedBodyIndex of the body associated with this marker.
Definition: Assembler.h:1226
Real getSystemConstraintsWeight() const
Return the current weight being given to the System's built-in Constraints; the default is Infinity...
Definition: Assembler.h:251
int size() const
Definition: BigMatrix.h:1411
const Array_< MarkerIx > & getMarkersOnBody(MobilizedBodyIndex mbx)
The Markers assembly condition organizes the markers by body after initialization; call this to get t...
Definition: Assembler.h:1270
Assembler & setAssemblyConditionWeight(AssemblyConditionIndex condition, Real weight)
Set the weight to be used for this AssemblyCondition.
Definition: Assembler.h:261
Assembler & setInternalState(const State &state)
Set the Assembler's internal state from an existing state which must be suitable for use with the Ass...
Definition: Assembler.h:307
AssemblyCondition(const String &name)
Base class constructor just takes the assembly condition name and saves it.
Definition: Assembler.h:707
#define SimTK_ERRCHK4_ALWAYS(cond, whereChecked, fmt, a1, a2, a3, a4)
Definition: ExceptionMacros.h:297
Every Simbody header and source file should include this header before any other Simbody header...
Vec2 getFreeQBounds(FreeQIndex freeQIndex) const
Return the allowable range for a particular free q.
Definition: Assembler.h:578
size_type size() const
Return the current number of elements stored in this array.
Definition: Array.h:2014
This Study attempts to find a configuration (set of joint coordinates q) of a Simbody MultibodySystem...
Definition: Assembler.h:148
MarkerIx addMarker(MobilizedBodyIndex bodyB, const Vec3 &markerInB, Real weight=1)
Define an unnamed marker.
Definition: Assembler.h:1100
const MobilizedBody & getMobilizedBody(MobilizedBodyIndex) const
Given a MobilizedBodyIndex, return a read-only (const) reference to the corresponding MobilizedBody w...
const MultibodySystem & getMultibodySystem() const
Return a reference to the MultibodySystem associated with this Assembler (that is, the System that was supplied in the Assembler's constructor.
Definition: Assembler.h:586
bool isUsingRMSErrorNorm() const
Determine whether we are currently using the RMS norm for constraint errors; if not we're using the d...
Definition: Assembler.h:531
void defineObservationOrder(const Array_< String > &observationOrder)
Define the meaning of the observations by giving the marker name corresponding to each observation...
Definition: Assembler.h:1162
Real assemble(State &state)
Given an initial value for the State, modify the q's in it to satisfy all the assembly conditions to ...
Definition: Assembler.h:355
virtual int initializeCondition() const
This is called whenever the Assembler is initialized in case this assembly condition wants to do some...
Definition: Assembler.h:719
Vec< 2 > Vec2
Definition: SmallMatrix.h:103
void setForceNumericalGradient(bool yesno)
This is useful for debugging but should not be used otherwise since the analytic gradient is to be pr...
Definition: Assembler.h:514
This is the handle class for the hidden State implementation.
Definition: State.h:264
virtual ~AssemblyCondition()
Destructor is virtual for use by derived classes.
Definition: Assembler.h:711
const Real NaN
This is the IEEE "not a number" constant for this implementation of the default-precision Real type; ...
unsigned char square(unsigned char u)
Definition: Scalar.h:351
const SimbodyMatterSubsystem & getMatterSubsystem() const
Ask the assembler for the MultibodySystem with which it is associated and extract the SimbodyMatterSu...
Definition: Assembler.h:841
AssemblyConditionIndex getAssemblyConditionIndex() const
Return the AssemblyConditionIndex of this concrete AssemblyCondition within the Assembler that has ad...
Definition: Assembler.h:815
const Vec3 & getObservation(ObservationIx ox) const
Return the current value of the location for this observation.
Definition: Assembler.h:1351
virtual int getNumErrors(const State &state) const
Override to supply an efficient method for determining how many errors will be returned by calcErrors...
Definition: Assembler.h:755
bool isFinite(const negator< float > &x)
Definition: negator.h:287
int calcGoal(const State &state, Real &goal) const
Calculate the current contribution (>= 0) of this assembly condition to the goal value that is being ...
Definition: Assembler.h:933
void moveAllObservations(const Array_< Vec3 > &observations)
Set the observed marker locations for a new observation frame.
Definition: Assembler.h:1316
int calcErrorJacobian(const State &state, Matrix &J) const
Override to supply an analytic Jacobian for the assembly errors returned by calcErrors().
Definition: Assembler.h:914
QValue(MobilizedBodyIndex mbx, MobilizerQIndex qx, Real value)
Construct an assembly condition that requests that the specified generalized coordinate be brought to...
Definition: Assembler.h:891
Includes internal headers providing declarations for the basic SimTK Core classes, including Simmatrix.
void unrestrictQ(MobilizedBodyIndex mbx, MobilizerQIndex qx)
Unrestrict a particular generalized coordinate q if it was previously restricted. ...
Definition: Assembler.h:465
void defineObservationOrder(int n, const char *const observationOrder[])
Define observation order using a C array of const char* names.
Definition: Assembler.h:1187
const MarkerIx getMarkerIx(const String &name)
Return the marker index associated with the given marker name.
Definition: Assembler.h:1216
const Assembler & getAssembler() const
Return the Assembler that has adopted this AssemblyCondition.
Definition: Assembler.h:810
ObservationIx getObservationIxForMarker(MarkerIx mx) const
Return the ObservationIx of the observation that is currently associated with the given marker...
Definition: Assembler.h:1245
Vector_< Real > Vector
Read fixed-size VectorView from input stream.
Definition: BigMatrix.h:3541
The SimTK::Array_<T> container class is a plug-compatible replacement for the C++ standard template l...
Definition: Array.h:50
#define SimTK_ERRCHK_ALWAYS(cond, whereChecked, msg)
Definition: ExceptionMacros.h:281
const MultibodySystem & getMultibodySystem() const
Ask the assembler for the MultibodySystem with which it is associated.
Definition: Assembler.h:837
void uninitializeAssembler() const
Call this when modifying any parameter of the concrete AssemblyCondition that would require reinitial...
Definition: Assembler.h:855
Real getErrorToleranceInUse() const
Obtain the tolerance setting that will be used during the next assemble() or track() call...
Definition: Assembler.h:209
Spatial configuration available.
Definition: Stage.h:58
void realizeModel(State &state) const
Realize the model to be used for subsequent computations with the given state.
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
void setValue(Real newValue)
Change the value to be used for this generalized coordinate; this can be done repeatedly during track...
Definition: Assembler.h:901
The job of the MultibodySystem class is to coordinate the activities of various subsystems which can ...
Definition: MultibodySystem.h:48
const Array_< Vec3, ObservationIx > & getAllObservations() const
Return the current values of all the observed locations.
Definition: Assembler.h:1358
QIndex getQIndexOfFreeQ(FreeQIndex freeQIndex) const
Return the absolute q index associated with a free q.
Definition: Assembler.h:566
int getNumFreeQs() const
Return the number of q's which are free to be changed by this already-initialized assembly analysis...
Definition: Assembler.h:560
virtual int calcGoalGradient(const State &state, Vector &gradient) const
Override to supply an analytic gradient for this assembly condition's goal.
Definition: Assembler.h:798
Unique integer type for Subsystem-local q indexing.
virtual void uninitializeCondition() const
This is called whenever the containing Assembler is uninitialized in case this assembly condition has...
Definition: Assembler.h:723
Markers()
The default constructor creates an empty Markers AssemblyCondition object that should be filled in wi...
Definition: Assembler.h:1051
void moveOneObservation(ObservationIx ox, const Vec3 &observation)
Move a single marker's observed location without moving any of the others.
Definition: Assembler.h:1293
bool hasObservation(MarkerIx mx) const
Return true if the supplied marker is currently associated with an observation.
Definition: Assembler.h:1250
This is the Matrix class intended to appear in user code.
Definition: BigMatrix.h:181
int getNumObservations() const
Return the number of observations that were defined via the last call to defineObservationOrder().
Definition: Assembler.h:1238
#define SimTK_INDEXCHECK_ALWAYS(ix, ub, where)
Definition: ExceptionMacros.h:106
const Real Infinity
This is the IEEE positive infinity constant for this implementation of the default-precision Real typ...
This Array_ helper class is the base class for ArrayView_ which is the base class for Array_; here we...
Definition: Array.h:48
SimTK::String is a plug-compatible std::string replacement (plus some additional functionality) inten...
Definition: String.h:62
Real getAccuracyInUse() const
Obtain the accuracy setting that will be used during the next assemble() or track() call...
Definition: Assembler.h:233
Real getAssemblyConditionWeight(AssemblyConditionIndex condition) const
Return the weight currently in use for this AssemblyCondition.
Definition: Assembler.h:278
int getNumFreeQs() const
Ask the assembler how many free q's there are; only valid after initialization but does not invoke in...
Definition: Assembler.h:825
void lockMobilizer(MobilizedBodyIndex mbx)
Lock this mobilizer at its starting position.
Definition: Assembler.h:405
void setUseRMSErrorNorm(bool yesno)
Use an RMS norm for the assembly errors rather than the default infinity norm (max absolute value)...
Definition: Assembler.h:526
void defineObservationOrder(const Array_< std::string > &observationOrder)
Define observation order using an Array_ of std::string.
Definition: Assembler.h:1176
An EventReporter is an object that defines an event that can occur within a system.
Definition: EventReporter.h:53
int calcGoalGradient(const State &state, Vector &grad) const
Override to supply an analytic gradient for this assembly condition's goal.
Definition: Assembler.h:941
#define SimTK_SIMBODY_EXPORT
Definition: Simbody/include/simbody/internal/common.h:72
Definition: Study.h:56
void clear()
Erase all the elements currently in this array without changing the capacity; equivalent to erase(beg...
Definition: Array.h:2492
void restrictQ(MobilizedBodyIndex mbx, MobilizerQIndex qx, Real lowerBound, Real upperBound)
Restrict a q to remain within a given range.
Definition: Assembler.h:449
const String & getMarkerName(MarkerIx ix)
Return the unique marker name assigned to the marker whose index is provided.
Definition: Assembler.h:1211
virtual int calcErrorJacobian(const State &state, Matrix &jacobian) const
Override to supply an analytic Jacobian for the assembly errors returned by calcErrors().
Definition: Assembler.h:745
The Mobilizer associated with each MobilizedBody, once modeled, has a specific number of generalized ...
A MobilizedBody is Simbody's fundamental body-and-joint object used to parameterize a system's motion...
Definition: MobilizedBody.h:167
void setForceNumericalJacobian(bool yesno)
This is useful for debugging but should not be used otherwise since the analytic Jacobian is to be pr...
Definition: Assembler.h:518
int calcErrors(const State &state, Vector &error) const
Calculate the amount by which this assembly condition is violated by the q values in the given state...
Definition: Assembler.h:905
const Vector & getQ(SubsystemIndex) const
Per-subsystem access to the global shared variables.
String & trimWhiteSpace()
Trim this String in place, removing all the initial leading and trailing white space, as defined by std::isspace() which typically includes space, tab (\t), newline (\n), return (\r), and form feed (\f).
Vec< 3 > Vec3
Definition: SmallMatrix.h:104
MarkerIx addMarker(const String &name, MobilizedBodyIndex bodyB, const Vec3 &markerInB, Real weight=1)
Define a new marker attached to a particular MobilizedBody.
Definition: Assembler.h:1072
const State & getInternalState() const
This provides read-only access to the Assembler's internal State; you probably should use updateFromI...
Definition: Assembler.h:548
VectorBase & resize(int m)
Definition: BigMatrix.h:1466
Define an assembly condition consisting of a scalar goal and/or a related set of assembly error equat...
Definition: Assembler.h:702
const char * getName() const
Return the name assigned to this AssemblyCondition on construction.
Definition: Assembler.h:802
MarkerIx getMarkerIxForObservation(ObservationIx ox) const
Return the MarkerIx of the marker that is associated with the given observation, or an invalid index ...
Definition: Assembler.h:1258
Real findCurrentMarkerError(MarkerIx mx) const
Using the current value of the internal state, calculate the distance between the given marker's curr...
Definition: Assembler.h:1375
This subsystem contains the bodies ("matter") in the multibody system, the mobilizers (joints) that d...
Definition: SimbodyMatterSubsystem.h:130
FreeQIndex getFreeQIndexOfQ(QIndex qx) const
A subset of the q's will be used as free q's for solving the assembly problem.
Definition: Assembler.h:573
bool isInitialized() const
Check whether the Assembler has been initialized since the last change was made to its contents...
Definition: Assembler.h:540
virtual int calcErrors(const State &state, Vector &err) const
Calculate the amount by which this assembly condition is violated by the q values in the given state...
Definition: Assembler.h:733
MatrixBase & resize(int m, int n)
Change the size of this matrix.
Definition: BigMatrix.h:950
This AssemblyCondition requests that a particular generalized coordinate end up with a specified valu...
Definition: Assembler.h:886
virtual int calcGoal(const State &state, Real &goal) const
Calculate the current contribution (>= 0) of this assembly condition to the goal value that is being ...
Definition: Assembler.h:775
bool empty() const
Return true if there are no elements currently stored in this array.
Definition: Array.h:2019
Assembler & setSystemConstraintsWeight(Real weight)
Change how the System's enabled built-in Constraints are weighted as compared to other assembly condi...
Definition: Assembler.h:243
int getNumMarkers() const
Return a count n of the number of currently-defined markers.
Definition: Assembler.h:1206
void defineObservationOrder(const Array_< MarkerIx > &observationOrder)
Define the meaning of the observation data by giving the MarkerIx associated with each observation...
Definition: Assembler.h:1125
const SimbodyMatterSubsystem & getMatterSubsystem() const
Return a reference to the SimbodyMatterSubsystem that is contained in the MultibodySystem that is ass...
Definition: Assembler.h:590
Assembler & setAccuracy(Real accuracy=0)
Set the accuracy to which a solution should be pursued.
Definition: Assembler.h:223
Assembler::FreeQIndex getFreeQIndexOfQ(QIndex qx) const
Ask the assembler where to find the free q (if any) that corresponds to a given q in the State; only ...
Definition: Assembler.h:834
Real getValue() const
Return the currently set value to be used for this generalized coordinate.
Definition: Assembler.h:898
void defineObservationOrder(const std::vector< String > &observationOrder)
Define observation order using an std::vector of SimTK::String.
Definition: Assembler.h:1170
bool hasMarker(ObservationIx ox) const
Return true if the supplied observation is currently associated with a marker.
Definition: Assembler.h:1263