IMP  2.1.0
The Integrative Modeling Platform
revolute_joints.h
Go to the documentation of this file.
1 /**
2  * \file kinematics/revolute_joints.h
3  * \brief functionality for defining various revolute kinematic
4  * joints between rigid bodies as part of a kinematic tree,
5  * including RevoluteJoint, DihedralAngleRevoluteJoint, and
6  * BondAngleRevoluteJoint
7  * \authors Dina Schneidman, Barak Raveh
8  *
9 
10  * Copyright 2007-2012 IMP Inventors. All rights reserved.
11  */
12 
13 #ifndef IMPKINEMATICS_REVOLUTE_JOINTS_H
14 #define IMPKINEMATICS_REVOLUTE_JOINTS_H
15 
16 #include "kinematics_config.h"
18 #include <IMP/kinematics/Joint.h>
19 #include <IMP/base/Object.h>
20 //#include <IMP/compatibility/nullptr.h>
21 #include <IMP/base/exception.h>
22 #include <IMP/core/internal/dihedral_helpers.h>
23 #include <IMP/algebra/Vector3D.h>
24 #include <IMP/base/check_macros.h>
25 
26 // TODO: for debug only = remove later
27 #define IMP_RAD_2_DEG(a) 180*a/IMP::algebra::PI
28 #define IMP_DEG_2_RAD(a) a*IMP::algebra::PI/180
29 
30 IMPKINEMATICS_BEGIN_NAMESPACE
31 
32 class KinematicForest;
33 
34 // inline void nice_print_trans(const IMP::algebra::Transformation3D& T,
35 // std::string description)
36 // {
37 // std::pair< IMP::algebra::Vector3D, double > aa;
38 // aa = IMP::algebra::get_axis_and_angle( T.get_rotation() );
39 // IMP_LOG( VERBOSE, description << "axis = " << aa.first
40 // << "; angle = " << IMP_RAD_2_DEG(aa.second) << " deg"
41 // << "; translation = " << T.get_translation()
42 // << std::endl );
43 // }
44 
45 
46 /********************** RevoluteJoint ***************/
47 
48 
49 /** Abstract class for all revolute joints **/
50 class IMPKINEMATICSEXPORT RevoluteJoint :
51 public Joint{
52  public:
53  /**
54  constructs a revolute joint on the line connecting a and b,
55  with an initial angle 'angle'
56 
57  @param parent,child kinematic nodes upstream and downstream (resp.) of this
58  joint
59  **/
61  IMP::core::RigidBody child);
62 
63 
64  // pure virtual dtr to declare as abstrat class for SWIG
65  virtual ~RevoluteJoint() = 0;
66 
67 
68  /******* getter / setter methods *********/
69  public:
70 
71  /**
72  sets the angle of the revolute joint and marks the internal
73  coordinates as changed in the kinematic forest object
74  */
75  void set_angle(double angle);
76 
77  /**
78  gets the angle of the revolute joint. This method is kinematically
79  safe (it triggers an update to internal coordinates if needed)
80  */
81  double get_angle() const;
82 
83  protected:
84  //#ifndef SWIG
85  // in global coordinates
86  const IMP::algebra::Vector3D& get_rot_axis_origin() const
87  { return rot_axis_origin_; }
88 
89  // in global coordinates
90  const IMP::algebra::Vector3D& get_rot_axis_unit_vector() const
91  { return rot_axis_unit_vector_; }
92  //#endif
93 
94  /****************** general protected methods ***************/
95 
96  protected:
97  /**
98  Updates the reference frame of the child node by this joint
99  angle, assuming the parent reference frame and the witnesses
100  that affect update_axis_of_rotation_from_cartesian_witnesses()
101  are all updated already
102  */
103  virtual void update_child_node_reference_frame() const;
104 
105  /**
106  this protected method updates the rot_axis_unit_vector_
107  and rot_axis_origin_ variables based on the cartesian witnesses
108  appropriate for a specific implementation of this abstract class,
109  using parent coordinates, assuming all caresian witnesses are updated
110  */
111  virtual void update_axis_of_rotation_from_cartesian_witnesses() = 0;
112 
113  /**
114  this protected method uses the cartesian witnesses to compute
115  the actual current angle of this joint (assuming external coordinates
116  of required cartesian witnesses are up to date).
117  @note this method does not update the angle stored in this joint,
118  which may be strictly different (if external or internal coords
119  are outdated)
120  */
121  virtual double get_current_angle_from_cartesian_witnesses() const = 0;
122 
123 
124  /**
125  Update the joint internal parameters based on external reference frames
126  of witnesses and rigid bodies, assuming external parameters are updated
127  */
129  update_axis_of_rotation_from_cartesian_witnesses();
130  angle_ = get_current_angle_from_cartesian_witnesses();
131  last_updated_angle_ = angle_;
133  }
134 
135  /**
136  Returns the transformation matrix for rotating a vector in
137  parent coordinates about the axis of the joint, in a way that
138  would bring the cartesian witnesses to the correct joint angle
139  (as measured by get_angle_from_cartesian_witnesses() ).
140  */
143  {
144  IMP_LOG( VERBOSE, "get_rotation " << IMP_RAD_2_DEG(angle_)
145  << ", last_updated_angle = "
146  << IMP_RAD_2_DEG(last_updated_angle_) << std::endl );
147  // rotate by the difference from last_updated_angle_
150  ( rot_axis_unit_vector_, angle_ - last_updated_angle_ );
152  IMP::algebra::get_rotation_about_point(rot_axis_origin_, R);
153 
154  // debug prints
155  //nice_print_trans(R_origin, "R_origin: ");
156 
157  return R_origin;
158  }
159 
160 
161  protected:
162  // the angle in Radians about the joint axis ("unit vector")
163  double angle_;
164 
165  // the angle used when the child reference frame was last up-to-date
166  // mutable cause logically does not change the state of this object
167  // (or is that so?)
168  mutable double last_updated_angle_;
169 
170  // the unit vector around which the joint revolves in parent coords
171  IMP::algebra::Vector3D rot_axis_unit_vector_;
172 
173  // the joint origin of rotation in parent coords
174  IMP::algebra::Vector3D rot_axis_origin_;
175 };
176 
177 
178 
179 /********************** DihedralAngleRevoluteJoint ***************/
180 // @TODO handle derivatives
181 
182 /** A revolute joint that is parametrized as a dihedral angle between
183  two planes */
184 class IMPKINEMATICSEXPORT
186  public:
187  /**
188  constructs a dihedral angle that revolves around the axis b-c,
189  using a,b,c,d as witnesses for the dihedral angle
190 
191  @param parent,child kinematic nodes upstream and downstream (resp.) of
192  this joint
193  @param a,b,c,d 'witnesses' whose coordinates define the dihedral
194  angle between the planes containing a-b-c and
195  b-c-d)
196 
197  @note It is assumed that neither a, b and c are downstream of child,
198  and also that d is not upstream of it
199  */
203 
204  protected:
205  /**
206  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
207  in parent coordinates based on the witnesses b_ and c_,
208  using b_-c_ as the axis of rotation
209  @note it is assumed b_ and c_ have update cartesian coordinates
210  */
212  using namespace IMP::algebra;
214  ( get_distance( b_.get_coordinates(), c_.get_coordinates() )
215  > 1e-12 ,
216  "witnesses b and c must be non identical beyone numerical error" );
217  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
218  //nice_print_trans(rf_parent.get_transformation_to(), "Parent trans: ");
219  rot_axis_origin_ = rf_parent.get_local_coordinates( b_.get_coordinates() );
220  IMP_LOG( VERBOSE, "global b_ " << b_.get_coordinates()
221  << " and local parent b_ " << rot_axis_origin_ << std::endl);
222  Vector3D v =
223  rf_parent.get_local_coordinates( c_.get_coordinates() )
224  - rf_parent.get_local_coordinates( b_.get_coordinates() );
225  rot_axis_unit_vector_ = v.get_unit_vector();
226  IMP_LOG( VERBOSE, "local axis of rot unnorm " << v
227  << " global axis " << c_.get_coordinates() - b_.get_coordinates()
228  << std::endl );
229  };
230 
231  /**
232  this protected method uses the cartesian witnesses to compute
233  the actual current dihedral angle of this joint (assuming
234  external coordinates of required cartesian witnesses are up to
235  date)
236  */
237  virtual double get_current_angle_from_cartesian_witnesses() const;
238 
239 
240  private:
241  IMP::core::XYZ a_;
242  IMP::core::XYZ b_;
243  IMP::core::XYZ c_;
244  IMP::core::XYZ d_;
245 };
246 
247 /********************** BondAngleRevoluteJoint ***************/
248 // TODO: do we want to handle derivatives?
249 
250 /** A revolute joint that is parametrized as a bond angle between three
251  particles
252  */
253 class IMPKINEMATICSEXPORT BondAngleRevoluteJoint : public RevoluteJoint{
254  public:
255  /**
256  constructs a joint that controls the angle a-b-c. The joint
257  revolves around the axis that passes through b, normal to the
258  plane containing a, b and c. a,b and c are the witnesses for the
259  bond angle.
260 
261  @param parent,child kinematic nodes upstream and downstream (resp.) of
262  this joint
263  @param a,b,c 'witnesses' whose coordinates define the joint angle a-b-c
264 
265  @note It is assumed that a and b are upstream of or inside
266  this joint's child rigid body, and that c is downstream of
267  it or inside it.
268  */
272 
273  protected:
274 
275  /**
276  this protected method uses the cartesian witnesses to compute the
277  actual current bond angle of this joint (assuming external
278  coordinates of required cartesian witnesses are up to date)
279  */
280  virtual double get_current_angle_from_cartesian_witnesses() const;
281 
282  /**
283  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
284  using b_ as origin of rotation and a vector perpendicular to the
285  plane containing a_,b_,c_ as axis of rotation, in global
286  coordinates
287  */
289  using namespace IMP::algebra;
290 
292  ( get_distance( b_.get_coordinates(), c_.get_coordinates() )
293  > 1e-12 ,
294  "witnesses b and c must be non identical beyond numerical error" );
296  ( get_distance( b_.get_coordinates(), a_.get_coordinates() )
297  > 1e-12 ,
298  "witnesses b and a must be non identical beyond numerical error" );
299  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
300  Vector3D v = rf_parent.get_local_coordinates
301  ( get_perpendicular_vector(a_, b_, c_) );
302  rot_axis_unit_vector_ = v.get_unit_vector();
303  rot_axis_origin_ = rf_parent.get_local_coordinates
304  ( b_.get_coordinates() );
305  };
306 
307  private:
308 
310  get_perpendicular_vector(core::XYZ a, core::XYZ b, core::XYZ c)
311  {
313  v1 = a.get_coordinates() - b.get_coordinates();
315  v2 = c.get_coordinates() - b.get_coordinates();
316  return IMP::algebra::get_vector_product(v1, v2);
317  }
318  IMP::core::XYZ a_;
319  IMP::core::XYZ b_;
320  IMP::core::XYZ c_;
321 };
322 
323 
324 
328 
329 IMPKINEMATICS_END_NAMESPACE
330 
331 #endif /* IMPKINEMATICS_REVOLUTE_JOINTS_H */
Rotation3D get_rotation_about_normalized_axis(const Vector3D &axis_norm, double angle)
Simple 3D transformation class.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
A reference frame in 3D.
virtual void update_joint_from_cartesian_witnesses()
virtual void update_axis_of_rotation_from_cartesian_witnesses()
Transformation2D get_rotation_about_point(const Vector2D &point, const Rotation2D &rotation)
Generates a Transformation2D object from a rotation around a point.
Vector3D get_local_coordinates(const Vector3D &v) const
double get_distance(const Plane3D &pln, const Vector3D &p)
Return the distance between a plane and a point in 3D.
Definition: Plane3D.h:68
Vector3D get_vector_product(const Vector3D &p1, const Vector3D &p2)
Returns the vector product (cross product) of two vectors.
Definition: Vector3D.h:31
functionality for defining a kinematic joint between rigid bodies as part of a kinematic tree ...
IMP::algebra::Transformation3D get_rotation_about_joint_in_parent_coordinates() const
virtual void update_joint_from_cartesian_witnesses()
functionality for defining nodes on a kinematic chain
A decorator for a particle with x,y,z coordinates.
Definition: XYZ.h:32
const algebra::Vector3D & get_coordinates() const
Convert it to a vector.
Definition: XYZ.h:109
virtual double get_current_angle_from_cartesian_witnesses() const =0
virtual void update_child_node_reference_frame() const
#define IMP_OBJECTS(Name, PluralName)
Define the types for storing sets of objects.
3D rotation class.
Definition: Rotation3D.h:45
Exception definitions and assertions.
Simple 3D vector class.
VectorD get_unit_vector() const
Definition: VectorD.h:204
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