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