RPP¶
src.python_motion_planning.local_planner.rpp.RPP
¶
Bases: LocalPlanner
Class for RPP motion planning.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
start
|
tuple
|
start point coordinate |
required |
goal
|
tuple
|
goal point coordinate |
required |
env
|
Env
|
environment |
required |
heuristic_type
|
str
|
heuristic function type |
'euclidean'
|
**params
|
other parameters can be found in the parent class LocalPlanner |
{}
|
Examples:
Python Console Session
>>> from python_motion_planning.utils import Grid
>>> from python_motion_planning.local_planner import RPP
>>> start = (5, 5, 0)
>>> goal = (45, 25, 0)
>>> env = Grid(51, 31)
>>> planner = RPP(start, goal, env)
>>> planner.run()
Source code in src\python_motion_planning\local_planner\rpp.py
Python
class RPP(LocalPlanner):
"""
Class for RPP motion planning.
Parameters:
start (tuple): start point coordinate
goal (tuple): goal point coordinate
env (Env): environment
heuristic_type (str): heuristic function type
**params: other parameters can be found in the parent class LocalPlanner
Examples:
>>> from python_motion_planning.utils import Grid
>>> from python_motion_planning.local_planner import RPP
>>> start = (5, 5, 0)
>>> goal = (45, 25, 0)
>>> env = Grid(51, 31)
>>> planner = RPP(start, goal, env)
>>> planner.run()
"""
def __init__(self, start: tuple, goal: tuple, env: Env, heuristic_type: str = "euclidean", **params) -> None:
super().__init__(start, goal, env, heuristic_type, **params)
# RPP parameters
self.regulated_radius_min = 0.9
self.scaling_dist = 0.6
self.scaling_gain = 1.0
# global planner
g_start = (start[0], start[1])
g_goal = (goal[0], goal[1])
self.g_planner = {"planner_name": "a_star", "start": g_start, "goal": g_goal, "env": env}
self.path = self.g_path[::-1]
def __str__(self) -> str:
return "Regulated Pure Pursuit (RPP)"
def plan(self):
"""
RPP motion plan function.
Returns:
flag (bool): planning successful if true else failed
pose_list (list): history poses of robot
lookahead_pts (list): history lookahead points
"""
lookahead_pts = []
dt = self.params["TIME_STEP"]
for _ in range(self.params["MAX_ITERATION"]):
# break until goal reached
if self.reachGoal(tuple(self.robot.state.squeeze(axis=1)[0:3]), self.goal):
return True, self.robot.history_pose, lookahead_pts
# get the particular point on the path at the lookahead distance
lookahead_pt, _, _ = self.getLookaheadPoint()
# get the tracking curvature with goalahead point
lookahead_k = 2 * math.sin(
self.angle(self.robot.position, lookahead_pt) - self.robot.theta
) / self.lookahead_dist
# calculate velocity command
e_theta = self.regularizeAngle(self.robot.theta - self.goal[2])
if not self.shouldMoveToGoal(self.robot.position, self.goal):
if not self.shouldRotateToPath(abs(e_theta)):
u = np.array([[0], [0]])
else:
u = np.array([[0], [self.angularRegularization(e_theta / dt)]])
else:
e_theta = self.regularizeAngle(self.angle(self.robot.position, lookahead_pt) - self.robot.theta)
if self.shouldRotateToPath(abs(e_theta)):
u = np.array([[0], [self.angularRegularization(e_theta / dt)]])
else:
# apply constraints
curv_vel = self.applyCurvatureConstraint(self.params["MAX_V"], lookahead_k)
cost_vel = self.applyObstacleConstraint(self.params["MAX_V"])
v_d = min(curv_vel, cost_vel)
u = np.array([[self.linearRegularization(v_d)], [self.angularRegularization(v_d * lookahead_k)]])
# update lookahead points
lookahead_pts.append(lookahead_pt)
# feed into robotic kinematic
self.robot.kinematic(u, dt)
return False, None, None
def run(self):
"""
Running both plannig and animation.
"""
_, history_pose, lookahead_pts = self.plan()
if not history_pose:
raise ValueError("Path not found and planning failed!")
path = np.array(history_pose)[:, 0:2]
cost = np.sum(np.sqrt(np.sum(np.diff(path, axis=0)**2, axis=1, keepdims=True)))
self.plot.plotPath(self.path, path_color="r", path_style="--")
self.plot.animation(path, str(self), cost, history_pose=history_pose, lookahead_pts=lookahead_pts)
def applyCurvatureConstraint(self, raw_linear_vel: float, curvature: float) -> float:
"""
Applying curvature constraints to regularize the speed of robot turning.
Parameters:
raw_linear_vel (float): the raw linear velocity of robot
curvature (float): the tracking curvature
Returns:
reg_vel (float): the regulated velocity
"""
radius = abs(1.0 / curvature)
if radius < self.regulated_radius_min:
return raw_linear_vel * (radius / self.regulated_radius_min)
else:
return raw_linear_vel
def applyObstacleConstraint(self, raw_linear_vel: float) -> float:
"""
Applying obstacle constraints to regularize the speed of robot approaching obstacles.
Parameters:
raw_linear_vel (float): the raw linear velocity of robot
Returns:
reg_vel (float): the regulated velocity
"""
obstacles = np.array(list(self.obstacles))
D = cdist(obstacles, np.array([[self.robot.px, self.robot.py]]))
obs_dist = np.min(D)
if obs_dist < self.scaling_dist:
return raw_linear_vel * self.scaling_gain * obs_dist / self.scaling_dist
else:
return raw_linear_vel
applyCurvatureConstraint(raw_linear_vel, curvature)
¶
Applying curvature constraints to regularize the speed of robot turning.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_linear_vel
|
float
|
the raw linear velocity of robot |
required |
curvature
|
float
|
the tracking curvature |
required |
Returns:
Name | Type | Description |
---|---|---|
reg_vel |
float
|
the regulated velocity |
Source code in src\python_motion_planning\local_planner\rpp.py
Python
def applyCurvatureConstraint(self, raw_linear_vel: float, curvature: float) -> float:
"""
Applying curvature constraints to regularize the speed of robot turning.
Parameters:
raw_linear_vel (float): the raw linear velocity of robot
curvature (float): the tracking curvature
Returns:
reg_vel (float): the regulated velocity
"""
radius = abs(1.0 / curvature)
if radius < self.regulated_radius_min:
return raw_linear_vel * (radius / self.regulated_radius_min)
else:
return raw_linear_vel
applyObstacleConstraint(raw_linear_vel)
¶
Applying obstacle constraints to regularize the speed of robot approaching obstacles.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
raw_linear_vel
|
float
|
the raw linear velocity of robot |
required |
Returns:
Name | Type | Description |
---|---|---|
reg_vel |
float
|
the regulated velocity |
Source code in src\python_motion_planning\local_planner\rpp.py
Python
def applyObstacleConstraint(self, raw_linear_vel: float) -> float:
"""
Applying obstacle constraints to regularize the speed of robot approaching obstacles.
Parameters:
raw_linear_vel (float): the raw linear velocity of robot
Returns:
reg_vel (float): the regulated velocity
"""
obstacles = np.array(list(self.obstacles))
D = cdist(obstacles, np.array([[self.robot.px, self.robot.py]]))
obs_dist = np.min(D)
if obs_dist < self.scaling_dist:
return raw_linear_vel * self.scaling_gain * obs_dist / self.scaling_dist
else:
return raw_linear_vel
plan()
¶
RPP motion plan function.
Returns:
Name | Type | Description |
---|---|---|
flag |
bool
|
planning successful if true else failed |
pose_list |
list
|
history poses of robot |
lookahead_pts |
list
|
history lookahead points |
Source code in src\python_motion_planning\local_planner\rpp.py
Python
def plan(self):
"""
RPP motion plan function.
Returns:
flag (bool): planning successful if true else failed
pose_list (list): history poses of robot
lookahead_pts (list): history lookahead points
"""
lookahead_pts = []
dt = self.params["TIME_STEP"]
for _ in range(self.params["MAX_ITERATION"]):
# break until goal reached
if self.reachGoal(tuple(self.robot.state.squeeze(axis=1)[0:3]), self.goal):
return True, self.robot.history_pose, lookahead_pts
# get the particular point on the path at the lookahead distance
lookahead_pt, _, _ = self.getLookaheadPoint()
# get the tracking curvature with goalahead point
lookahead_k = 2 * math.sin(
self.angle(self.robot.position, lookahead_pt) - self.robot.theta
) / self.lookahead_dist
# calculate velocity command
e_theta = self.regularizeAngle(self.robot.theta - self.goal[2])
if not self.shouldMoveToGoal(self.robot.position, self.goal):
if not self.shouldRotateToPath(abs(e_theta)):
u = np.array([[0], [0]])
else:
u = np.array([[0], [self.angularRegularization(e_theta / dt)]])
else:
e_theta = self.regularizeAngle(self.angle(self.robot.position, lookahead_pt) - self.robot.theta)
if self.shouldRotateToPath(abs(e_theta)):
u = np.array([[0], [self.angularRegularization(e_theta / dt)]])
else:
# apply constraints
curv_vel = self.applyCurvatureConstraint(self.params["MAX_V"], lookahead_k)
cost_vel = self.applyObstacleConstraint(self.params["MAX_V"])
v_d = min(curv_vel, cost_vel)
u = np.array([[self.linearRegularization(v_d)], [self.angularRegularization(v_d * lookahead_k)]])
# update lookahead points
lookahead_pts.append(lookahead_pt)
# feed into robotic kinematic
self.robot.kinematic(u, dt)
return False, None, None
run()
¶
Running both plannig and animation.
Source code in src\python_motion_planning\local_planner\rpp.py
Python
def run(self):
"""
Running both plannig and animation.
"""
_, history_pose, lookahead_pts = self.plan()
if not history_pose:
raise ValueError("Path not found and planning failed!")
path = np.array(history_pose)[:, 0:2]
cost = np.sum(np.sqrt(np.sum(np.diff(path, axis=0)**2, axis=1, keepdims=True)))
self.plot.plotPath(self.path, path_color="r", path_style="--")
self.plot.animation(path, str(self), cost, history_pose=history_pose, lookahead_pts=lookahead_pts)