Autonomous Racing  1
f1tenth Project Group of Technical University Dortmund, Germany
track.py
Go to the documentation of this file.
1 # coding: utf-8
2 
3 import random
4 import numpy as np
5 import math
6 import rospy
7 import sys
8 
9 from tf.transformations import euler_from_quaternion
10 from track_geometry import PATH
11 
12 from collections import namedtuple
13 Point = namedtuple("Point", ["x", "y"])
14 
15 
16 class TrackPosition():
17  def __init__(self, segment, x, y, point, track):
18  self.point = point
19  self.segment = segment
22  self.segment_progress = y / track.segment_length[segment]
23  self.total_distance = track.cumulative_distance[segment] + y
24  self.total_progress = self.total_distance / track.length
25  self.angle = math.atan2(
26  track.forward[segment, 1], track.forward[segment, 0])
27 
28  def __str__(self):
29  return "{0:.2f} m ({1:.0f}%), segment {2:d}, to center: {3:.2f} m, track: {4:.0f}°".format(
30  self.total_distance,
31  self.total_progress * 100,
32  self.segment,
33  self.distance_to_center,
34  self.angle * 180 / math.pi
35  )
36 
37  def get_relative_angle(self, orientation):
38  quaternion = [
39  orientation.w,
40  orientation.x,
41  orientation.y,
42  orientation.z]
43  euler = euler_from_quaternion(quaternion)
44  return (euler[0] + self.angle) % (2 * math.pi) - math.pi
45 
46  def faces_forward(self, orientation):
47  return abs(self.get_relative_angle(orientation)) < math.pi / 2
48 
49 
50 class Track():
51  def __init__(self, points):
52  self.points = points[:-1, :]
53  self.size = points.shape[0] - 1
54  relative = points[1:, :] - points[:-1, :]
55  self.segment_length = np.linalg.norm(relative, axis=1)
56  self.length = np.sum(self.segment_length)
57  self.forward = relative / self.segment_length[:, np.newaxis]
58  self.right = np.array(
59  [self.forward[:, 1], -self.forward[:, 0]]).transpose()
60  self.cumulative_distance = np.zeros(points.shape[0])
61  self.cumulative_distance[1:] = np.cumsum(self.segment_length)
62 
63  def localize(self, point):
64  ''' Returns a TrackPosition object based on a position in world space. '''
65  local = np.array([point.x, point.y]) - self.points
66  x = local[:, 0] * self.right[:, 0] + local[:, 1] * self.right[:, 1]
67  y = local[:, 0] * self.forward[:, 0] + local[:, 1] * self.forward[:, 1]
68  distances = np.abs(x)
69  distances[(y < 0) | (y > self.segment_length)] = float("Inf")
70  segment = np.argmin(distances)
71  return TrackPosition(segment, x[segment], y[segment], point, self)
72 
73  def get_position(self, total_distance, distance_to_center=0):
74  ''' Returns a TrackPosition object based on the on-track distance from the start
75  line and the distance to the center of the track. '''
76  segment = 0
77  while self.cumulative_distance[segment + 1] < total_distance:
78  segment += 1
79  segment_distance = total_distance - self.cumulative_distance[segment]
80  x = self.points[segment, 0] + self.forward[segment, 0] * \
81  segment_distance + self.right[segment, 0] * distance_to_center
82  y = self.points[segment, 1] + self.forward[segment, 1] * \
83  segment_distance + self.right[segment, 1] * distance_to_center
84  return TrackPosition(segment, distance_to_center, # nopep8
85  segment_distance, Point(x, y), self) # nopep8
86 
87 
88 world_name = rospy.get_param("world_name")
89 
90 if world_name not in [
91  "racetrack_decorated",
92  "racetrack_decorated_2",
93  "racetrack_decorated_2_big"]:
94  print "ERROR: Racetrack not supported by track.py"
95  sys.exit(1)
96 
97 if world_name == "racetrack_decorated_2_big":
98  PATH *= 2.5
99 
100 track = Track(PATH)
def __init__(self, segment, x, y, point, track)
Definition: track.py:17
def get_relative_angle(self, orientation)
Definition: track.py:37
def localize(self, point)
Definition: track.py:63
def faces_forward(self, orientation)
Definition: track.py:46
def __init__(self, points)
Definition: track.py:51
def get_position(self, total_distance, distance_to_center=0)
Definition: track.py:73