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

631 feature execution check function for planned local trajectory #654

Closed
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
48ae661
Merge current main and [Feature]: calculate positions of lane marking…
THDThieleT Jan 16, 2025
576000a
removed debugger from lane_position node
THDThieleT Jan 16, 2025
f0441ad
reset to old value
THDThieleT Jan 16, 2025
46ce25f
WIP adding function for getting lane on the left side of the car
THDThieleT Jan 16, 2025
a674d18
added functions for lanemarkings left and right, PRE shapely
THDThieleT Jan 17, 2025
18490b3
Merge main with shapely into this branch
EyMaxl Jan 20, 2025
c1424e4
added function head for local trajectory check
THDThieleT Jan 20, 2025
1b07c0d
first try for transforming path to shapely object
THDThieleT Jan 20, 2025
c84dfe3
node that provides test path for testing the map function
THDThieleT Jan 20, 2025
c8d2cb8
fixed import error from Path message type
THDThieleT Jan 22, 2025
9d463c5
added node vor publishing test trajectory
THDThieleT Jan 22, 2025
467fca5
current WIP
THDThieleT Jan 22, 2025
3e98b13
Merge remote-tracking branch 'origin/582-feature-calculate-positions-…
Jan 23, 2025
b32a303
check trajectory function succesfully checks if lane marking is cros…
Jan 23, 2025
6fbb236
temporary adjustments for visualizing new map features
Jan 23, 2025
3a0f48c
test path is now dynamic and swiches sides
Jan 23, 2025
118e856
set lidar Z distance back to -inf for lane detection to work better
Jan 23, 2025
a5d498f
fixed Syntax error
THDThieleT Jan 24, 2025
b603b1a
added collision check for local path and parameter tuning
THDThieleT Jan 24, 2025
f91c9ac
Merge remote-tracking branch 'origin/main' into 631-feature-execution…
THDThieleT Jan 24, 2025
bcdbbb4
fixed bug where buffer area increases instead of changes
THDThieleT Jan 24, 2025
8cb86c3
[WIP] needs to be removed for PR / reset
THDThieleT Jan 24, 2025
589ee7c
Merge remote-tracking branch 'origin/main' into 631-feature-execution…
THDThieleT Jan 26, 2025
4a63321
update function description
THDThieleT Jan 26, 2025
6db0192
reformatting for linter check
THDThieleT Jan 26, 2025
b5510aa
removed wrong inserted text after merge conflict
THDThieleT Jan 26, 2025
7312f34
try for fixing linter
THDThieleT Jan 26, 2025
2cf5796
removed failure from merge conflict
THDThieleT Jan 26, 2025
7b03578
fixed error after renaming variable
THDThieleT Jan 26, 2025
4182c57
added comments and fixed return type of get_lanemarking for linter
THDThieleT Jan 27, 2025
aecbab9
added map subscriber to test local path
Jan 29, 2025
2b028c9
added path test to launch file
Jan 29, 2025
4141310
always print check status
seitzseb Jan 29, 2025
2fa2121
Merge remote-tracking branch 'origin/main' into 631-feature-execution…
seitzseb Jan 29, 2025
9c6207c
reset debug option for map.py to False
THDThieleT Jan 29, 2025
ac8038b
removed path_test from launch file
THDThieleT Feb 11, 2025
ccac3ef
Merge remote-tracking branch 'origin/Main' into 631-feature-execution…
THDThieleT Feb 11, 2025
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
2 changes: 1 addition & 1 deletion code/mapping/ext_modules/.debug_enabled
Original file line number Diff line number Diff line change
@@ -1 +1 @@
False
True
105 changes: 105 additions & 0 deletions code/mapping/ext_modules/mapping_common/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import shapely
from shapely import STRtree
import shapely.plotting
import numpy as np
import numpy.typing as npt

Expand All @@ -15,6 +16,7 @@
from shapely.geometry import Polygon, LineString

from mapping import msg
from nav_msgs.msg import Path


@dataclass
Expand Down Expand Up @@ -176,6 +178,40 @@ def get_entities_with_coverage(self, polygon, entities: List[Entity], coverage):

return collision_entities

def entities_in_area(self, radius, only_in_front=True) -> List[Entity]:
""" Returns the entities without the hero car
in a given radius around the hero car.
Flag only_in_front decides if entities
behind the car, are returend too.
Only checks if the first entity is_hero

Returns:
List[Entity]: Entities in front and/or back of hero
without the hero car in given radius
"""
entities = self.entities_without_hero()
entities_in_area = []

if only_in_front:
for entity in entities:
distance = np.sqrt(
np.power(entity.transform.translation().x(), 2)
+ np.power(entity.transform.translation().y(), 2)
)
if entity.transform.translation().x() > 0 and distance < radius:
entities_in_area.append(entity)
return entities_in_area
else:
for entity in entities:
distance = np.sqrt(
np.power(entity.transform.translation().x(), 2)
+ np.power(entity.transform.translation().y(), 2)
)
if distance < radius:
entities_in_area.append(entity)

return entities_in_area

