def move_head(target_position, painter): target_position = Point(target_position) painter.draw_point(target_position) head_bottom_position = Point((0, 0, torso_height + neck_length)) head_top_position = Point((0, 0, torso_height + neck_length + head_height)) distance_between_head_bottom_and_target = head_bottom_position.distance_to(target_position) assert distance_between_head_bottom_and_target == head_height distance_between_head_top_and_target = head_top_position.distance_to(target_position) neck_lateral_radians = get_angle_with_3_sides_known(distance_between_head_top_and_target, head_height, head_height) def get_neck_transversal_radians(target_x, target_y): if target_x != 0: radiance = atan(target_y / target_x) else: # perpendicular if target_y > 0: radiance = half_pi elif target_y < 0: radiance = -half_pi else: radiance = 0 return radiance neck_transversal_radians = get_neck_transversal_radians(target_x=target_position[0], target_y=target_position[1]) return neck_transversal_radians, neck_lateral_radians
def _get_hip_lateral(self, hip_frontal_radians, knee_lateral_radians): if self.is_left: current_ankle = Point(self.robot_model.draw_left_lower_limp(left_hip_frontal_radians=hip_frontal_radians, left_knee_lateral_radians=knee_lateral_radians, draw=False)[-2].vertex) else: current_ankle = Point(self.robot_model.draw_right_lower_limp(right_hip_frontal_radians=hip_frontal_radians, right_knee_lateral_radians=knee_lateral_radians, draw=False)[-2].vertex) opposite_side_length = current_ankle.distance_to(self.target_at_ankle__with_hip_transversal_counteracted) if is_float_equal(opposite_side_length, 0): return 0 target_at_ankle_with_hip_transversal_counteracted__radius = self.hip_bottom_position.distance_to(self.target_at_ankle__with_hip_transversal_counteracted) current_ankle_radius = self.hip_bottom_position.distance_to(current_ankle) assert is_float_equal(target_at_ankle_with_hip_transversal_counteracted__radius, current_ankle_radius), '{} {}'.format(target_at_ankle_with_hip_transversal_counteracted__radius, current_ankle_radius) assert opposite_side_length < current_ankle_radius + target_at_ankle_with_hip_transversal_counteracted__radius hip_lateral_radians = get_angle_with_3_sides_known(opposite_side_length, current_ankle_radius, target_at_ankle_with_hip_transversal_counteracted__radius) if self.is_left: return hip_lateral_radians else: return -hip_lateral_radians
class LineSegment: def __init__(self, initial, end): self.initial = Point(initial) self.end = Point(end) self._mid_point = None self._length = None def get_point_at(self, fraction): x = self.initial.x + (self.end.x - self.initial.x) * fraction y = self.initial.y + (self.end.y - self.initial.y) * fraction z = self.initial.z + (self.end.z - self.initial.z) * fraction return Point((x, y, z)) def has_point(self, p): if self.initial.x <= p.x <= self.end.x\ and self.initial.y <= p.y <= self.end.y\ and self.initial.z <= p.x <= self.end.x: return True else: return False @property def mid_point(self): if self._mid_point is None: self._mid_point = self.get_point_at(0.5) return self._mid_point @property def length(self): if self._length is None: self._length = self.initial.distance_to(self.end) return self._length
class InverseKinematicsLeg(): DEBUG = False def __init__(self, is_left, hip_transversal_radians, target_position, robot_model, painter): self.robot_model = robot_model self.painter = painter self.is_left = is_left if self.DEBUG: print('is_left', is_left) if self.is_left: self.hip_top_position = Point(left_hip_top_position) self.hip_bottom_position = Point(left_hip_bottom_position) else: self.hip_top_position = Point(right_hip_top_position) self.hip_bottom_position = Point(right_hip_bottom_position) if self.DEBUG: print('hip top & bottom\n\t', self.hip_top_position, '\n\t', self.hip_bottom_position) self.hip_transversal_radians = hip_transversal_radians self.target_position = Point(target_position) self.target_at_ankle = Point(translate_3d_point(target_position, dz=foot_height)) if self.DEBUG: print('target & at ankle\n\t', self.target_position, '\n\t', self.target_at_ankle) # counteract hip transversal self.target_at_ankle__with_hip_transversal_counteracted = self._get_target_with_hip_transversal_counteracted() if self.DEBUG: print('target_at_ankle__with_hip_transversal_counteracted\n\t', self.target_at_ankle__with_hip_transversal_counteracted) def get_angles(self): if self.DEBUG: self.painter.draw_point(self.target_position, color='y.') if self.DEBUG: self.painter.draw_point(self.target_at_ankle, color='y.') knee_lateral_radians, knee_interior_radians, knee_exterior_radians = self._get_knee_lateral() if self.DEBUG: print('knee_lateral_radians', degrees(knee_lateral_radians)) hip_frontal_radians = self._get_hip_frontal() if self.DEBUG: print('hip_frontal_radians', degrees(hip_frontal_radians)) hip_lateral_radians = - self._get_hip_lateral(hip_frontal_radians, knee_lateral_radians) if self.DEBUG: print('hip_lateral_radians', degrees(hip_lateral_radians)) ankle_lateral_radians = -(abs(hip_lateral_radians) - knee_exterior_radians) if not self.is_left: ankle_lateral_radians *= -1 if self.DEBUG: print('ankle_lateral_radians', ankle_lateral_radians) ankle_frontal_radians = hip_frontal_radians if self.DEBUG: print('ankle_frontal_radians', ankle_frontal_radians) if self.DEBUG: print('fd (hip_transversal, hip_frontal, hip_lateral, knee_lateral)') if self.DEBUG: print(' ', to_degrees((self.hip_transversal_radians, hip_frontal_radians, hip_lateral_radians, knee_lateral_radians))) return hip_frontal_radians, hip_lateral_radians, knee_lateral_radians, ankle_lateral_radians, ankle_frontal_radians def _get_target_with_hip_transversal_counteracted(self): move_back_to_origin = get_translate_matrix(-self.hip_top_position.x, -self.hip_top_position.y, -self.hip_top_position.z) rotate_along_z_axis = get_rotate_matrix_along_axis('z', self.hip_transversal_radians) move_back_to_point = get_translate_matrix(self.hip_top_position.x, self.hip_top_position.y, self.hip_top_position.z) target_at_ankle__with_hip_transversal_counteracted = apply_matrix_to_vertex(self.target_at_ankle, move_back_to_point.dot(rotate_along_z_axis.dot(move_back_to_origin))) return Point(target_at_ankle__with_hip_transversal_counteracted) def _get_knee_lateral(self): d1 = self.hip_bottom_position.distance_to(self.target_at_ankle__with_hip_transversal_counteracted) if self.DEBUG: print('d1', d1, self.hip_bottom_position, self.target_at_ankle__with_hip_transversal_counteracted) assert is_float_equal(d1, leg_length) or d1 < leg_length, '{} {} {}'.format(d1, leg_length, d1-leg_length) if is_float_equal(d1, leg_length): knee_interior_radians = pi else: knee_interior_radians = get_angle_with_3_sides_known(d1, upper_leg_length, lower_leg_length) knee_exterior_radians = pi - knee_interior_radians if self.DEBUG: print('knee interior & exterior angles', degrees(knee_interior_radians), degrees(knee_exterior_radians)) if self.is_left: knee_lateral_radians = knee_exterior_radians else: knee_lateral_radians = -knee_exterior_radians return knee_lateral_radians, knee_interior_radians, knee_exterior_radians def _get_hip_frontal(self): target_at_ankle_with_hip_transversal_counteracted__y_offset_to_hip_bottom = abs(self.target_at_ankle__with_hip_transversal_counteracted.y - self.hip_bottom_position.y) target_at_ankle_with_hip_transversal_counteracted__z_offset_to_hip_bottom = abs(self.target_at_ankle__with_hip_transversal_counteracted.z - self.hip_bottom_position.z) hip_frontal_radians = atan( target_at_ankle_with_hip_transversal_counteracted__y_offset_to_hip_bottom / target_at_ankle_with_hip_transversal_counteracted__z_offset_to_hip_bottom) if self.is_left: return -hip_frontal_radians else: return hip_frontal_radians def _get_hip_lateral(self, hip_frontal_radians, knee_lateral_radians): if self.is_left: current_ankle = Point(self.robot_model.draw_left_lower_limp(left_hip_frontal_radians=hip_frontal_radians, left_knee_lateral_radians=knee_lateral_radians, draw=False)[-2].vertex) else: current_ankle = Point(self.robot_model.draw_right_lower_limp(right_hip_frontal_radians=hip_frontal_radians, right_knee_lateral_radians=knee_lateral_radians, draw=False)[-2].vertex) opposite_side_length = current_ankle.distance_to(self.target_at_ankle__with_hip_transversal_counteracted) if is_float_equal(opposite_side_length, 0): return 0 target_at_ankle_with_hip_transversal_counteracted__radius = self.hip_bottom_position.distance_to(self.target_at_ankle__with_hip_transversal_counteracted) current_ankle_radius = self.hip_bottom_position.distance_to(current_ankle) assert is_float_equal(target_at_ankle_with_hip_transversal_counteracted__radius, current_ankle_radius), '{} {}'.format(target_at_ankle_with_hip_transversal_counteracted__radius, current_ankle_radius) assert opposite_side_length < current_ankle_radius + target_at_ankle_with_hip_transversal_counteracted__radius hip_lateral_radians = get_angle_with_3_sides_known(opposite_side_length, current_ankle_radius, target_at_ankle_with_hip_transversal_counteracted__radius) if self.is_left: return hip_lateral_radians else: return -hip_lateral_radians