IMP  2.2.0
The Integrative Modeling Platform
KinematicForest.h
Go to the documentation of this file.
1 /**
2  * \file IMP/kinematics/KinematicForest.h
3  * \brief Wrapper class for a kinematic forest (collection of trees)
4  made of KinematicNode objects, interconnected by joints. This data
5  structure allows for kinematic control of the tree and
6  interconversion between internal and external coordinates.
7  * \authors Dina Schneidman, Barak Raveh
8  *
9  * Copyright 2007-2014 IMP Inventors. All rights reserved.
10  */
11 
12 #ifndef IMPKINEMATICS_KINEMATIC_FOREST_H
13 #define IMPKINEMATICS_KINEMATIC_FOREST_H
14 
15 #include "kinematics_config.h"
16 #include <IMP/kernel/Model.h>
18 #include <IMP/kinematics/Joint.h>
20 #include <IMP/base/Object.h>
21 #include <IMP/Decorator.h>
22 #include <boost/unordered_set.hpp>
23 #include <IMP/base/exception.h>
24 #include <IMP/base/Object.h>
25 #include <IMP/base/check_macros.h>
27 #include <IMP/atom/Hierarchy.h>
28 #include <queue>
29 #include <algorithm>
30 
31 IMPKINEMATICS_BEGIN_NAMESPACE
32 
33 /**
34  An unified interface for defining and manipulating a kinematic
35  structure over a model. The kinematic structure is defined as a
36  forest over model particles at a certain hierarchy, such that a
37  directed edge indicates the propagation of changes in internal
38  coordinates (joint values) to values of external (cartesian)
39  coordinates.
40 
41  \see Joint
42  */
43 class IMPKINEMATICSEXPORT KinematicForest
44  : public base::Object // or kernel::ModelObject?
45  {
46  public:
48 
50 
51  // TODO: think about what foldtree scheme to use (star?),
52  /**
53  Builds a kinematic forest automatically from a hierarchy that
54  contains rigid bodies and adds a ScoreState to the model, to
55  make sure the internal and external coordinates are synced
56  before model updating
57  */
59 
60  /**
61  Adds a kinematic edge between parent and child,
62  using a TransformationJoint between them, and
63  decorating them as KinematicNodes if needed.
64  */
65  // NOTE: must have root on first call
66  // TODO: verify parent_rb is in tree
68  // create joint and associate it with parent and child
69  IMP_NEW(TransformationJoint, joint, (parent, child));
70  add_edge(joint);
71  return joint;
72  }
73 
74  /**
75  Adds a kinematic edge between the joint parent and child
76  rigid bodies, decorating them as KinematicNodes if needed.
77  The joint becomes owned by this KinematicForest, such that
78  changes to the joint are synchronized with the KinematicForest
79 
80  @note it is assumed that neither the joint or the rigid bodies in it
81  were previously added to a kinematic forest (might change in
82  future IMP versions)
83  */
84  void add_edge(Joint* joint);
85  /**
86  adds edges between each pair of consecutive rigid bodies in the list
87  rbs, using default TransformationJoint joints (transforming from one
88  rigid body to the next)
89 
90  @param rbs list of n consecutive rigid bodies
91  */
93  for (int i = 0; i < (int)rbs.size() - 1; i++) {
94  add_edge(rbs[i], rbs[i + 1]);
95  }
96  }
97 
98  // rebuild tree (same topology but change directionality)
99  void reset_root(IMP::kernel::Particle* new_root) {
100  // TODO: implement
102  IMP_UNUSED(new_root);
103  }
104 
105  void update_all_internal_coordinates() {
106  IMP_LOG(VERBOSE, "updating internal coords needed?" << std::endl);
107  if (is_internal_coords_updated_) {
108  return;
109  }
110  IMP_LOG(VERBOSE, "updating!" << std::endl);
111  for (unsigned int i = 0; i < joints_.size(); i++) {
112  joints_[i]->update_joint_from_cartesian_witnesses();
113  }
114  is_internal_coords_updated_ = true;
115  }
116 
117  void update_all_external_coordinates() {
118  if (is_external_coords_updated_) {
119  return;
120  }
121  // tree BFS traversal from roots
122  std::queue<KinematicNode> q;
123  boost::unordered_set<KinematicNode>::iterator it;
124  for (it = roots_.begin(); it != roots_.end(); it++) {
125  q.push(*it);
126  }
127  while (!q.empty()) {
128  KinematicNode n = q.front();
129  q.pop();
130  JointsTemp out_joints = n.get_out_joints();
131  for (unsigned int i = 0; i < out_joints.size(); i++) {
132  Joint* joint_i = out_joints[i];
133  // TODO: add and implement to joint
134  joint_i->update_child_node_reference_frame();
135  q.push(KinematicNode(joint_i->get_child_node()));
136  }
137  }
138  is_external_coords_updated_ = true;
139  }
140 
141  // return joints sorted by BFS traversal
142  Joints get_ordered_joints() const {
143  Joints ret;
144  // tree BFS traversal from roots
145  std::queue<KinematicNode> q;
146  boost::unordered_set<KinematicNode>::iterator it;
147  for (it = roots_.begin(); it != roots_.end(); it++) q.push(*it);
148 
149  while (!q.empty()) {
150  KinematicNode n = q.front();
151  q.pop();
152  if (n.get_in_joint() != nullptr) ret.push_back(n.get_in_joint());
153 
154  JointsTemp out_joints = n.get_out_joints();
155  for (unsigned int i = 0; i < out_joints.size(); i++) {
156  Joint* joint_i = out_joints[i];
157  q.push(KinematicNode(joint_i->get_child_node()));
158  }
159  }
160  return ret;
161  }
162 
163  /**
164  notifies the tree that joint (internal) coordinates
165  have changed and therefore external coordinates are not
166  up to date
167  */
169  is_external_coords_updated_ = false;
170  }
171 
172  /**
173  notifies the tree that external Cartesian coordinates
174  have changed and therefore internal (joint) coordinates are not
175  up to date
176  */
178  is_internal_coords_updated_ = false;
179  }
180 
181  /**
182  sets the corodinates of a particle, and makes sure that particles
183  and joints in the tree will return correct external and internal
184  coordinates
185 
186  @param rb a rigid body that was previously added to the tree
187  @param c new coordinates
188  */
190  IMP_USAGE_CHECK(get_is_member(rb),
191  "A KinematicForest can only handle particles "
192  << " that were perviously added to it");
193  rb.set_coordinates(c);
194  mark_external_coordinates_changed();
195  }
196 
197  /**
198  */
199  IMP::algebra::Vector3D get_coordinates_safe(IMP::core::RigidBody rb) const {
200  IMP_USAGE_CHECK(get_is_member(rb),
201  "A KinematicForest can only handle particles "
202  << " that were perviously added to it");
203  const_cast<KinematicForest*>(this)->update_all_external_coordinates();
204  return rb.get_coordinates();
205  }
206 
207  /**
208  */
209  bool get_is_member(IMP::core::RigidBody rb) const {
210  kernel::Particle* p = rb.get_particle();
211  return KinematicNode::get_is_setup(p) &&
212  nodes_.find(KinematicNode(p)) != nodes_.end();
213  }
214 
215  // TODO: do we want to add safe access to rigid body members?
216 
217  /**
218  */
219  IMP::algebra::ReferenceFrame3D get_reference_frame_safe(
220  IMP::core::RigidBody rb) const {
221  IMP_USAGE_CHECK(get_is_member(rb),
222  "A KinematicForest can only handle particles "
223  << " that were perviously added to it");
224  const_cast<KinematicForest*>(this)->update_all_external_coordinates();
225  return rb.get_reference_frame();
226  }
227 
228  /**
229  sets the reference frame of a rigid body, and makes sure that
230  particles and joints in the tree will return correct external
231  and internal coordinates when queried through the KinematicForest
232 
233  @param rb a rigid body that was previously added to the tree
234  @param r new reference frame
235  */
238  IMP_USAGE_CHECK(get_is_member(rb),
239  "A KinematicForest can only handle particles "
240  << " that were perviously added to it");
241  rb.set_reference_frame(r);
242  mark_external_coordinates_changed();
243  }
244 
245  // TODO: handle derivatives, and safe getting / setting of them
246 
247  private:
248  IMP::kernel::Particles get_children(IMP::kernel::Particle parent) const;
249 
250  IMP::kernel::Particle get_parent(IMP::kernel::Particle child) const;
251 
252 #ifndef SWIG
253  friend std::ostream& operator<<(std::ostream& s, const KinematicForest& kt);
254 #endif
255 
256  private:
257  kernel::Model* m_;
258 
259  bool is_internal_coords_updated_;
260  bool is_external_coords_updated_;
261 
262  /** the root nodes that serves as spatial anchor to the
263  kinematic trees in the forest */
264  boost::unordered_set<KinematicNode> roots_;
265 
266  /** the set of nodes in the tree */
267  boost::unordered_set<KinematicNode> nodes_;
268 
269  Joints joints_;
270 };
271 
273 
274 IMPKINEMATICS_END_NAMESPACE
275 
276 #endif /* IMPKINEMATICS_KINEMATIC_FOREST_H */
Import IMP/kernel/Decorator.h in the namespace.
#define IMP_NOT_IMPLEMENTED
Use this to make that the method is not implemented yet.
IMP::base::Vector< IMP::base::WeakPointer< Joint > > JointsTemp
Definition: Joint.h:130
Particle * get_particle() const
#define IMP_UNUSED(variable)
#define IMP_NEW(Typename, varname, args)
Declare a ref counted pointer to a new object.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
A reference frame in 3D.
a kinematic joints between rigid bodies that allows any transformation
Decorator for helping deal with a hierarchy of molecules.
void set_reference_frame_safe(IMP::core::RigidBody rb, IMP::algebra::ReferenceFrame3D r)
void add_rigid_bodies_in_chain(IMP::core::RigidBodies rbs)
functionality for defining a kinematic joint between rigid bodies as part of a kinematic tree ...
The standard decorator for manipulating molecular structures.
void set_reference_frame(const IMP::algebra::ReferenceFrame3D &tr)
Set the current reference frame.
void set_coordinates(const algebra::Vector3D &v)
set all coordinates from a vector
Definition: XYZ.h:62
Various general useful macros for IMP.
void set_coordinates_safe(IMP::core::RigidBody rb, IMP::algebra::Vector3D c)
functionality for defining nodes on a kinematic chain
#define IMP_OBJECT_METHODS(Name)
Define the basic things needed by any Object.
Class to handle individual model particles.
IMP::base::Vector< IMP::base::Pointer< Joint > > Joints
Definition: Joint.h:130
Storage of a model, its restraints, constraints and particles.
Common base class for heavy weight IMP objects.
Definition: base/Object.h:106
#define IMP_OBJECTS(Name, PluralName)
Define the types for storing sets of objects.
Exception definitions and assertions.
Joint * add_edge(IMP::core::RigidBody parent, IMP::core::RigidBody child)
VectorD< 3 > Vector3D
Definition: VectorD.h:395
Exception definitions and assertions.
A shared base class to help in debugging and things.
A decorator for a rigid body.
Definition: rigid_bodies.h:75
Class for storing model, its restraints, constraints, and particles.
Definition: kernel/Model.h:72
IMP::algebra::ReferenceFrame3D get_reference_frame() const
Get the reference frame for the local coordinates.
Definition: rigid_bodies.h:192