Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

165 feature local trajectory planning with frenet trajectory planner #177

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions build/docker/agent/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,7 @@ RUN source ~/.bashrc && pip install -r /workspace/requirements.txt
COPY --chown=$USERNAME:$USERNAME ./code /workspace/code/

# Install Frenet Optimal Trajectory Planner
RUN sudo mkdir /erdos
RUN sudo mkdir /erdos/dependencies
RUN sudo mkdir /erdos/dependencies/frenet_optimal_trajectory_planner
RUN sudo mkdir -p /erdos/dependencies/frenet_optimal_trajectory_planner
# Needed to resolve dependencies correctly inside freent_optimal_trajectory_planner
ENV PYLOT_HOME=/erdos

Expand Down
18 changes: 9 additions & 9 deletions code/planning/src/global_planner/global_planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def __init__(self):

self.path_pub = self.new_publisher(
msg_type=Path,
topic='/paf/' + self.role_name + '/trajectory',
topic='/paf/' + self.role_name + '/trajectory_global',
qos_profile=1)

self.speed_limit_pub = self.new_publisher(
Expand Down Expand Up @@ -257,16 +257,16 @@ def run(self):
:return:
"""

def loop(timer_event=None):
if len(self.path_backup.poses) < 1:
return
# def loop(timer_event=None):
# if len(self.path_backup.poses) < 1:
# return

# Continuously update paths time to update car position in rviz
# TODO: remove next lines when local planner exists
self.path_backup.header.stamp = rospy.Time.now()
self.path_pub.publish(self.path_backup)
# # # Continuously update paths time to update car position in rviz
# # # TODO: remove next lines when local planner exists
# self.path_backup.header.stamp = rospy.Time.now()
# self.path_pub.publish(self.path_backup)

self.new_timer(self.control_loop_rate, loop)
# self.new_timer(self.control_loop_rate, loop)
self.spin()


Expand Down
14 changes: 12 additions & 2 deletions code/planning/src/local_planner/ACC.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(self):
# Get trajectory to determine current speed limit
self.trajectory_sub: Subscriber = self.new_subscription(
Path,
f"/paf/{self.role_name}/trajectory",
f"/paf/{self.role_name}/trajectory_global",
self.__set_trajectory,
qos_profile=1)

Expand All @@ -66,6 +66,14 @@ def __init__(self):
Float32,
f"/paf/{self.role_name}/acc_velocity",
qos_profile=1)
self.wp_publisher: Publisher = self.new_publisher(
Float32,
f"/paf/{self.role_name}/current_wp",
qos_profile=1)
self.speed_limit_publisher: Publisher = self.new_publisher(
Float32,
f"/paf/{self.role_name}/speed_limit",
qos_profile=1)

# List of all speed limits, sorted by waypoint index
self.__speed_limits_OD: [float] = []
Expand All @@ -88,7 +96,7 @@ def _set_distance(self, data: Float32):
"""Get min distance to object in front from perception

Args:
data (MinDistance): Minimum Distance from LIDAR
data (Float32): Minimum Distance from LIDAR
"""
self.obstacle_distance = data.data

Expand Down Expand Up @@ -148,8 +156,10 @@ def __current_position_callback(self, data: PoseStamped):
if d_new < d_old:
# update current waypoint and corresponding speed limit
self.__current_wp_index += 1
self.wp_publisher.publish(self.__current_wp_index)
self.speed_limit = \
self.__speed_limits_OD[self.__current_wp_index]
self.speed_limit_publisher.publish(self.speed_limit)

def run(self):
"""
Expand Down
218 changes: 130 additions & 88 deletions code/planning/src/local_planner/motion_planning.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# import rospy
# import tf.transformations
import ros_compatibility as roscomp
import rospy
Expand All @@ -10,8 +9,7 @@
from std_msgs.msg import String, Float32, Bool
from nav_msgs.msg import Path
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion


from carla_msgs.msg import CarlaSpeedometer
import numpy as np

from frenet_optimal_trajectory_planner.FrenetOptimalTrajectory.fot_wrapper \
Expand All @@ -20,15 +18,10 @@
import planning # noqa: F401
from behavior_agent.behaviours import behavior_speed as bs

# from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion
# from carla_msgs.msg import CarlaRoute # , CarlaWorldInfo
# from nav_msgs.msg import Path
# from std_msgs.msg import String
# from std_msgs.msg import Float32MultiArray

from utils import convert_to_ms, approx_obstacle_pos, \
hyperparameters

def convert_to_ms(speed):
return speed / 3.6
# from scipy.spatial._kdtree import KDTree


class MotionPlanning(CompatibleNode):
Expand All @@ -49,17 +42,43 @@ def __init__(self):
self.__acc_speed = 0.0
self.__stopline = None # (Distance, isStopline)
self.__change_point = None # (Distance, isLaneChange, roadOption)
self.published = False
self.current_pos = None
self.current_heading = None
self.trajectory = None
self.overtaking = False
self.overtake_start = rospy.get_rostime()
self.current_wp = None
self.enhanced_path = None
self.current_speed = None
self.speed_limit = None

self.counter = 0
self.speed_list = []
self.__first_trajectory = None
self.__corners = None
self.__in_corner = False

# Subscriber
self.speed_limit_sub = self.new_subscription(
Float32,
f"/paf/{self.role_name}/speed_limit",
self.__set_speed_limit,
qos_profile=1)
self.velocity_sub: Subscriber = self.new_subscription(
CarlaSpeedometer,
f"/carla/{self.role_name}/Speed",
self.__get_current_velocity,
qos_profile=1)
self.head_sub = self.new_subscription(
Float32,
f"/paf/{self.role_name}/current_heading",
self.__set_heading,
qos_profile=1)

self.trajectory_sub = self.new_subscription(
Path,
f"/paf/{self.role_name}/trajectory",
self.__save_trajectory,
f"/paf/{self.role_name}/trajectory_global",
self.__set_trajectory,
qos_profile=1)
self.current_pos_sub = self.new_subscription(
PoseStamped,
Expand Down Expand Up @@ -95,24 +114,60 @@ def __init__(self):
qos_profile=1)

# Publisher
# self.traj_pub: Publisher = self.new_publisher(
# Path,
# f"/paf/{self.role_name}/trajectory",
# qos_profile=1)
self.traj_pub: Publisher = self.new_publisher(
msg_type=Path,
topic=f"/paf/{self.role_name}/trajectory",
qos_profile=1)
self.velocity_pub: Publisher = self.new_publisher(
Float32,
f"/paf/{self.role_name}/target_velocity",
qos_profile=1)

self.wp_subs = self.new_subscription(
Float32,
f"/paf/{self.role_name}/current_wp",
self.__set_wp,
qos_profile=1)
# Publisher for emergency stop
self.emergency_pub = self.new_publisher(
Bool,
f"/paf/{self.role_name}/emergency",
qos_profile=1)

self.logdebug("MotionPlanning started")
self.published = False
self.current_pos = None
self.counter = 0

def __set_speed_limit(self, data: Float32):
"""Set current speed limit
Args:
data (Float32): Current speed limit
"""
self.speed_limit = data.data

def __get_current_velocity(self, data: CarlaSpeedometer):
"""Get current velocity from CarlaSpeedometer
Args:
data (CarlaSpeedometer): Current velocity
"""
self.current_speed = float(data.speed)

def __set_wp(self, data: Float32):
"""Recieve current waypoint index from ACC
Args:
data (Float32): Waypoint index
"""
self.current_wp = data.data

def __set_heading(self, data: Float32):
"""Set current Heading
Args:
data (Float32): Current Heading vom Subscriber
"""
self.current_heading = data.data

def __save_trajectory(self, data):
if self.__first_trajectory is None:
Expand All @@ -122,84 +177,70 @@ def __save_trajectory(self, data):

def __set_current_pos(self, data: PoseStamped):
"""set current position
Args:
data (PoseStamped): current position
"""
self.current_pos = np.array([data.pose.position.x,
data.pose.position.y])
data.pose.position.y,
data.pose.position.z])

