コード例 #1
0
 def is_collinear(self, other):
     """returns True if self and other are collinear (lie on the same line)"""
     if not self.rotation.isParallel(other.rotation):
         return False
     
     tmp = self.log(self.inverse().transform(other))
     return epsilon_equals(tmp.dy, 0.0) and epsilon_equals(tmp.dtheta, 0.0)
コード例 #2
0
    def get_curvature(self, t):
        """Returns the curvature of the spline at t"""

        num = (self.dx(t) * self.ddy(t) - self.ddx(t) * self.dy(t))
        # Checks if dx(t) and dy(t) are zero to avoid ZeroDivisionError
        if epsilon_equals(self.dx(t), 0) and epsilon_equals(self.dy(t), 0):
            return math.inf * (-1.0 if num < 0 else 1.0)

        return num / (
            (self.dx(t) * self.dx(t) + self.dy(t) * self.dy(t)) *
            math.sqrt(self.dx(t) * self.dx(t) + self.dy(t) * self.dy(t)))
コード例 #3
0
    def get_dCurvature(self, t):
        """Returns dCurvature of the spline at t"""

        # Checks if dx(t) and dy(t) are zero to avoid ZeroDivisionError
        if epsilon_equals(self.dx(t), 0) and epsilon_equals(self.dy(t), 0):
            return 0

        dx2dy2 = self.dx(t) * self.dx(t) + self.dy(t) * self.dy(t)
        num = (self.dx(t) * self.dddy(t) -
               self.dddx(t) * self.dy(t)) * dx2dy2 - 3 * (
                   self.dx(t) * self.ddy(t) - self.ddx(t) * self.dy(t)) * (
                       self.dx(t) * self.ddx(t) + self.dy(t) * self.ddy(t))
        return num / (dx2dy2 * dx2dy2 * math.sqrt(dx2dy2))
コード例 #4
0
def fit_parabola(p1, p2, p3):
    """Returns the x-coordinate of the vertex of the parabola"""
    a = p3.x * (p2.y - p1.y) + p2.x * (p1.y - p3.y) + p1.x * (p3.y - p2.y)
    b = p3.x * p3.x * (p1.y - p2.y) + p2.x * p2.x * (
        p3.y - p1.y) + p1.x * p1.x * (p2.y - p3.y)
    if epsilon_equals(a, 0):
        # Raises a divide by zero error because they're colinear
        return 0.0
    return -b / (2 * a)
コード例 #5
0
    def get_pose(self, t):
        """Returns pose of the spline at t"""

        # Avoid ZeroDivisionError
        dCurvature_ds = 0 if epsilon_equals(
            self.get_velocity(t),
            0) else self.get_dCurvature(t) / self.get_velocity(t)

        return Pose(self.get_point(t), self.get_heading(t),
                    self.get_curvature(t), dCurvature_ds)
コード例 #6
0
    def test_util(self):
        """Tests util methods"""

        # Test limit2
        self.assertAlmostEqual(1.0, limit2(1.0, -2.0, 4.0))
        self.assertAlmostEqual(-0.0, limit2(1.0, -2.0, -0.0))
        self.assertAlmostEqual(-2.0, limit2(-5.0, -2.0, -0.0))

        # Test limit
        self.assertAlmostEqual(1.0, limit(1.0, 4.0))
        self.assertAlmostEqual(4.0, limit(6.0, 4.0))
        self.assertAlmostEqual(-3.0, limit(-5.0, 3.0))

        # Test interpolate
        self.assertAlmostEqual(1.0, interpolate(.0, 4.0, .25))
        self.assertAlmostEqual(1.0, interpolate(-1, 4.0, .4))
        self.assertAlmostEqual(1.0, interpolate(4.0, 0.0, .75))

        # Test epsilon_equals
        self.assertTrue(epsilon_equals(1, 1.5, .5))
        self.assertTrue(epsilon_equals(2, 1.5, .5))
        self.assertFalse(epsilon_equals(1, 1.5))
コード例 #7
0
 def sample(self, t):
     """Returns interpolated trajectory point based on t"""
     if t >= self.end_t:
         return self.trajectory.points[self.trajectory.trajectory_length() -
                                       1]
     if t <= self.start_t:
         return self.trajectory.points[0]
     for i in range(1, self.trajectory.trajectory_length()):
         s = self.trajectory.points[i]
         if s.t >= t:
             prev_s = self.trajectory.points[i - 1]
             if epsilon_equals(s.t, prev_s.t):
                 return s
             return prev_s.interpolate(s, (t - prev_s.t) / (s.t - prev_s.t))
コード例 #8
0
    def update(self, value):
        """Returns True if value changes and is equivalent for a set amount of time"""

        # Not the same, so reset timer, update prev_value, and return False
        if (not epsilon_equals(value, self.prev_value)):
            self.start_time = time.perf_counter()
            self.prev_value = value
            self.first = True
            return False

        dt = time.perf_counter() - self.start_time
        return_value = False

        if (dt >= self.timeout) and (self.first):
            self.first = False
            return_value = True

        self.prev_value = value
        return return_value
