IMP logo
IMP Reference Guide  2.14.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-2020 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  //! Construct on the line connecting a and b, with an initial angle 'angle'
50  /**
51  @param parent,child kinematic nodes upstream and downstream (resp.) of this
52  joint
53  **/
55 
56  // pure virtual dtr to declare as abstract class for SWIG
57  virtual ~RevoluteJoint() = 0;
58 
59  /******* getter / setter methods *********/
60  public:
61  /**
62  sets the angle of the revolute joint and marks the internal
63  coordinates as changed in the kinematic forest object
64  */
65  void set_angle(double angle);
66 
67  /**
68  gets the angle of the revolute joint. This method is kinematically
69  safe (it triggers an update to internal coordinates if needed)
70  */
71  double get_angle() const;
72 
73  protected:
74  //#ifndef SWIG
75  // in global coordinates
76  const IMP::algebra::Vector3D& get_rot_axis_origin() const {
77  return rot_axis_origin_;
78  }
79 
80  // in global coordinates
81  const IMP::algebra::Vector3D& get_rot_axis_unit_vector() const {
82  return rot_axis_unit_vector_;
83  }
84  //#endif
85 
86  /****************** general protected methods ***************/
87 
88  protected:
89  /**
90  Updates the reference frame of the child node by this joint
91  angle, assuming the parent reference frame and the witnesses
92  that affect update_axis_of_rotation_from_cartesian_witnesses()
93  are all updated already
94  */
95  virtual void update_child_node_reference_frame() const;
96 
97  /**
98  this protected method updates the rot_axis_unit_vector_
99  and rot_axis_origin_ variables based on the Cartesian witnesses
100  appropriate for a specific implementation of this abstract class,
101  using parent coordinates, assuming all Cartesian witnesses are updated
102  */
103  virtual void update_axis_of_rotation_from_cartesian_witnesses() = 0;
104 
105  /**
106  this protected method uses the Cartesian witnesses to compute
107  the actual current angle of this joint (assuming external coordinates
108  of required Cartesian witnesses are up to date).
109  @note this method does not update the angle stored in this joint,
110  which may be strictly different (if external or internal coords
111  are outdated)
112  */
113  virtual double get_current_angle_from_cartesian_witnesses() const = 0;
114 
115  /**
116  Update the joint internal parameters based on external reference frames
117  of witnesses and rigid bodies, assuming external parameters are updated
118  */
120  update_axis_of_rotation_from_cartesian_witnesses();
121  angle_ = get_current_angle_from_cartesian_witnesses();
122  last_updated_angle_ = angle_;
124  }
125 
126  /**
127  Returns the transformation matrix for rotating a vector in
128  parent coordinates about the axis of the joint, in a way that
129  would bring the Cartesian witnesses to the correct joint angle
130  (as measured by get_angle_from_cartesian_witnesses() ).
131  */
134  IMP_LOG(VERBOSE, "get_rotation " << IMP_RAD_2_DEG(angle_)
135  << ", last_updated_angle = "
136  << IMP_RAD_2_DEG(last_updated_angle_)
137  << std::endl);
138  // rotate by the difference from last_updated_angle_
141  rot_axis_unit_vector_, angle_ - last_updated_angle_);
143  IMP::algebra::get_rotation_about_point(rot_axis_origin_, R);
144 
145  // debug prints
146  // nice_print_trans(R_origin, "R_origin: ");
147 
148  return R_origin;
149  }
150 
151  protected:
152  // the angle in Radians about the joint axis ("unit vector")
153  double angle_;
154 
155  // the angle used when the child reference frame was last up-to-date
156  // mutable cause logically does not change the state of this object
157  // (or is that so?)
158  mutable double last_updated_angle_;
159 
160  // the unit vector around which the joint revolves in parent coords
161  IMP::algebra::Vector3D rot_axis_unit_vector_;
162 
163  // the joint origin of rotation in parent coords
164  IMP::algebra::Vector3D rot_axis_origin_;
165 };
166 
167 /********************** DihedralAngleRevoluteJoint ***************/
168 // @TODO handle derivatives
169 
170 //! Joint that is parameterized as a dihedral angle between two planes
171 class IMPKINEMATICSEXPORT DihedralAngleRevoluteJoint : public RevoluteJoint {
172  public:
173  /**
174  constructs a dihedral angle that revolves around the axis b-c,
175  using a,b,c,d as witnesses for the dihedral angle
176 
177  @param parent,child kinematic nodes upstream and downstream (resp.) of
178  this joint
179  @param a,b,c,d 'witnesses' whose coordinates define the dihedral
180  angle between the planes containing a-b-c and
181  b-c-d)
182 
183  @note It is assumed that neither a, b and c are downstream of child,
184  and also that d is not upstream of it
185  */
189  IMP::core::XYZ d);
190 
191  IMP::core::XYZ get_a() const { return a_; }
192  IMP::core::XYZ get_b() const { return b_; }
193  IMP::core::XYZ get_c() const { return c_; }
194  IMP::core::XYZ get_d() const { return d_; }
195 
196  protected:
197  /**
198  updates the rot_axis_unit_vector_ and rot_axis_origin_ variables
199  in parent coordinates based on the witnesses b_ and c_,
200  using b_-c_ as the axis of rotation
201  @note it is assumed b_ and c_ have update Cartesian coordinates
202  */
204  using namespace IMP::algebra;
206  get_distance(b_.get_coordinates(), c_.get_coordinates()) > 1e-12,
207  "witnesses b and c must be non identical beyond numerical error");
208  ReferenceFrame3D rf_parent = get_parent_node().get_reference_frame();
209  // nice_print_trans(rf_parent.get_transformation_to(), "Parent trans: ");
210  rot_axis_origin_ = rf_parent.get_local_coordinates(b_.get_coordinates());
211  IMP_LOG(VERBOSE, "global b_ " << b_.get_coordinates()
212  << " and local parent b_ " << rot_axis_origin_
213  << std::endl);
214  Vector3D v = rf_parent.get_local_coordinates(c_.get_coordinates()) -
215  rf_parent.get_local_coordinates(b_.get_coordinates());
216  rot_axis_unit_vector_ = v.get_unit_vector();
217  IMP_LOG(VERBOSE, "local axis of rot unnorm "
218  << v << " global axis "
219  << c_.get_coordinates() - b_.get_coordinates()
220  << std::endl);
221  };
222 
223  /**
224  this protected method uses the Cartesian witnesses to compute
225  the actual current dihedral angle of this joint (assuming
226  external coordinates of required Cartesian witnesses are up to
227  date)
228  */
229  virtual double get_current_angle_from_cartesian_witnesses() const;
230 
231  private:
232  IMP::core::XYZ a_;
233  IMP::core::XYZ b_;
234  IMP::core::XYZ c_;
235  IMP::core::XYZ d_;
236 };
237 
238 /********************** BondAngleRevoluteJoint ***************/
239 // TODO: do we want to handle derivatives?
240 
241 //! Joint that is parameterized as a bond angle between three particles
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)
Definition: Rotation3D.h:395
Simple 3D transformation class.
Abstract class for all revolute joints.
Joint that is parameterized as a bond angle between three particles.
Exception definitions and assertions.
double get_angle(const Line3D &a, const Line3D &b)
Get angle in radians between two lines around their closest points.
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)
Generate a Transformation2D object from a rotation around a point.
Vector3D get_local_coordinates(const Vector3D &v) const
Vector3D get_vector_product(const Vector3D &p1, const Vector3D &p2)
Return 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:109
virtual double get_current_angle_from_cartesian_witnesses() const =0
virtual void update_child_node_reference_frame() const
3D rotation class.
Definition: Rotation3D.h:51
Joint that is parameterized as a dihedral angle between two planes.
#define IMP_OBJECTS(Name, PluralName)
Define the types for storing lists of object pointers.
Definition: object_macros.h:44
Exception definitions and assertions.
Base class for joints between rigid bodies in a kinematic tree.
Definition: Joint.h:30
A shared base class to help in debugging and things.
VectorD< 3 > Vector3D
Definition: VectorD.h:421
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:82
double get_distance(const Line3D &s, const Vector3D &p)
Get closest distance between a line and a point.