Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
helper.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 import numpy as np
16 
17 
18 def normalize_angle(angle):
19  """
20  Normalize the angle to between [0, 2pi).
21 
22  Args:
23  angle: float
24  The angle to normalize in radians
25 
26  Returns
27  -------
28  The normalized angle in the range [0,2pi)
29 
30  """
31  while angle >= 2 * np.pi:
32  angle -= 2 * np.pi
33 
34  while angle < 0:
35  angle += 2 * np.pi
36 
37  return angle
38 
39 
40 def angle_difference(angle_1, angle_2, left_turn=None):
41  """
42  Calculate the difference between two angles based on a given direction.
43 
44  Args:
45  angle_1: float
46  The starting angle in radians
47  angle_2: float
48  The ending angle in radians
49  left_turn: bool
50  The direction of turn. True if left, false if right
51  and None if smallest angular difference should be
52  returned
53 
54  Returns
55  -------
56  The angular difference between the two angles according to
57  the specified turn direction
58 
59  """
60  if left_turn is None:
61  dif = abs(angle_1 - angle_2)
62 
63  return dif if dif <= np.pi else 2 * np.pi - dif
64 
65  elif left_turn:
66 
67  if angle_2 >= angle_1:
68  return abs(angle_1 - angle_2)
69  else:
70  return 2 * np.pi - abs(angle_1 - angle_2)
71 
72  else:
73  if angle_1 >= angle_2:
74  return abs(angle_1 - angle_2)
75  else:
76  return 2 * np.pi - abs(angle_1 - angle_2)
77 
78 
79 def interpolate_yaws(start_angle, end_angle, left_turn, steps):
80  """
81  Create equally spaced yaws between two angles.
82 
83  Args:
84  start_angle: float
85  The starting angle
86  end_angle: float
87  The ending angle
88  left_turn: bool
89  The direction of turn. True if left, False otherwise
90  steps: int
91  The number of yaws to generate between start and end
92  angle
93 
94  Returns
95  -------
96  An array of yaws starting at start angle and ending at end
97  angle with steps number of angles between them
98 
99  """
100  if left_turn:
101  if start_angle > end_angle:
102  end_angle += 2 * np.pi
103  else:
104  if end_angle > start_angle:
105  end_angle -= 2 * np.pi
106 
107  yaws = np.linspace(start_angle, end_angle, steps)
108  yaws = np.vectorize(normalize_angle)(yaws)
109 
110  return yaws
111 
112 
113 def get_rotation_matrix(angle):
114  """
115  Return a rotation matrix that is equivalent to a 2D rotation of angle.
116 
117  Args:
118  angle: float
119  The angle to create a rotation matrix for
120 
121  Returns
122  -------
123  A 2x2 matrix representing a 2D rotation by angle
124 
125  """
126  return np.array([[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]])