コード例 #9
0
def get_max_drivetrain_velocity(trajectory_point, max_velocity):
    """Returns the max absolute velocity for a tank drive"""

    # Going straight
    if epsilon_equals(trajectory_point.pose.curvature, 0.0):
        return max_velocity

    # Turning in place
    if math.isinf(trajectory_point.pose.curvature):
        return 0.0

    # right speed if left at max velocity
    right_left_max = max_velocity * (trajectory_point.pose.curvature + 1) / (
        1.0 - trajectory_point.pose.curvature)
    if abs(right_left_max) <= max_velocity:
        return (max_velocity + right_left_max) / 2.0

    # left speed if right at max velocity
    left_right_max = max_velocity * (1 - trajectory_point.pose.curvature) / (
        1.0 + trajectory_point.pose.curvature)
    return (max_velocity + left_right_max) / 2.0
コード例 #10
0
    def update_constraints(self, dt):
        """Periodically called to update trajectory Constraints"""

        # Temporarily Save Values
        max_velocity = self.screen.ids.max_vel.ids.slider.value
        max_acceleration = self.screen.ids.max_accel.ids.slider.value
        max_centr_acceleration = self.screen.ids.max_centr_accel.ids.slider.value
        start_velocity = self.screen.ids.start_vel.ids.slider.value
        end_velocity = self.screen.ids.end_vel.ids.slider.value

        # Check and Update if Necessary
        updated = False
        if self.max_vel.update(max_velocity):
            self.current_trajectory.update_constraint(max_velocity, 0)
            updated = True
        if self.max_accel.update(max_acceleration):
            self.current_trajectory.update_constraint(max_acceleration, 1)
            updated = True
        if self.max_centr_accel.update(max_centr_acceleration):
            self.current_trajectory.update_constraint(max_centr_acceleration, 2)
            updated = True
        if self.start_vel.update(start_velocity):
            self.current_trajectory.update_constraint(start_velocity, 3)
            updated = True
        if self.end_vel.update(end_velocity):
            self.current_trajectory.update_constraint(end_velocity, 4)
            updated = True

        if updated:
            self.update_stats()
            self.reset_animation()

        if self.animation_active:
            self.update_animation(dt)
            self.update_stats()
        elif not (self.animation_active or epsilon_equals(self.prev_time, self.screen.ids.time.value)):
            self.calculate_model(self.screen.ids.time.value)
            self.update_stats()
        
        self.prev_time = self.screen.ids.time.value
コード例 #11
0
    def interpolate(self, other, x):
        """Returns interpolatation between self and other"""
        new_t = interpolate(self.t, other.t, x)
        delta_t = new_t - self.t

        # Going for 2nd pass through timed states
        if delta_t < 0.0:
            return other.interpolate(self, 1.0 - x)

        # Constant acceleration formulas
        reversing = self.velocity < 0.0 or (epsilon_equals(0.0, self.velocity)
                                            and self.acceleration < 0.0)
        new_v = self.velocity + self.acceleration * delta_t
        new_s = (-1.0 if reversing else
                 1.0) * (self.velocity * delta_t +
                         .5 * self.acceleration * delta_t * delta_t)

        return TrajectoryPoint(
            self.pose.interpolate(other.pose,
                                  new_s / self.pose.distance(other.pose)),
            new_t, new_v, self.acceleration, self.index_floor,
            other.index_ceil, self.distance + new_s)
コード例 #12
0
    def calculate_model(self, t):
        """Calculates parameters for the model and updates drawing"""
        
        # Updates Time and gets next trajectory point
        self.current_time  = t
        self.screen.ids.time.value = t
        point = self.iterator.advance(t)
        
        # Update Velocity
        self.origin = [self.translate_x(point.pose.translation.x), self.translate_y(point.pose.translation.y)]
        
        self.angle = point.pose.rotation.get_degrees()
        self.vel_length = 5.4 * abs(point.velocity) / self.current_trajectory.max_velocity
        

        # Update Acceleration
        centr = point.velocity ** 2 * point.pose.curvature / self.current_trajectory.max_centr_acceleration
        linear = point.acceleration / self.current_trajectory.max_abs_acceleration

        # If zero width, it leaves previous shape, so have small width
        self.accel_length = 5.4 * math.hypot(centr, linear)
        if epsilon_equals(self.accel_length, 0):
            self.accel_length = .01
        self.accel_angle = math.degrees(math.atan2(centr, linear))
コード例 #13
0
 def isParallel(self, other):
     """Returns True if two rotations are parallel (cross product of 0)"""
     return epsilon_equals(self.to_translation().cross(other.to_translation()), 0)
コード例 #14
0
def get_max_centripetal_velocity(trajectory_point, max_centr_accel):
    """Returns max centripetal velocity"""
    if epsilon_equals(trajectory_point.pose.curvature, 0.0):
        return 1e4
    return math.sqrt(abs(max_centr_accel / trajectory_point.pose.curvature))