1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22  """The elements describing the joint group. The two MBDyn extensions  
 23  have been made. 
 24  The first one is L{BindingsHinge} for setting an angle vector between 
 25  two nodes orientation matrix at run time. Using the interface developed 
 26  with L{SphericalHinge} and L{Prismatic}, a new L{Coincidence} joint 
 27  that clamp two node has been created. 
 28  """ 
 29  from mbdyn.general import NULL, EYE 
 30  from mbdyn.references import NONE_REF 
 31  from mbdyn.common import MANAGER 
 32   
 33  from mbdyn.elements_base import ElementWithNode 
 34   
 35  JOINT_CLASS = {} 
 36   
 38      """The top class for joints. Each joint has a type 
 39      and is attached to a node. Some of them will  
 40      also be able to manipulate a reference from the 
 41      L{mbdyn.bindings.joints} module. 
 42      """ 
 43   
 45          ElementWithNode.__init__(self, name) 
 46          self.mbdyn_type = "joint" 
 47          self.group_key = "JOINT" 
 48          self.arg_names += ["joint_type", "node"] 
 49          self.control_data_with_values = [("joints", "+1  # %s" % name)] 
  50   
 52          """Set the MBDyn instance reference under the C{mbdyn_inst} 
 53          attribute. The reference will be from a class defined in the 
 54          L{mbdyn.bindings.joints} module."""  
 55          mbdyn_joints = self.simulation.wrapt_mbdyn.elts.joints 
 56          self.mbdyn_inst = mbdyn_joints.get_from_label(self.label) 
   57   
 58   
 60      """Description of a joint associated to two nodes. 
 61      """ 
 62   
 64          CommonJoint.__init__(self, name) 
 65          self.node = None 
 66          self.node2 = None 
 67          self.mbdyn_node = None 
 68          self.mbdyn_node2 = None 
  69   
 71          """Does not make sense for a joint of 2 nodes""" 
 72          mess = "For a 'CommonJoint2Nodes', the method 'attach_to_node' " 
 73          mess += "is not relevant.\nUse 'set_node1' and 'set_node2' instead." 
 74          print mess 
  75   
 77          """Set the first node of the joint""" 
 78          self.node = node 
  79   
 81          """Set the second node of the joint""" 
 82          self.node2 = node 
  83       
 85          """Set the node labels (or index)""" 
 86          self.mbdyn_node = self.node.mbdyn_label 
 87          self.mbdyn_node2 = self.node2.mbdyn_label 
   88   
 89   
 91      """The clamp joint. 
 92      """ 
 93   
100   
102          """Set the default on the clamp. It will be 
103          a position and orientation matrix relative to the 
104          attached node""" 
105          self.set_position("node") 
106          self.set_orientation_matrix("node") 
 107   
114   
 122   
123   
124  JOINT_CLASS["Clamp"] = Clamp 
125   
126   
128      """Set a distance between two nodes. There is no constraint 
129      on the nodes orientation matrix. 
130      """ 
131   
132 -    def __init__(self, name="Distance joint"): 
 137   
139          """Set the constant distance between the two nodes""" 
140          MANAGER.add_argument(self, "distance", value, com, 
141                                                      "const, %s" % str(value)) 
  142   
143   
144  JOINT_CLASS["Distance"] = Distance 
145   
146   
148      """Imposed rotation on a hinge.  
149      """ 
150   
151 -    def __init__(self, name="drive hinge"): 
 152          CommonJoint2Nodes.__init__(self, name) 
153          MANAGER.add_argument(self, "joint_type", "drive hinge") 
154          MANAGER.add_argument(self, "hinge1", "hinge") 
155          MANAGER.add_argument(self, "hinge2", "hinge") 
156          self.class_key = "DriveHinge" 
157   
158          self.arg_names += ["hinge1", "orientation_matrix1",  
159                             "node2", 
160                             "hinge2", "orientation_matrix2", 
161                             "orientation_axis", "value"] 
162       
163          self.set_default() 
 164   
173   
177   
181       
183          """Set the relative orientation axis for the rotation""" 
184          kargs["ref"]  = NONE_REF 
185          MANAGER.add_vector(self, "orientation_axis", args, kargs) 
 186   
188          """Set the value of the rotation""" 
189          MANAGER.add_argument(self, "value", value, com, 
190                                              "const, %s" % str(value)) 
  191   
