IMP  2.2.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-2014 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 /********************** RevoluteJoint ***************/
46 
47 /** Abstract class for all revolute joints **/
48 class IMPKINEMATICSEXPORT RevoluteJoint : public Joint {
49  public:
50  /**
51  constructs a revolute joint on the line connecting a and b,
52  with an initial angle 'angle'
53 
54  @param parent,child kinematic nodes upstream and downstream (resp.) of this
55  joint
56  **/
58 
59  // pure virtual dtr to declare as abstrat class for SWIG
60  virtual ~RevoluteJoint() = 0;
61 
62  /******* getter / setter methods *********/
63  public:
64  /**
65  sets the angle of the revolute joint and marks the internal
66  coordinates as changed in the kinematic forest object
67  */
68  void set_angle(double angle);
69 
70  /**
71  gets the angle of the revolute joint. This method is kinematically
72  safe (it triggers an update to internal coordinates if needed)
73  */
74  double get_angle() const;
75 
76  protected:
77  //#ifndef SWIG
78  // in global coordinates
79  const IMP::algebra::Vector3D& get_rot_axis_origin() const {
80  return rot_axis_origin_;
81  }
82 
83  // in global coordinates
84  const IMP::algebra::Vector3D& get_rot_axis_unit_vector() const {
85  return rot_axis_unit_vector_;
86  }
87  //#endif
88 
89  /****************** general protected methods ***************/
90 
91  protected:
92  /**
93  Updates the reference frame of the child node by this joint
94  angle, assuming the parent reference frame and the witnesses
95  that affect update_axis_of_rotation_from_cartesian_witnesses()
96  are all updated already
97  */
98  virtual void update_child_node_reference_frame() const;
99 
100  /**
101  this protected method updates the rot_axis_unit_vector_
102  and rot_axis_origin_ variables based on the cartesian witnesses
103  appropriate for a specific implementation of this abstract class,
104  using parent coordinates, assuming all caresian witnesses are updated
105  */
106  virtual void update_axis_of_rotation_from_cartesian_witnesses() = 0;
107 
108  /**
109  this protected method uses the cartesian witnesses to compute
110  the actual current angle of this joint (assuming external coordinates
111  of required cartesian witnesses are up to date).
112  @note this method does not update the angle stored in this joint,
113  which may be strictly different (if external or internal coords
114  are outdated)
115  */
116  virtual double get_current_angle_from_cartesian_witnesses() const = 0;
117 
118  /**
119  Update the joint internal parameters based on external reference frames
120  of witnesses and rigid bodies, assuming external parameters are updated
121  */
123  update_axis_of_rotation_from_cartesian_witnesses();
124  angle_ = get_current_angle_from_cartesian_witnesses();
125  last_updated_angle_ = angle_;
127  }
128 
129  /**
130  Returns the transformation matrix for rotating a vector in
131  parent coordinates about the axis of the joint, in a way that
132  would bring the cartesian witnesses to the correct joint angle
133  (as measured by get_angle_from_cartesian_witnesses() ).
134  */
137  IMP_LOG(VERBOSE, "get_rotation " << IMP_RAD_2_DEG(angle_)
138  << ", last_updated_angle = "
139  << IMP_RAD_2_DEG(last_updated_angle_)
140  << std::endl);
141  // rotate by the difference from last_updated_angle_
144  rot_axis_unit_vector_, angle_ - last_updated_angle_);
146  IMP::algebra::get_rotation_about_point(rot_axis_origin_, R);
147 
148  // debug prints
149  // nice_print_trans(R_origin, "R_origin: ");
150 
151  return R_origin;
152  }
153 
154  protected:
155  // the angle in Radians about the joint axis ("unit vector")
156  double angle_;
157 
158  // the angle used when the child reference frame was last up-to-date
159  // mutable cause logically does not change the state of this object
160  // (or is that so?)
161  mutable double last_updated_angle_;
162 
163  // the unit vector around which the joint revolves in parent coords
164  IMP::algebra::Vector3D rot_axis_unit_vector_;
165 
166  // the joint origin of rotation in parent coords
167  IMP::algebra::Vector3D rot_axis_origin_;
168 };
169 
170 /********************** DihedralAngleRevoluteJoint ***************/
171 // @TODO handle derivatives
172 
173 /** A revolute joint that is parametrized as a dihedral angle between
174  two planes */
175 class IMPKINEMATICSEXPORT DihedralAngleRevoluteJoint : public RevoluteJoint {
176  public:
177  /**
178  constructs a dihedral angle that revolves around the axis b-c,
179  using a,b,c,d as witnesses for the dihedral angle
180 
181  @param parent,child kinematic nodes upstream and downstream (resp.) of
182  this joint
183  @param a,b,c,d 'witnesses' whose coordinates define the dihedral
184  angle between the planes containing a-b-c and
185  b-c-d)
186 
187  @note It is assumed that neither a, b and c are downstream of child,
188  and also that d is not upstream of it
189  */
193  IMP::core::XYZ d);
194 
195  protected:
196  /**
197  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
198  in parent coordinates based on the witnesses b_ and c_,
199  using b_-c_ as the axis of rotation
200  @note it is assumed b_ and c_ have update cartesian coordinates
201  */
203  using namespace IMP::algebra;
205  get_distance(b_.get_coordinates(), c_.get_coordinates()) > 1e-12,
206  "witnesses b and c must be non identical beyone numerical error");
207  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
208  // nice_print_trans(rf_parent.get_transformation_to(), "Parent trans: ");
209  rot_axis_origin_ = rf_parent.get_local_coordinates(b_.get_coordinates());
210  IMP_LOG(VERBOSE, "global b_ " << b_.get_coordinates()
211  << " and local parent b_ " << rot_axis_origin_
212  << std::endl);
213  Vector3D v = rf_parent.get_local_coordinates(c_.get_coordinates()) -
214  rf_parent.get_local_coordinates(b_.get_coordinates());
215  rot_axis_unit_vector_ = v.get_unit_vector();
216  IMP_LOG(VERBOSE, "local axis of rot unnorm "
217  << v << " global axis "
218  << c_.get_coordinates() - b_.get_coordinates()
219  << std::endl);
220  };
221 
222  /**
223  this protected method uses the cartesian witnesses to compute
224  the actual current dihedral angle of this joint (assuming
225  external coordinates of required cartesian witnesses are up to
226  date)
227  */
228  virtual double get_current_angle_from_cartesian_witnesses() const;
229 
230  private:
231  IMP::core::XYZ a_;
232  IMP::core::XYZ b_;
233  IMP::core::XYZ c_;
234  IMP::core::XYZ d_;
235 };
236 
237 /********************** BondAngleRevoluteJoint ***************/
238 // TODO: do we want to handle derivatives?
239 
240 /** A revolute joint that is parametrized as a bond angle between three
241  particles
242  */
243 class IMPKINEMATICSEXPORT BondAngleRevoluteJoint : public RevoluteJoint {
244  public:
245  /**
246  constructs a joint that controls the angle a-b-c. The joint
247  revolves around the axis that passes through b, normal to the
248  plane containing a, b and c. a,b and c are the witnesses for the
249  bond angle.
250 
251  @param parent,child kinematic nodes upstream and downstream (resp.) of
252  this joint
253  @param a,b,c 'witnesses' whose coordinates define the joint angle a-b-c
254 
255  @note It is assumed that a and b are upstream of or inside
256  this joint's child rigid body, and that c is downstream of
257  it or inside it.
258  */
262 
263  protected:
264  /**
265  this protected method uses the cartesian witnesses to compute the
266  actual current bond angle of this joint (assuming external
267  coordinates of required cartesian witnesses are up to date)
268  */
269  virtual double get_current_angle_from_cartesian_witnesses() const;
270 
271  /**
272  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
273  using b_ as origin of rotation and a vector perpendicular to the
274  plane containing a_,b_,c_ as axis of rotation, in global
275  coordinates
276  */
278  using namespace IMP::algebra;
279 
281  get_distance(b_.get_coordinates(), c_.get_coordinates()) > 1e-12,
282  "witnesses b and c must be non identical beyond numerical error");
284  get_distance(b_.get_coordinates(), a_.get_coordinates()) > 1e-12,
285  "witnesses b and a must be non identical beyond numerical error");
286  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
287  Vector3D v =
288  rf_parent.get_local_coordinates(get_perpendicular_vector(a_, b_, c_));
289  rot_axis_unit_vector_ = v.get_unit_vector();
290  rot_axis_origin_ = rf_parent.get_local_coordinates(b_.get_coordinates());
291  };
292 
293  private:
294  static IMP::algebra::Vector3D get_perpendicular_vector(core::XYZ a,
295  core::XYZ b,
296  core::XYZ c) {
299  return IMP::algebra::get_vector_product(v1, v2);
300  }
301  IMP::core::XYZ a_;
302  IMP::core::XYZ b_;
303  IMP::core::XYZ c_;
304 };
305 
309 
310 IMPKINEMATICS_END_NAMESPACE
311 
312 #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:67
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
#define IMP_OBJECTS(Name, PluralName)
Define the types for storing sets of objects.
3D rotation class.
Definition: Rotation3D.h:46
Exception definitions and assertions.
VectorD< 3 > Vector3D
Definition: VectorD.h:395
Simple 3D vector class.
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