def change_trajectory(self, distance: float):
self.overtake_start = rospy.get_rostime()
limit_waypoints = 30
np_array = np.array(self.trajectory.poses)
obstacle_position = approx_obstacle_pos(distance,
self.current_heading,
self.current_pos,
self.current_speed)
# trajectory_np = self.convert_pose_to_array(np_array)
# wp = KDTree(trajectory_np[:, :2]).query(obstacle_position[0][:2])[1]
selection = np_array[int(self.current_wp):int(self.current_wp) +
int(distance + limit_waypoints)]
waypoints = self.convert_pose_to_array(selection)

initial_conditions = {
'ps': 0,
'target_speed': self.current_speed,
'pos': np.array([self.current_pos[0], self.current_pos[1]]),
'vel': np.array([obstacle_position[2][0],
obstacle_position[2][1]]),
'wp': waypoints,
'obs': np.array([[obstacle_position[0][0],
obstacle_position[0][1],
obstacle_position[1][0],
obstacle_position[1][1]]])
}
result_x, result_y, speeds, ix, iy, iyaw, d, s, speeds_x, \
speeds_y, misc, costs, success = run_fot(initial_conditions,
hyperparameters)
if success:
result = []
for i in range(len(result_x)):
position = Point(result_x[i], result_y[i], 0)
quaternion = tf.transformations.quaternion_from_euler(0,
0,
iyaw[i])
orientation = Quaternion(x=quaternion[0], y=quaternion[1],
z=quaternion[2], w=quaternion[3])
pose = Pose(position, orientation)
pos = PoseStamped()
pos.header.frame_id = "global"
pos.pose = pose
result.append(pos)
path = Path()
path.header.stamp = rospy.Time.now()
path.header.frame_id = "global"
path.poses = list(np_array[:int(self.current_wp)]) + \
result + list(np_array[int(self.current_wp + 25 + 30):])
self.trajectory = path