192   
193  JOINT_CLASS["DriveHinge"] = DriveHinge 
194   
195   
197      """A drive hinge joint having its angle vector set at  
198      run time. This object is still in development and may lead 
199      to unstable simulation. 
200      """ 
201   
202 -    def __init__(self, name="bindings hinge"): 
  206   
207   
208  JOINT_CLASS["BindingsHinge"] = BindingsHinge 
209   
210   
212      """Constraint the relative rotation of two nodes. 
213      The hinge keyword is used to assign the joint initial orientation. 
214      """ 
215   
217          CommonJoint2Nodes.__init__(self, name) 
218          self.class_key = "Prismatic" 
219          MANAGER.add_argument(self, "joint_type", "prismatic") 
220          MANAGER.add_argument(self, "hinge1", "hinge") 
221          MANAGER.add_argument(self, "hinge2", "hinge") 
222          self.arg_names += ["hinge1", "orientation_matrix1", 
223                             "node2",  
224                             "hinge2", "orientation_matrix2"] 
 225   
231       
235   
 239   
240   
241  JOINT_CLASS["Prismatic"] = Prismatic 
242   
243   
245      """An abstract class used as decorator 
246      for setting the common documentation on the L{RevoluteHinge} 
247      and the L{RevolutePin} classes. 
248      """ 
249   
250 -    def __init__(self, om1_name, om2_name): 
 251          self.doc = """The third axis of the revolute pin is supposed to be  
252          the axis of rotation of the joint. This method will set 
253          the C{%(om1)s} and the C{%(om2)s} 
254          to the same value, that's why a matrix is expected. Example:: 
255   
256              joint.set_rotation_axis(two=(0., 1., 0.), 
257                                      three=(1., 0., 0.)) 
258           
259          It will make the joint rotate along the M{x} axis of the joint  
260          reference frame. In that example, the C{two} keyword is needed to 
261          build the orientation matrix, it confirms that the second axis 
262          of the joint reference frame is also the second axis of the  
263          joint orientation matrix.  
264          Another example for rotating along the C{y} axis:: 
265   
266              joint.set_rotation_axis(one=(1., 0., 0.), 
267                                      three=(0., 1., 0.)) 
268   
269          You can still use that method if both orientation matrix are 
270          the same and you know them. If both orientation matrix are not 
271          the same, use C{set_%(om1)s} and C{set_%(om2)s} instead.  
272          """  % {"om1" : om1_name, "om2" : om2_name} 
 273   
275          """Set the documentation on the method""" 
276          method.__doc__ = self.doc 
277          return method 
  278   
279   
281      """A pivot hinge between two nodes. 
282      The rotation will occur around the node 1, the axis being defined 
283      by L{set_rotation_axis}. 
284   
285      If an offset is applied on a clamped node 1, the center of rotation  
286      of the joint will move but the node will stay where it is. 
287      If an offset is applied on the node 2, the node will move, modifying 
288      its initial position due to the constraint. 
289      """ 
290   
291 -    def __init__(self, name="revolute hinge"): 
 292          CommonJoint2Nodes.__init__(self, name) 
293          self.class_key = "RevoluteHinge" 
294          MANAGER.add_argument(self, "joint_type", "revolute hinge") 
295          MANAGER.add_argument(self, "hinge1", "hinge") 
296          MANAGER.add_argument(self, "hinge2", "hinge") 
297          self.arg_names += [ "offset1", "hinge1", 
298                              "orientation_matrix1", 
299                              "node2", 
300                              "offset2", "hinge2", 
301                              "orientation_matrix2"] 
302          self.set_default() 
 303   
311       
313          """Set the relative offset of the node 1""" 
314          MANAGER.add_vector(self, "offset1", args, kargs) 
 315       
319       
321          """Set the relative offset of the node 2""" 
322          MANAGER.add_vector(self, "offset2", args, kargs) 
 323       
327   
328      @_SetRevoluteDocumentation("orientation_matrix1", "orientation_matrix2") 
 332   
333   
334  JOINT_CLASS["RevoluteHinge"] = RevoluteHinge 
335   
336   
338      """A pivot between a built-in node clamped to the ground 
339      and the user one. The axis of rotation 
340      is set thanks to the L{set_rotation_axis}. 
341      """ 
342   
343 -    def __init__(self, name="revolute_pin"): 
 344          CommonJoint.__init__(self, name) 
