IMP  2.4.0
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-2015 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/base/exception.h>
21 #include <IMP/core/internal/dihedral_helpers.h>
22 #include <IMP/algebra/Vector3D.h>
23 #include <IMP/base/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  protected:
195  /**
196  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
197  in parent coordinates based on the witnesses b_ and c_,
198  using b_-c_ as the axis of rotation
199  @note it is assumed b_ and c_ have update Cartesian coordinates
200  */
202  using namespace IMP::algebra;
204  get_distance(b_.get_coordinates(), c_.get_coordinates()) > 1e-12,
205  "witnesses b and c must be non identical beyond numerical error");
206  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
207  // nice_print_trans(rf_parent.get_transformation_to(), "Parent trans: ");
208  rot_axis_origin_ = rf_parent.get_local_coordinates(b_.get_coordinates());
209  IMP_LOG(VERBOSE, "global b_ " << b_.get_coordinates()
210  << " and local parent b_ " << rot_axis_origin_
211  << std::endl);
212  Vector3D v = rf_parent.get_local_coordinates(c_.get_coordinates()) -
213  rf_parent.get_local_coordinates(b_.get_coordinates());
214  rot_axis_unit_vector_ = v.get_unit_vector();
215  IMP_LOG(VERBOSE, "local axis of rot unnorm "
216  << v << " global axis "
217  << c_.get_coordinates() - b_.get_coordinates()
218  << std::endl);
219  };
220 
221  /**
222  this protected method uses the Cartesian witnesses to compute
223  the actual current dihedral angle of this joint (assuming
224  external coordinates of required Cartesian witnesses are up to
225  date)
226  */
227  virtual double get_current_angle_from_cartesian_witnesses() const;
228 
229  private:
230  IMP::core::XYZ a_;
231  IMP::core::XYZ b_;
232  IMP::core::XYZ c_;
233  IMP::core::XYZ d_;
234 };
235 
236 /********************** BondAngleRevoluteJoint ***************/
237 // TODO: do we want to handle derivatives?
238 
239 /** A revolute joint that is parameterized as a bond angle between three
240  particles
241  */
242 class IMPKINEMATICSEXPORT BondAngleRevoluteJoint : public RevoluteJoint {
243  public:
244  /**
245  constructs a joint that controls the angle a-b-c. The joint
246  revolves around the axis that passes through b, normal to the
247  plane containing a, b and c. a,b and c are the witnesses for the
248  bond angle.
249 
250  @param parent,child kinematic nodes upstream and downstream (resp.) of
251  this joint
252  @param a,b,c 'witnesses' whose coordinates define the joint angle a-b-c
253 
254  @note It is assumed that a and b are upstream of or inside
255  this joint's child rigid body, and that c is downstream of
256  it or inside it.
257  */
261 
262  protected:
263  /**
264  this protected method uses the Cartesian witnesses to compute the
265  actual current bond angle of this joint (assuming external
266  coordinates of required Cartesian witnesses are up to date)
267  */
268  virtual double get_current_angle_from_cartesian_witnesses() const;
269 
270  /**
271  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
272  using b_ as origin of rotation and a vector perpendicular to the
273  plane containing a_,b_,c_ as axis of rotation, in global
274  coordinates
275  */
277  using namespace IMP::algebra;
278 
280  get_distance(b_.get_coordinates(), c_.get_coordinates()) > 1e-12,
281  "witnesses b and c must be non identical beyond numerical error");
283  get_distance(b_.get_coordinates(), a_.get_coordinates()) > 1e-12,
284  "witnesses b and a must be non identical beyond numerical error");
285  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
286  Vector3D v =
287  rf_parent.get_local_coordinates(get_perpendicular_vector(a_, b_, c_));
288  rot_axis_unit_vector_ = v.get_unit_vector();
289  rot_axis_origin_ = rf_parent.get_local_coordinates(b_.get_coordinates());
290  };
291 
292  private:
293  static IMP::algebra::Vector3D get_perpendicular_vector(core::XYZ a,
294  core::XYZ b,
295  core::XYZ c) {
298  return IMP::algebra::get_vector_product(v1, v2);
299  }
300  IMP::core::XYZ a_;
301  IMP::core::XYZ b_;
302  IMP::core::XYZ c_;
303 };
304 
308 
309 IMPKINEMATICS_END_NAMESPACE
310 
311 #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:71
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:107
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:52
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:170
A decorator for a rigid body.
Definition: rigid_bodies.h:75