Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
trajectory.py
1 # Copyright (c) 2021, Matthew Booker
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License. Reserved.
14 
15 from dataclasses import dataclass
16 from typing import Any, Union
17 
18 from nav2_smac_planner.lattice_primitives.helper import angle_difference, normalize_angle
19 import numpy as np
20 from numpy.typing import NDArray
21 
22 AnyFloat = np.floating[Any]
23 TrajectoryFloat = Union[float, AnyFloat]
24 FloatNDArray = NDArray[AnyFloat]
25 
26 
27 @dataclass(frozen=True)
29  """
30  A dataclass that holds the data needed to create the path for a trajectory.
31 
32  turning_radius: The radius of the circle used to generate
33  the arc of the path
34  x_offset: The x coordinate of the circle used to generate
35  the arc of the path
36  y_offset: They y coordinate of the circle used to generate
37  the arc of the path
38  end_point: The end coordinate of the path
39  start_angle: The starting angle of the path
40  - given in radians from -pi to pi where 0 radians is along
41  the positive x axis
42  end_angle: The end angle of the path
43  - given in radians from -pi to pi where 0 radians is along
44  the positive x axis
45  left_turn: Whether the arc in the path turns to the left
46  arc_start_point: Coordinates of the starting position of the arc
47  arc_end_point: Coordinates of the ending position of the arc
48  """
49 
50  turning_radius: TrajectoryFloat
51  x_offset: float
52  y_offset: float
53  end_point: FloatNDArray
54  start_angle: float
55  end_angle: float
56  left_turn: bool
57 
58  arc_start_point: FloatNDArray
59  arc_end_point: FloatNDArray
60 
61  @property
62  def arc_length(self) -> TrajectoryFloat:
63  """Arc length of the trajectory."""
64  result: TrajectoryFloat = self.turning_radius * angle_difference(
65  self.start_angle, self.end_angle, self.left_turn
66  )
67  return result
68 
69  @property
70  def start_straight_length(self) -> AnyFloat:
71  """Length of the straight line fromnorarc_start_pointm start to arc."""
72  return np.linalg.norm(self.arc_start_point)
73 
74  @property
75  def end_straight_length(self) -> AnyFloat:
76  """Length of the straight line from arc to end."""
77  return np.linalg.norm(self.end_point - self.arc_end_point)
78 
79  @property
80  def total_length(self) -> AnyFloat:
81  """Total length of trajectory."""
82  return self.arc_lengtharc_length + self.start_straight_lengthstart_straight_length + self.end_straight_lengthend_straight_length
83 
84  @staticmethod
85  def no_arc(end_point: FloatNDArray, start_angle: float,
86  end_angle: float) -> 'TrajectoryParameters':
87  """Create the parameters for a trajectory with no arc."""
88  return TrajectoryParameters(
89  turning_radius=0.0,
90  x_offset=0.0,
91  y_offset=0.0,
92  end_point=end_point,
93  start_angle=start_angle,
94  end_angle=end_angle,
95  left_turn=True,
96  arc_start_point=end_point,
97  arc_end_point=end_point,
98  )
99 
100 
101 @dataclass(frozen=True)
102 class Path:
103  """
104  A dataclass that holds the generated poses for a given trajectory.
105 
106  xs: X coordinates of poses along trajectory
107  ys: Y coordinates of poses along trajectory
108  yaws: Yaws of poses along trajectory
109  """
110 
111  xs: FloatNDArray
112  ys: FloatNDArray
113  yaws: FloatNDArray
114 
115  def __add__(self, rhs: 'Path') -> 'Path':
116  """Add two paths together by concatenating them."""
117  if self.xs is None:
118  return rhs
119 
120  xs = np.concatenate((self.xs, rhs.xs))
121  ys = np.concatenate((self.ys, rhs.ys))
122  yaws = np.concatenate((self.yaws, rhs.yaws))
123 
124  return Path(xs, ys, yaws)
125 
126  def to_output_format(self) -> Any:
127  """Return the path data in a format suitable for outputting."""
128  output_xs = self.xs.round(5)
129  output_ys = self.ys.round(5)
130 
131  # A bit of a hack but it removes any -0.0
132  output_xs = output_xs + 0.0
133  output_ys = output_ys + 0.0
134  output_yaws = self.yaws + 0.0
135 
136  vectorized_normalize_angle = np.vectorize(normalize_angle)
137  output_yaws = vectorized_normalize_angle(output_yaws)
138 
139  stacked = np.vstack([output_xs, output_ys, output_yaws]).transpose()
140 
141  return stacked.tolist()
142 
143 
144 @dataclass(frozen=True)
146  """
147  A dataclass that holds the path and parameters for a trajectory.
148 
149  path: The Path that represents the trajectory
150  parameters: The TrajectoryParameters that represent the trajectory
151  """
152 
153  path: Path
154  parameters: TrajectoryParameters
'Path' __add__(self, 'Path' rhs)
Definition: trajectory.py:115
'TrajectoryParameters' no_arc(FloatNDArray end_point, float start_angle, float end_angle)
Definition: trajectory.py:86