345          MANAGER.add_argument(self, "joint_type", "revolute pin") 
346          self.class_key = "RevolutePin" 
347          self.group_key = "JOINT" 
348          self.arg_names += [ "offset", "hinge1", 
349                              "orientation_matrix","abs_pin_position", 
350                              "hinge2", "abs_pin_orientation_matrix"] 
351          MANAGER.add_argument(self, "hinge1", "hinge") 
352          MANAGER.add_argument(self, "hinge2", "hinge") 
 353   
363       
365          """Set the absolute pin position""" 
366          MANAGER.add_vector(self, "abs_pin_position", args, kargs) 
 367   
372   
374          """Set the relative offset of the second connection""" 
375          MANAGER.add_vector(self, "offset", args, kargs) 
 376   
378          """Set the relative orientation matrix of the second connection""" 
379          MANAGER.add_orientation_matrix(self, "orientation_matrix", args, kargs) 
 380      
381      @_SetRevoluteDocumentation("abs_pin_orientation_matrix", 
382                                 "orientation_matrix") 
 386      
387   
388  JOINT_CLASS["RevolutePin"] = RevolutePin 
389   
390   
392      """A spherical hinge between two nodes. 
393      """ 
394   
395 -    def __init__(self, name="spherical hinge"): 
 396          CommonJoint2Nodes.__init__(self, name) 
397          MANAGER.add_argument(self, "joint_type", "spherical hinge") 
398          MANAGER.add_argument(self, "hinge1", "hinge") 
399          MANAGER.add_argument(self, "hinge2", "hinge") 
400          self.class_key = "SphericalHinge" 
401          self.arg_names += [ "offset1", "hinge1", 
402                              "orientation_matrix1", 
403                              "node2", 
404                              "offset2", "hinge2", 
405                              "orientation_matrix2"] 
406          self.set_default() 
 407       
415       
417          """Set the relative offset of the node 1""" 
418          MANAGER.add_vector(self, "offset1", args, kargs) 
 419   
424       
426          """Set the relative offset of the node 2""" 
427          MANAGER.add_vector(self, "offset2", args, kargs) 
 428       
 432   
433   
434  JOINT_CLASS["SphericalHinge"] = SphericalHinge 
435   
436   
437   
438   
440      """A joint that makes two nodes clamped to each other. 
441      This joints does not exist in MBDyn but is based on 
442      the Python interface. 
443   
444      This joint combines of a L{SphericalHinge} 
445      and L{Prismatic}. The L{SphericalHinge} constraints the motion 
446      of the two joints but allow rotations. The L{Prismatic} however 
447      constraints the orientation matrix of the two nodes, both 
448      have to stay the same which suppress the rotation. 
449      Example making two nodes clamped:: 
450   
451          ref = ReferenceFrame() 
452          ref.set_position(10., 0., 0.) 
453           
454          node1 = StructuralNode() 
455          node2 = StructuralNode() 
456          node2.set_relative_from(ref) 
457   
458          joint = Coincidence() 
459          joint.set_relative_from(ref) 
460          joint.set_node1(node1) 
461          joint.set_node2(node2) 
462   
463      Both joints can be accessed by the attributes: 
464      C{spherical_hinge} and C{prismatic}. 
465      """ 
466   
468          if name == None: 
469              self.name = "coincidence" 
470          else: 
471              self.name = "coincidence " + name 
472          self.spherical_hinge = SphericalHinge("Spherical hinge " + self.name) 
473          self.prismatic = Prismatic("Prismatic " + self.name) 
474           
475          self._joints = [self.spherical_hinge, 
476                          self.prismatic] 
477          self.mbdyn_objects = self._joints 
478           
479          self.group_key = "JOINT" 
480          self.class_key = "Coincidence" 
481          self.set_default() 
 482   
487   
492   
494          """Set the node 1 for the two joints""" 
495          for joint in self._joints: 
496              joint.set_node1(node1) 
 497   
499          """Set the node 2 for the two joints""" 
500          for joint in self._joints: 
501              joint.set_node2(node2) 
  502   
503   
504  JOINT_CLASS["Coincidence"] = Coincidence 
505