def __set_trajectory(self, data: Path):
"""get current trajectory global planning
Args:
data (Path): Trajectory waypoints
"""
if len(data.poses) and not self.published > 0:
self.published = True
np_array = np.array(data.poses)
selection = np_array[5:17]
waypoints = self.convert_pose_to_array(selection)
self.logerr(waypoints)
obs = np.array(
[[waypoints[5][0]-0.5, waypoints[5][1], waypoints[5][0]+0.5,
waypoints[5][1]-2]])
initial_conditions = {
'ps': 0,
'target_speed': self.__acc_speed,
'pos': np.array([983.5807552562393, 5370.014637890163]),
'vel': np.array([5, 1]),
'wp': waypoints,
'obs': obs
}
hyperparameters = {
"max_speed": 25.0,
"max_accel": 15.0,
"max_curvature": 15.0,
"max_road_width_l": 3.0,
"max_road_width_r": 0.5,
"d_road_w": 0.5,
"dt": 0.2,
"maxt": 20.0,
"mint": 6.0,
"d_t_s": 0.5,
"n_s_sample": 2.0,
"obstacle_clearance": 0.1,
"kd": 1.0,
"kv": 0.1,
"ka": 0.1,
"kj": 0.1,
"kt": 0.1,
"ko": 0.1,
"klat": 1.0,
"klon": 1.0,
"num_threads": 0, # set 0 to avoid using threaded algorithm
}
result_x, result_y, speeds, ix, iy, iyaw, d, s, speeds_x, \
speeds_y, misc, costs, success = run_fot(initial_conditions,
hyperparameters)
if success:
print("Success!")
print("result_x: ", result_x)
print("result_y: ", result_y)
result = []
for i in range(len(result_x)):
position = Point(result_x[i], result_y[i], 703)
quat = tf.transformations.quaternion_from_euler(0, 0,
iyaw[i])
orientation = Quaternion(x=quat[0], y=quat[1],
z=quat[2], w=quat[3])
pose = Pose(position, orientation)
pos = PoseStamped()
pos.header.stamp = rospy.Time.now()
pos.header.frame_id = "global"
pos.pose = pose
result.append(PoseStamped)
path = Path()
path.header.stamp = rospy.Time.now()
path.path_backup.header.frame_id = "global"
path.poses = list(np_array[:5]) + result + list(np_array[17:])
self.traj_pub.publish(path)
self.trajectory = data

def __calc_corner_points(self):
coords = self.convert_pose_to_array(np.array(self.__first_trajectory))
Expand Down Expand Up @@ -444,6 +485,8 @@ def loop(timer_event=None):
self.__corners is not None):
self.update_target_speed(self.__acc_speed,
self.__curr_behavior)
self.trajectory.header.stamp = rospy.Time.now()
self.traj_pub.publish(self.trajectory)

self.new_timer(self.control_loop_rate, loop)
self.spin()
Expand All @@ -455,7 +498,6 @@ def loop(timer_event=None):
:param args:
"""
roscomp.init('MotionPlanning')

try:
node = MotionPlanning()
node.run()
Expand Down
Loading
Loading