def build_tree(
self,
f: Optional[FlagFilter] = None,
Expand Down Expand Up @@ -229,6 +265,75 @@ def to_ros_msg(self) -> msg.Map:
header = Header(stamp=self.timestamp)
return msg.Map(header=header, entities=entities)

def lane_marking_left(self) -> Entity:
for entity in self.entities:
if entity.flags._is_lanemark is True and entity.position_index == 1:
return entity
return None

def lane_marking_right(self) -> Entity:
for entity in self.entities:
if entity.flags._is_lanemark is True and entity.position_index == -1:
return entity
return None

def check_trajectory(self, local_path: Path) -> int:
"""
Checks the calculated local path on multiple conditions
return -1: local_path is None
return 0: Path has no obstacles / infringments
return 1: Path is planned through a gap,
which is too small for the car (without lanes)
return 2: Path cuts the left lane marking
return 3: Path cuts the right lane marking
"""

# check if there is a local path
if local_path.poses is None:
return -1

# transform local path to shapely object
trajectory_shapely_points = []
for pos in local_path.poses:
trajectory_shapely_points.append(
shapely.Point(pos.pose.position.x, pos.pose.position.y)
)
local_trajectory = shapely.LineString(trajectory_shapely_points)
# widen the Linestring to an area representing the cars width
local_trajectory_buffer = local_trajectory.buffer(1, 3)

# Check path collision with other entities
obstacles = self.entities_in_area(10)
for entity in obstacles:
if (
shapely.intersection(entity.to_shapely().poly, local_trajectory_buffer)
and entity.flags._is_lanemark is False
):
return 1

# decrease buffer size for lane checkking
local_trajectory_buffer = local_trajectory.buffer(0.5, 3)
# Check left lane
left_lane = self.lane_marking_left()
if left_lane is not None:
if shapely.intersection(
left_lane.to_shapely().poly, local_trajectory_buffer
):
# given path crosses lane marking on the left
return 2

# Check right lane
right_lane = self.lane_marking_right()
if right_lane is not None:
if shapely.intersection(
right_lane.to_shapely().poly, local_trajectory_buffer
):
# given path crosses lane marking on the right
return 3

# given path is okay and is not colliding
return 0


@dataclass(init=False)
class MapTree:
Expand Down
6 changes: 6 additions & 0 deletions code/mapping/src/mapping_data_integration.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in this file seem unnecessary. (lidar_data is already set to None as part of the class definition)

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def __init__(self, name, **kwargs):
callback=self.lanemarkings_callback,
qos_profile=1,
)
self.lidar_data = None
self.new_subscription(
topic=self.get_param("~hero_speed_topic", "/carla/hero/Speed"),
msg_type=CarlaSpeedometer,
Expand Down Expand Up @@ -106,6 +107,9 @@ def __init__(self, name, **kwargs):
self.rate = self.get_param("~map_publish_rate", 20)
self.new_timer(1.0 / self.rate, self.publish_new_map)

def callback(self, data: Path):
self.local_trajectory = data

def hero_speed_callback(self, data: CarlaSpeedometer):
self.hero_speed = data

Expand Down Expand Up @@ -146,6 +150,7 @@ def radar_marker_callback(self, data: MarkerArray):
def lidar_callback(self, data: PointCloud2):
self.lidar_data = data

<<<<<<<<< Temporary merge branch 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Resolve merge conflict.

Conflicting marker (<<<<<<<<< Temporary merge branch 1) at line 154 breaks Python syntax. Remove or resolve it.

-154 <<<<<<<<< Temporary merge branch 1
+# (Resolve or remove the conflict marker)

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.8.2)

154-154: SyntaxError: Expected a statement


154-154: SyntaxError: Expected a statement


154-154: SyntaxError: Expected a statement


154-154: SyntaxError: Expected a statement


154-154: SyntaxError: Expected a statement


154-154: SyntaxError: Simple statements must be separated by newlines or semicolons


154-154: SyntaxError: Simple statements must be separated by newlines or semicolons


154-154: SyntaxError: Simple statements must be separated by newlines or semicolons

def entities_from_lidar_marker(self) -> List[Entity]:
data = self.lidar_marker_data
if data is None or not hasattr(data, "markers") or data.markers is None:
Expand Down Expand Up @@ -336,6 +341,7 @@ def publish_new_map(self, timer_event=None):
stamp = rospy.get_rostime()
map = Map(timestamp=stamp, entities=entities)
msg = map.to_ros_msg()

self.map_publisher.publish(msg)


Expand Down
62 changes: 62 additions & 0 deletions code/mapping/src/path_test.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is not a "main" node of the car, I would recommend putting this in a test subfolder inside the src directory

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python
import ros_compatibility as roscomp
import rospy
from geometry_msgs.msg import PoseStamped
from ros_compatibility.node import CompatibleNode
from nav_msgs.msg import Path
import random


class TestPath(CompatibleNode):

def __init__(self):
"""
This node handles the translation from the static main frame to the
moving hero frame. The hero frame always moves and rotates as the
ego vehicle does. The hero frame is used by sensors like the lidar.
Rviz also uses the hero frame. The main frame is used for planning.
"""
super(TestPath, self).__init__("TestPath")
self.loginfo("TestPath node started")
self.local_trajectory = Path()

self.publisher = self.new_publisher(
msg_type=Path,
topic="test_trajectory",
qos_profile=1,
)

self.rate = 0.5
self.new_timer(0.5, self.generate_trajectory)

def generate_trajectory(self, timer_event=None) -> Path:
path_msg = Path()
path_msg.header = rospy.Header()
path_msg.header.stamp = rospy.Time.now()
path_msg.header.frame_id = "hero"
path_msg.poses = []
curve = 0
factor = 1
if random.uniform(-1, 1) < 0:
factor = -1

for i in range(0, 10):
pos = PoseStamped()
pos.header.stamp = rospy.Time.now()
pos.header.frame_id = "hero"
curve = curve + 0.01 * i * random.uniform(0, 1)
pos.pose.position.x = i
pos.pose.position.y = curve * factor
pos.pose.position.z = 0
pos.pose.orientation.w = 1
path_msg.poses.append(pos)

self.local_trajectory = path_msg
self.publisher.publish(path_msg)


if __name__ == "__main__":
name = "path_test_node"
roscomp.init(name)
node = TestPath()
node.spin()
Loading