IMP  2.1.0
The Integrative Modeling Platform
KinematicForest.h
Go to the documentation of this file.
1 /**
2  * \file 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-2012 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 <IMP/base/set.h>
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  /**
62  Adds a kinematic edge between parent and child,
63  using a TransformationJoint between them, and
64  decorating them as KinematicNodes if needed.
65  */
66  // NOTE: must have root on first call
67  // TODO: verify parent_rb is in tree
69  {
70  // create joint and associate it with parent and child
71  IMP_NEW( TransformationJoint, joint, (parent, child) );
72  add_edge( joint );
73  return joint;
74  }
75 
76  /**
77  Adds a kinematic edge between the joint parent and child
78  rigid bodies, decorating them as KinematicNodes if needed.
79  The joint becomes owned by this KinematicForest, such that
80  changes to the joint are synchronized with the KinematicForest
81 
82  @note it is assumed that neither the joint or the rigid bodies in it
83  were previously added to a kinematic forest (might change in
84  future IMP versions)
85  */
86  void add_edge(Joint* joint);
87  /**
88  adds edges between each pair of consecutive rigid bodies in the list
89  rbs, using default TransformationJoint joints (transforming from one
90  rigid body to the next)
91 
92  @param rbs list of n consecutive rigid bodies
93  */
95  for(int i = 0 ; i < (int)rbs.size() - 1; i++){
96  add_edge( rbs[i], rbs[i+1] );
97  }
98  }
99 
100  // rebuild tree (same topology but change directionality)
101  void reset_root(IMP::kernel::Particle* new_root){
102  // TODO: implement
104  IMP_UNUSED(new_root);
105  }
106 
107  void update_all_internal_coordinates(){
108  IMP_LOG(VERBOSE, "updating internal coords needed?" << std::endl);
109  if(is_internal_coords_updated_){
110  return;
111  }
112  IMP_LOG(VERBOSE, "updating!" << std::endl);
113  for(unsigned int i = 0; i < joints_.size(); i++){
114  joints_[i]->update_joint_from_cartesian_witnesses();
115  }
116  is_internal_coords_updated_ = true;
117  }
118 
119  void update_all_external_coordinates(){
120  if(is_external_coords_updated_){
121  return;
122  }
123  // tree BFS traversal from roots
124  std::queue<KinematicNode> q;
126  for(it = roots_.begin(); it != roots_.end(); it++){
127  q.push( *it );
128  }
129  while( !q.empty() ){
130  KinematicNode n = q.front();
131  q.pop();
132  JointsTemp out_joints = n.get_out_joints();
133  for(unsigned int i = 0; i < out_joints.size(); i++){
134  Joint* joint_i = out_joints[i];
135  // TODO: add and implement to joint
136  joint_i->update_child_node_reference_frame();
137  q.push( KinematicNode(joint_i->get_child_node() ) );
138  }
139  }
140  is_external_coords_updated_ = true;
141  }
142 
143  // return joints sorted by BFS traversal
144  Joints get_ordered_joints() const {
145  Joints ret;
146  // tree BFS traversal from roots
147  std::queue<KinematicNode> q;
149  for(it = roots_.begin(); it != roots_.end(); it++) q.push(*it);
150 
151  while(!q.empty()) {
152  KinematicNode n = q.front();
153  q.pop();
154  if(n.get_in_joint() != nullptr) ret.push_back(n.get_in_joint());
155 
156  JointsTemp out_joints = n.get_out_joints();
157  for(unsigned int i = 0; i < out_joints.size(); i++) {
158  Joint* joint_i = out_joints[i];
159  q.push(KinematicNode(joint_i->get_child_node()));
160  }
161  }
162  return ret;
163  }
164 
165  /**
166  notifies the tree that joint (internal) coordinates
167  have changed and therefore external coordinates are not
168  up to date
169  */
171  is_external_coords_updated_ = false;
172  }
173 
174  /**
175  notifies the tree that external Cartesian coordinates
176  have changed and therefore internal (joint) coordinates are not
177  up to date
178  */
180  is_internal_coords_updated_ = false;
181  }
182 
183  /**
184  sets the corodinates of a particle, and makes sure that particles
185  and joints in the tree will return correct external and internal
186  coordinates
187 
188  @param rb a rigid body that was previously added to the tree
189  @param c new coordinates
190  */
191  void set_coordinates_safe
193  IMP_USAGE_CHECK( get_is_member(rb) ,
194  "A KinematicForest can only handle particles "
195  << " that were perviously added to it" );
196  rb.set_coordinates( c );
197  mark_external_coordinates_changed();
198  }
199 
200  /**
201  */
202  IMP::algebra::Vector3D get_coordinates_safe
203  ( IMP::core::RigidBody rb ) const{
204  IMP_USAGE_CHECK( get_is_member(rb) ,
205  "A KinematicForest can only handle particles "
206  << " that were perviously added to it" );
207  const_cast<KinematicForest*>(this)->update_all_external_coordinates();
208  return rb.get_coordinates();
209  }
210 
211  /**
212  */
213  bool get_is_member(IMP::core::RigidBody rb) const{
214  kernel::Particle* p = rb.get_particle();
215  return
216  KinematicNode::get_is_setup( p ) &&
217  nodes_.find( KinematicNode( p ) ) != nodes_.end() ;
218  }
219 
220  // TODO: do we want to add safe access to rigid body members?
221 
222  /**
223  */
225  get_reference_frame_safe(IMP::core::RigidBody rb) const {
226  IMP_USAGE_CHECK( get_is_member(rb) ,
227  "A KinematicForest can only handle particles "
228  << " that were perviously added to it" );
229  const_cast<KinematicForest*>(this)->update_all_external_coordinates();
230  return rb.get_reference_frame();
231  }
232 
233  /**
234  sets the reference frame of a rigid body, and makes sure that
235  particles and joints in the tree will return correct external
236  and internal coordinates when queried through the KinematicForest
237 
238  @param rb a rigid body that was previously added to the tree
239  @param r new reference frame
240  */
241  void set_reference_frame_safe
243  IMP_USAGE_CHECK( get_is_member(rb) ,
244  "A KinematicForest can only handle particles "
245  << " that were perviously added to it" );
246  rb.set_reference_frame( r );
247  mark_external_coordinates_changed();
248  }
249 
250  // TODO: handle derivatives, and safe getting / setting of them
251 
252  private:
253  IMP::kernel::Particles get_children(IMP::kernel::Particle parent) const;
254 
255  IMP::kernel::Particle get_parent(IMP::kernel::Particle child) const;
256 
257 #ifndef SWIG
258  friend std::ostream& operator<<(std::ostream& s,
259  const KinematicForest& kt);
260 #endif
261 
262  private:
263  kernel::Model* m_;
264 
265  bool is_internal_coords_updated_;
266  bool is_external_coords_updated_;
267 
268  /** the root nodes that serves as spatial anchor to the
269  kinematic trees in the forest */
271 
272  /** the set of nodes in the tree */
274 
275  Joints joints_;
276 
277 };
278 
280 
281 
282 IMPKINEMATICS_END_NAMESPACE
283 
284 #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:145
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 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:64
Various general useful macros for IMP.
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:145
Storage of a model, its restraints, constraints and particles.
Common base class for heavy weight IMP objects.
#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)
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
Declare an efficient stl-compatible set.
Class for storing model, its restraints, constraints, and particles.
IMP::algebra::ReferenceFrame3D get_reference_frame() const
Get the reference frame for the local coordinates.
Definition: rigid_bodies.h:146