@@ -57,7 +57,7 @@ class BodySegment(object):
5757 viz_cylinder_radius = 0.035 # meters
5858
5959 def __init__ (self , label , description , parent_reference_frame ,
60- origin_joint , joint_description , inertial_frame ):
60+ origin_joint , joint_description , inertial_frame , passive_torque = False ):
6161 """Initializes a body segment."""
6262
6363 self .label = label
@@ -66,6 +66,7 @@ def __init__(self, label, description, parent_reference_frame,
6666 self .origin_joint = origin_joint
6767 self .joint_description = joint_description
6868 self .inertial_frame = inertial_frame
69+ self .passive_torque = passive_torque ;
6970
7071 self ._create_symbols ()
7172 self ._kinematic_differential_equations ()
@@ -112,6 +113,13 @@ def _create_symbols(self):
112113 self .mass_center_x_symbol ,
113114 self .mass_center_y_symbol ]
114115
116+ if self .passive_torque :
117+ # we need these constants to define the passive range of motion
118+ self .qmin_symbol = symbols ('qmin{}' .format (subscript ), ** sym_kwargs )
119+ self .qmax_symbol = symbols ('qmax{}' .format (subscript ), ** sym_kwargs )
120+ self .constants .append (self .qmin_symbol )
121+ self .constants .append (self .qmax_symbol )
122+
115123 # functions of time
116124 self .generalized_coordinate_symbol = \
117125 time_varying ('q{}' .format (subscript ))
@@ -183,8 +191,33 @@ def _create_rigid_body(self):
183191
184192 def _joint_torque (self ):
185193 """Creates the joint torque vector acting on the segment."""
186- self .torque = self .joint_torque_symbol * self .reference_frame .z
187- # TODO : add in passive joint stiffness and damping
194+ torque = self .joint_torque_symbol
195+
196+ # add in passive joint stiffness and damping
197+ if self .passive_torque :
198+ # hard-coded parameters, these are not critical
199+ k1 = 1.0 # linear stiffness (Nm/rad)
200+ k2 = 5000.0 # quadratic stiffness (Nm/rad^2) applied when outside the qmin to qmax range
201+ b = 1.0 # linear damping (Nms/rad)
202+
203+ # turn the three terms off individually, for testing
204+ # currently, setting k1 and k2 to zero makes it work.
205+ # k1 = 0.0;
206+ # k2 = 0.0;
207+ # b = 0.0;
208+
209+ # add a weak linear stiffness and damping
210+ torque += - k1 * self .generalized_coordinate_symbol - b * self .generalized_speed_symbol
211+
212+ # add quadratic stiffness when angle is outside the range qmin to qmax
213+ qmaxdiff = self .generalized_coordinate_symbol - self .qmax_symbol
214+ qmaxpenetration = (Abs (qmaxdiff ) + qmaxdiff ) / 2 # this is a positive value
215+ qmindiff = self .qmin_symbol - self .generalized_coordinate_symbol
216+ qminpenetration = (Abs (qmindiff ) + qmindiff ) / 2 # this is a positive value
217+ torque += - k2 * (qmaxpenetration ** 2 - qminpenetration ** 2 );
218+
219+ # apply this torque on the Z axis of the segment
220+ self .torque = torque * self .reference_frame .z
188221
189222 def _gravity (self ):
190223 """Creates the gravitational force vector acting on the segment."""
0 commit comments