/old/code/robot_parts.py

https://github.com/pkok/bsc-thesis
Python | 127 lines | 56 code | 12 blank | 59 comment | 3 complexity | 6897050ec9f158737660404e3f1c3bd9 MD5 | raw file
  1. #from decimal import Decimal
  2. import numpy
  3. import numpy.linalg
  4. number = float
  5. zero = number("0")
  6. one = number("1")
  7. e0 = numpy.matrix([one, zero, zero, zero]).T
  8. e1 = numpy.matrix([zero, one, zero, zero]).T
  9. e2 = numpy.matrix([zero, zero, one, zero]).T
  10. e3 = numpy.matrix([zero, zero, zero, one]).T
  11. BASE = [e0, e1, e2, e3]
  12. def point(*data):
  13. return numpy.matrix(sum(map(lambda x: x[0] * x[1],\
  14. zip(data, BASE)))).T
  15. original_orientation = numpy.matrix([zero, zero, zero])
  16. origin = point(zero)
  17. def distance(p1, p2):
  18. """Return the Euclidean distance between two joints p1 and p2.
  19. """
  20. return numpy.linalg.norm(p1 - p2)
  21. class Joint(object):
  22. """The location, orientation and constraints of a robot's joint.
  23. """
  24. def __init__(self, location, orientation=None, constraints=None):
  25. if orientation is None:
  26. orientation = original_orientation
  27. if constraints is None:
  28. constraints = Constraints(False, False)
  29. elif type(constraints) is not Constraints:
  30. constraints = Constraints(*constraints)
  31. self.location = location
  32. self.orientation = orientation
  33. self.constraints = constraints
  34. class Constraints(list):
  35. """Rotational and orientational constraints on joints.
  36. """
  37. def __init__(self, orientation=False, rotation=False):
  38. super(type(self), self).__init__((orientation, rotation))
  39. self[0], self[1] = self._check(orientation, rotation)
  40. def _check(self, orientation, rotation):
  41. new_constraints = []
  42. for constr in (orientation, rotation):
  43. # If the constraint is not iterable...
  44. if not getattr(constr, "__iter__", False):
  45. constraints_changed = True
  46. constr = [interval.empty, interval.empty, interval.empty]
  47. # ... or not all of type interval
  48. elif any(map(lambda x: type(x) is not interval, constr)):
  49. constraints_changed = True
  50. new_constr = []
  51. for interval_ in constr:
  52. if not getattr(interval_, "__iter__", False):
  53. interval_ = (0, 0)
  54. new_constr.append(interval(*interval_))
  55. constr = new_constr
  56. new_constraints.append(constr)
  57. return new_constraints
  58. @property
  59. def orientation(self):
  60. return self[0]
  61. @orientation.setter
  62. def orientation(self, value):
  63. self[0] = value
  64. @property
  65. def rotation(self):
  66. return self[1]
  67. @rotation.setter
  68. def rotation(self, value):
  69. self[1] = value
  70. class interval(object):
  71. """A more abstract notion and not iterable version of range.
  72. You can test whether an object is in the interval, and change the interval
  73. through its properties.
  74. """
  75. def __init__(self, start, end, include_start=True, include_end=True):
  76. self.start = start
  77. self.end = end
  78. self.include_start = include_start
  79. self.include_end = include_end
  80. def __contains__(self, value):
  81. return self.start <= value <= self.end
  82. @property
  83. def interval(self):
  84. return (self.start, self.end)
  85. @interval.setter
  86. def interval(self, value):
  87. self.start, self.end = value
  88. def includes(self, value):
  89. start_cmp = cmp(value, self.start)
  90. end_cmp = cmp(self.end, value)
  91. if start_cmp < 0 or end_cmp > 0:
  92. return False
  93. if not self.include_start and start_cmp == 0:
  94. return False
  95. if not self.include_end and end_cmp == 0:
  96. return False
  97. return True
  98. @property
  99. def empty(self):
  100. return interval(zero, zero)