-
Notifications
You must be signed in to change notification settings - Fork 0
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
688 feature add lane free check to lanechange behavior #731
base: main
Are you sure you want to change the base?
688 feature add lane free check to lanechange behavior #731
Conversation
… of https://github.com/una-auxme/paf into 688-feature-add-lane-free-check-to-lanechange-behavior
…-to-lanechange-behavior
…-to-lanechange-behavior
…ot trigger because target_velocity was not published
…free-check-to-lanechange-behavior
…dd-lane-free-check-to-lanechange-behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (6)
code/planning/src/behavior_agent/behavior_tree.py (1)
127-127
: Behavior tree structure improvedReplacing
metarules
withrules
in the rootParallel
node simplifies the execution flow by directly using the rules defined earlier in the function rather than wrapping them in a meta sequence.Note that while this change is positive, it's important to verify that this doesn't impact any functionality that might have been dependent on the meta sequence structure.
code/control/src/velocity_controller.py (1)
114-116
: Moved logging message outside the condition blockThe logging message for reverse driving (
"VelocityController: reverse driving"
) appears to be outside of theFIXED_SPEED_OVERRIDE
condition but should be part of theelse
block. This might lead to confusing logs when fixed speed mode is active.Apply this diff to fix the logging placement:
if self.FIXED_SPEED_OVERRIDE: reverse = True throttle = 1 brake = 0 + rospy.loginfo("VelocityController: reverse driving with fixed speed") else: reverse = True throttle = (-1) * self.pid_t(abs(target_velocity)) brake = 0 rospy.loginfo("VelocityController: reverse driving")
code/planning/src/behavior_agent/behaviors/unstuck_routine.py (2)
5-9
: Remove unused imports to keep code clean.
According to static analysis,Tuple
,Union
, andShapelyEntity
are not used, so it’s best to remove them for clarity.- from typing import Optional, Tuple, Union + from typing import Optional - from mapping_common.entity import ShapelyEntity, Entity + from mapping_common.entity import Entity🧰 Tools
🪛 Ruff (0.8.2)
5-5:
typing.Tuple
imported but unusedRemove unused import
(F401)
5-5:
typing.Union
imported but unusedRemove unused import
(F401)
9-9:
mapping_common.entity.ShapelyEntity
imported but unusedRemove unused import:
mapping_common.entity.ShapelyEntity
(F401)
344-349
: Combine the two branches to reduce repetition.
Since both conditions calladd_speed_override(-0.05)
, you can merge them:- if ( - get_distance(self.init_pos, self.current_pos) < UNSTUCK_CLEAR_DISTANCE - ) and not collision_detected: - add_speed_override(-0.05) - elif get_distance(self.init_pos, self.current_pos) < 0.5: - add_speed_override(-0.05) + if ( + (get_distance(self.init_pos, self.current_pos) < UNSTUCK_CLEAR_DISTANCE and not collision_detected) + or get_distance(self.init_pos, self.current_pos) < 0.5 + ): + add_speed_override(-0.05) + else: + add_speed_override(0.001)🧰 Tools
🪛 Ruff (0.8.2)
344-349: Combine
if
branches using logicalor
operatorCombine
if
branches(SIM114)
code/planning/src/behavior_agent/behaviors/lane_change.py (2)
69-70
: Avoid using a global variable for lane-change state in multi-threaded code.
UsingLANECHANGE_FREE
as a global variable can cause concurrency issues if multiple agents/threads access it simultaneously. Storing lane-change states in the behavior’s blackboard or a thread-safe data structure would improve maintainability and avoid data races.
556-567
: Reconsider returningStatus.FAILURE
on a successfully finished lane change.
When the lane change completes (line 565), the code returnsStatus.FAILURE
. Typically, a completed lane change aligns withStatus.SUCCESS
. Unless there is a design reason for a “finished” lane change to signal failure, consider using:- return debug_status( - self.name, Status.FAILURE, "Lane Change Change: Finished" - ) + return debug_status( + self.name, Status.SUCCESS, "Lane Change Change: Finished" + )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
build/agent_service.yaml
(0 hunks)code/acting/src/acting/passthrough.py
(2 hunks)code/control/src/vehicle_controller.py
(1 hunks)code/control/src/velocity_controller.py
(1 hunks)code/mapping/ext_modules/mapping_common/map.py
(1 hunks)code/perception/CMakeLists.txt
(2 hunks)code/perception/msg/LaneChange.msg
(1 hunks)code/perception/src/global_plan_distance_publisher.py
(4 hunks)code/planning/src/behavior_agent/behavior_tree.py
(2 hunks)code/planning/src/behavior_agent/behaviors/behavior_speed.py
(1 hunks)code/planning/src/behavior_agent/behaviors/lane_change.py
(5 hunks)code/planning/src/behavior_agent/behaviors/overtake.py
(3 hunks)code/planning/src/behavior_agent/behaviors/overtake_service_utils.py
(1 hunks)code/planning/src/behavior_agent/behaviors/topics2blackboard.py
(1 hunks)code/planning/src/behavior_agent/behaviors/unstuck_routine.py
(5 hunks)code/planning/src/local_planner/utils.py
(1 hunks)doc/general/architecture_current.md
(3 hunks)doc/general/architecture_planned.md
(1 hunks)doc/planning/motion_planning.md
(1 hunks)
💤 Files with no reviewable changes (1)
- build/agent_service.yaml
✅ Files skipped from review due to trivial changes (2)
- code/planning/src/behavior_agent/behaviors/overtake_service_utils.py
- doc/general/architecture_planned.md
🧰 Additional context used
🪛 Ruff (0.8.2)
code/planning/src/behavior_agent/behaviors/unstuck_routine.py
5-5: typing.Tuple
imported but unused
Remove unused import
(F401)
5-5: typing.Union
imported but unused
Remove unused import
(F401)
9-9: mapping_common.entity.ShapelyEntity
imported but unused
Remove unused import: mapping_common.entity.ShapelyEntity
(F401)
11-11: shapely
imported but unused
Remove unused import: shapely
(F401)
344-349: Combine if
branches using logical or
operator
Combine if
branches
(SIM114)
code/planning/src/behavior_agent/behaviors/lane_change.py
437-437: SyntaxError: Expected ',', found int
🪛 LanguageTool
doc/planning/motion_planning.md
[uncategorized] ~38-~38: Loose punctuation mark.
Context: ...rent waypoint. - /paf/hero/lane_change
: Subscribes to the Carla Waypoint to che...
(UNLIKELY_OPENING_PUNCTUATION)
🔇 Additional comments (30)
code/perception/msg/LaneChange.msg (1)
4-4
: Good addition of spatial information to enhance lane change messages.The addition of the
position
field usinggeometry_msgs/Point
type enhances the message by providing explicit spatial coordinates for the lane change point. This is a logical extension that complements the existingdistance
field, enabling more precise navigation during lane changes.code/mapping/ext_modules/mapping_common/map.py (1)
36-39
:✅ Verification successful
Well-structured enum for lane change direction.
The newly added
LaneFreeDirection
enum provides clear semantics for lane change directions with properly named constants (LEFT
andRIGHT
). This improves code readability and maintains consistency throughout lane change operations.One thing to verify: ensure that the boolean mapping (LEFT=False, RIGHT=True) is used consistently throughout the codebase to prevent potential confusion.
🏁 Script executed:
#!/bin/bash # Search for usages of LaneFreeDirection to ensure consistent usage rg "LaneFreeDirection\.(LEFT|RIGHT)" -A 2 -B 2Length of output: 3175
Enum Mapping for LaneFreeDirection Verified and Consistent
The
LaneFreeDirection
enum defined as:class LaneFreeDirection(Enum): LEFT = False RIGHT = Trueprovides clear semantics and aligns with the intended boolean mapping. A repository-wide search confirmed that the enum is used consistently in the lane change logic (e.g., in
code/planning/src/behavior_agent/behaviors/lane_change.py
).Approved.
doc/planning/motion_planning.md (1)
38-38
: Topic name updated correctly in documentation.The topic name has been updated from
/paf/hero/lane_change_distance
to/paf/hero/lane_change
to reflect the changes made throughout the codebase. This maintains consistency between the implementation and documentation.🧰 Tools
🪛 LanguageTool
[uncategorized] ~38-~38: Loose punctuation mark.
Context: ...rent waypoint. -/paf/hero/lane_change
: Subscribes to the Carla Waypoint to che...(UNLIKELY_OPENING_PUNCTUATION)
code/planning/src/behavior_agent/behaviors/behavior_speed.py (1)
60-60
:✅ Verification successful
Appropriate addition of new lane change behavior state.
The new
lc_wait_free
behavior with a non-zero speed (30 km/h) complements the existinglc_wait
behavior (0 speed). This appears to support the implementation of lane-free checks, allowing the vehicle to proceed at a moderate speed when the target lane is free rather than coming to a complete stop.Note that according to the file header comments, the speed values in this file are deprecated and "completely unused in favor of the ACC" since PR #725. Verify that the behavior name itself is being properly utilized in the lane change implementation.
🏁 Script executed:
#!/bin/bash # Search for usages of the new behavior name to ensure it's being used appropriately rg "lc_wait_free" --type pyLength of output: 276
Verification complete: "lc_wait_free" behavior is correctly integrated.
We confirmed that the new behavior is actively used within the lane change implementation (refer to the publish call in
code/planning/src/behavior_agent/behaviors/lane_change.py
). The utilization aligns with the intended design despite the deprecation of speed values per the header comments.code/control/src/vehicle_controller.py (1)
156-159
:❓ Verification inconclusive
Improved steering logic for unstuck and stop behaviors
The change inverts the steering direction during unstuck and stop behaviors, which should help the vehicle maneuver more effectively in recovery situations. This is a sensible approach as it allows the vehicle to steer in the opposite direction to get out of stuck positions.
To ensure this change doesn't cause unexpected behavior, verify this in simulation with these specific scenarios:
- Vehicle attempting to get unstuck from various positions
- Vehicle executing stop behaviors
- Testing that the transition between normal and unstuck/stop steering is smooth
🏁 Script executed:
#!/bin/bash # Search for any existing tests for unstuck or stop behaviors rg -A 3 -B 3 "us_unstuck|us_stop" --type pyLength of output: 3640
Simulation Verification Required: Confirm Unstuck & Stop Behavior Transitions
The modified steering logic (multiplying
_p_steer
by -1 forus_unstuck
andus_stop
) is implemented as intended incode/control/src/vehicle_controller.py
(lines 156–159). References in related modules (e.g., in planning and behavior routines) confirm these behaviors are triggered as expected. Please ensure that simulation tests cover the following:
- Vehicle unstuck scenarios: Validate steering inversion when the vehicle is trying to recover from being stuck.
- Stop behavior: Confirm that the vehicle executes a controlled stopping behavior.
- Transition smoothness: Verify that switching between normal and recovery (unstuck/stop) steering is seamless.
doc/general/architecture_current.md (2)
126-126
: Topic name update reflects the changes in codeThe topic rename from
lane_change_distance
tolane_change
is consistent with other changes in the codebase. This documentation update ensures that the architecture documentation stays accurate.
262-262
: Topic name update in local planning sectionThe topic reference has been properly updated here as well, maintaining consistency across the documentation.
code/planning/src/behavior_agent/behaviors/topics2blackboard.py (1)
95-95
:❓ Verification inconclusive
Topic subscription updated to match the new topic name
This change aligns the topic subscription with the renamed topic (
lane_change
instead oflane_change_distance
), consistent with the architectural changes throughout the codebase.To ensure the topic rename is consistent across the entire codebase:
🏁 Script executed:
#!/bin/bash # Check if there are any remaining references to the old topic name rg "lane_change_distance" --type pyLength of output: 35
Action: Manually Verify Topic Name Consistency
Automated searches across Python files show no lingering references to the old topic name “lane_change_distance.” However, since the initial script produced no output, please manually verify that:
- The file
code/planning/src/behavior_agent/behaviors/topics2blackboard.py
(line 95) correctly uses"name": f"/paf/{role_name}/lane_change"
without any residual references to “lane_change_distance.”- There are no occurrences of “lane_change_distance” in non-Python files (e.g., configuration, documentation, tests) that might affect the rename.
Once confirmed, you can safely assume the topic update is fully consistent.
code/perception/CMakeLists.txt (2)
17-17
: Added geometry_msgs dependency to support LaneChange message enhancementThe addition of geometry_msgs as a dependency is necessary to support the new position field in the LaneChange message, which allows for spatial information to be included in lane change data.
79-79
:✅ Verification successful
Added geometry_msgs to message generation dependencies
This correctly adds geometry_msgs to the message generation dependencies, ensuring that types from this package can be used in the LaneChange message. This change complements the addition to the find_package section above.
Verify that the LaneChange.msg file has been updated to include a position field of type geometry_msgs/Point:
🏁 Script executed:
#!/bin/bash # Check the LaneChange.msg file for the position field cat code/perception/msg/LaneChange.msgLength of output: 120
Review Confirmed: Geometry_msgs Dependency and Message Field Verification
The changes correctly add the
geometry_msgs
dependency, and theLaneChange.msg
file now includes theposition
field of typegeometry_msgs/Point
as expected.
- Verified in
code/perception/msg/LaneChange.msg
that the linegeometry_msgs/Point position
exists.- This update complements the changes made in CMakeLists.txt and the
find_package
additions.code/planning/src/behavior_agent/behavior_tree.py (1)
83-83
:✅ Verification successful
Lane change behavior has been simplified
The change from separate Enter/Leave actions to a single
Change
action simplifies the lane change process. This consolidation aligns with the PR objective to rework the lane change behavior.
🏁 Script executed:
#!/bin/bash # Description: Check for implementation of lane_change.Change class and its usage # Find the implementation of the Change class in lane_change.py rg -A 10 "class Change" code/planning/src/behavior_agent/behaviors/lane_change.pyLength of output: 395
Validated: Lane Change Behavior Simplification
The usage of
lane_change.Change("Execute Change")
in the behavior tree now aligns with the intended simplified lane change process. The implementation incode/planning/src/behavior_agent/behaviors/lane_change.py
confirms that theChange
class is correctly defined, inheriting frompy_trees.behaviour.Behaviour
, which meets the PR objectives.
- File Verified:
code/planning/src/behavior_agent/behaviors/lane_change.py
contains the properChange
class implementation.- Usage Confirmed: The instantiation
lane_change.Change("Execute Change")
incode/planning/src/behavior_agent/behavior_tree.py
is correct and reflects the consolidation of lane change actions.code/planning/src/local_planner/utils.py (2)
15-16
: Improved precision with floating-point valuesConverting integer values to floating-point improves precision in distance calculations, which is beneficial for vehicle control systems.
17-18
:❓ Verification inconclusive
New lane change distance parameters added
These new constants provide more nuanced control for lane change behaviors:
TARGET_DISTANCE_TO_STOP_LANECHANGE
: Defines when to stop during a lane changeTARGET_DISTANCE_TO_TRIGGER_LANECHANGE
: Controls when to trigger lane changesThe trigger distance of 75.0 meters seems quite large. Consider whether this distance is appropriate based on the comments in the PR about premature lane changes.
🏁 Script executed:
#!/bin/bash # Description: Check where and how the new lane change constants are used # Search for usage of TARGET_DISTANCE_TO_TRIGGER_LANECHANGE rg "TARGET_DISTANCE_TO_TRIGGER_LANECHANGE" -A 5 code/planning/src/behavior_agent/behaviors/ # Search for usage of TARGET_DISTANCE_TO_STOP_LANECHANGE rg "TARGET_DISTANCE_TO_STOP_LANECHANGE" -A 5 code/planning/src/behavior_agent/behaviors/Length of output: 2630
Action: Revisit and confirm lane change distance parameters
The new constants are correctly integrated in the lane change behavior code (see
code/planning/src/behavior_agent/behaviors/lane_change.py
). Specifically:
TARGET_DISTANCE_TO_STOP_LANECHANGE
(5.0 meters) is used to determine when a lane change should stop.TARGET_DISTANCE_TO_TRIGGER_LANECHANGE
(75.0 meters) is applied to trigger the lane change maneuver.Based on the verification output, these constants are consistently referenced. However, the trigger distance of 75.0 meters appears relatively high compared to the stopping distance, which might be a contributing factor for premature lane changes. Please reassess this value against simulation results or defined behavioral requirements to ensure it meets the intended control strategy.
code/acting/src/acting/passthrough.py (2)
61-67
: Updated mapped_topics listThe mapped_topics list is properly updated to include the new acc_to_target_velocity mapping, ensuring it's processed by the Passthrough class.
38-42
:✅ Verification successful
New topic mapping for acceleration velocity
This new
TopicMapping
creates a pass-through from/paf/{role_name}/acc_velocity
to/paf/hero/target_velocity
, enabling direct influence on target velocity from acceleration commands. This enhances the communication between components.
🏁 Script executed:
#!/bin/bash # Description: Verify topic naming consistency across the codebase # Check for other usages of the target_velocity topic rg "/paf/hero/target_velocity" --glob "!code/acting/src/acting/passthrough.py" # Check for other usages of the acc_velocity topic rg "/paf/hero/acc_velocity" --glob "!code/acting/src/acting/passthrough.py"Length of output: 1825
Validated Topic Mapping for Acceleration Velocity
The new
TopicMapping
incode/acting/src/acting/passthrough.py
(lines 38–42) correctly creates a pass-through from/paf/{role_name}/acc_velocity
to/paf/hero/target_velocity
. Verification shows that:
/paf/hero/target_velocity
is used consistently across launch files, behavior routines, and documentation./paf/hero/acc_velocity
is referenced in planning behaviors (e.g., inleave_parking_space.py
) and related documents.This confirms that the naming and implementation are consistent with the rest of the codebase. No further changes are needed.
code/control/src/velocity_controller.py (1)
111-124
: Improved handling of negative target velocitiesThe changes to reverse driving logic are beneficial:
- Simplified logic by handling all negative velocities as signals for reverse driving
- Added flexibility through PID-based throttle control when not in fixed speed mode
- Removed hard-coded checks for specific velocity values (-3)
These changes make the code more maintainable and adaptable to different scenarios, which is helpful for the lane change behavior enhancements.
code/planning/src/behavior_agent/behaviors/overtake.py (2)
369-370
: Resetting counter only if lane is blocked looks consistent.
This aligns with the idea that the counter should only reset if the oncoming lane is definitively blocked.
507-508
: Identical reset logic in Wait class.
Mirroring the same counter reset condition when the lane is blocked helps maintain consistency between behaviors.code/planning/src/behavior_agent/behaviors/unstuck_routine.py (4)
13-14
: Additional imports look correct.
The newly importedadd_speed_override
,debug_status
, anddebug_marker
appear to be used properly below.
16-19
: Stop mark service imports are used appropriately.
These look useful for adjusting stop marks during the unstuck routine.
22-24
: Configuration changes for stuck durations are fine.
Increasing the thresholds for stuck detection and wait seems intentional.
26-27
: Marker color and lookup distance adjustments are acceptable.
No obvious issues with the new constants.code/perception/src/global_plan_distance_publisher.py (6)
7-7
: Using RoadOption for clarity is a good step.
Replacing magic numbers with enumerations improves readability.
62-62
: Topic name change aligns with the new naming convention.
Switching to"/lane_change"
is consistent with the broader rename.
91-98
: Enumerated checks for normal driving options.
Relying onRoadOption.VOID, LEFT, RIGHT, STRAIGHT
fosters explicitness.
103-108
: Extended LaneChange message with position is logical.
Publishing the current route position can provide richer context.
112-115
: Conditional lane change checks.
Ensuring we only setlane_change=True
if we detect left/right lane changes is clearer.
131-135
: Fallback to LANEFOLLOW for repeated lane changes.
Setting the second upcoming road option toLANEFOLLOW
prevents unwanted double lane changes.code/planning/src/behavior_agent/behaviors/lane_change.py (2)
110-111
: Question the conditional usage ofRoadOption.CHANGELANERIGHT
.
Here, the conditionif RoadOption.CHANGELANERIGHT:
setslane_pos = 1
without comparing it toself.change_option
. This might always evaluate to true ifRoadOption.CHANGELANERIGHT
is a non-zero constant, leading to unintended logic. Consider confirming if the check should instead be:- if RoadOption.CHANGELANERIGHT: + if self.change_option == RoadOption.CHANGELANERIGHT:
285-288
: Ensure early-right lane changes are disallowed if no lane exists.
The logic at line 285 only checks lane-free conditions when changing to the left. This aligns with the comment about not changing to the right too early. However, make sure you also detect if a right lane is non-existent and handle it safely to prevent abrupt lane shifts onto walkways.Also applies to: 295-298
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
code/planning/src/behavior_agent/behaviors/lane_change.py (2)
17-17
: Remove unused import
Themath.isclose
import is unused throughout the file, as flagged by static analysis. Consider removing it to keep the code clean.- from math import isclose
🧰 Tools
🪛 Ruff (0.8.2)
17-17:
math.isclose
imported but unusedRemove unused import:
math.isclose
(F401)
69-70
: Question use of global state
The repeated assignment to the global variableLANECHANGE_FREE
here and elsewhere can complicate code clarity and maintainability. Globally shared mutable state can lead to subtle bugs if multiple behaviors alter it in conflicting ways.You might consider encapsulating the lane-free state logic within a class or the blackboard to avoid introducing potential side effects across behaviors.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
code/planning/src/behavior_agent/behaviors/lane_change.py
(5 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
code/planning/src/behavior_agent/behaviors/lane_change.py
17-17: math.isclose
imported but unused
Remove unused import: math.isclose
(F401)
🔇 Additional comments (1)
code/planning/src/behavior_agent/behaviors/lane_change.py (1)
283-349
: Verify lane change approach for right lane
The code explicitly handles early lane changes only whenself.change_direction
isLaneFreeDirection.LEFT
. Lane changes to the right do not undergo the same lane-free check in this approach block, which can be intentional to prevent unintended right-lane maneuvers. However, if you plan to allow early right-lane changes under certain conditions, you might need a symmetrical check.Would you like to:
- Keep the existing logic that prevents early right-lane changes?
- Add a similar lane-free approach check for
LaneFreeDirection.RIGHT
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
code/planning/src/behavior_agent/behaviors/lane_change.py (1)
107-110
:⚠️ Potential issueFix the lane position conditional logic.
The conditional check
if RoadOption.CHANGELANERIGHT:
is not comparing against any value, so it will always evaluate to True as long asRoadOption.CHANGELANERIGHT
has a non-zero/non-False value. This is likely not the intended behavior.Apply this diff to fix the conditional check:
- if RoadOption.CHANGELANERIGHT: + if self.change_option == RoadOption.CHANGELANERIGHT: lane_pos = 1
🧹 Nitpick comments (1)
code/planning/src/behavior_agent/behaviors/lane_change.py (1)
42-42
: Replace global variable with a better state management approach.Using a global variable like
LANECHANGE_FREE
makes the code harder to test, debug, and reason about. Consider using a blackboard parameter or class attribute instead for better encapsulation.- LANECHANGE_FREE = False
Add to the appropriate class:
def __init__(self, name): super().__init__(name) # Add to blackboard during initialization self.blackboard = py_trees.blackboard.Blackboard() self.blackboard.set("lanechange_free", False) # Then replace all references to the global variable: # global LANECHANGE_FREE -> self.blackboard.get("lanechange_free") # LANECHANGE_FREE = X -> self.blackboard.set("lanechange_free", X)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
code/planning/src/behavior_agent/behavior_tree.py
(1 hunks)code/planning/src/behavior_agent/behaviors/lane_change.py
(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- code/planning/src/behavior_agent/behavior_tree.py
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Build and push image
🔇 Additional comments (9)
code/planning/src/behavior_agent/behaviors/lane_change.py (9)
116-123
: Good approach to remove potential blocking stop marks.Removing the overtake stop marks before executing a lane change is a good practice to prevent conflicts between different behaviors.
125-145
: Clever handling of overtaking scenarios with lane changes.This is an elegant solution to handle the case where the vehicle is already in an overtaking maneuver when a lane change to the left is requested. By adapting the overtake end position rather than executing a separate lane change, you avoid unnecessary maneuvers.
232-238
: Good optimization to skip unnecessary states.Skipping the approach phase when the lane change is already determined to be free is an effective optimization that streamlines the behavior flow.
284-284
: Potential issue with left-only early lane change logic.The condition
self.change_direction is LaneFreeDirection.LEFT
means early lane changes are only attempted when changing to the left lane. While this makes sense based on the PR objective comment about avoiding driving on walkways, this could limit functionality.Consider whether this is the intended behavior and if there are scenarios where early lane changes to the right would be beneficial and safe. If you want to be more selective, consider checking for specific road conditions rather than disabling all right lane changes.
295-326
: Counter-based reliability pattern for lane-free checks.Using a counter to require multiple consecutive positive lane-free checks is an excellent approach to handle inconsistencies in sensor data or perception. This helps prevent premature lane changes based on false positive checks.
4-5
: Good addition of Point for positional awareness.Adding the Point import from geometry_msgs.msg to incorporate positional data in lane change decisions is a valuable enhancement that provides more context for decision-making.
157-158
:❓ Verification inconclusive
Validate coordinate transformation.
Make sure that the position values from the lane_change message are consistent with the coordinate system expected by the local_pos transformation. It would be safer to add a comment documenting the coordinate system expectations or add validation for the position values.
🏁 Script executed:
#!/bin/bash # Checking for coordinate system documentation or validation # Look for coordinate system documentation echo "Looking for coordinate system documentation..." rg -A 5 -B 5 "coordinate system" --glob "*.py" --glob "*.md" # Check the LaneChange message definition to understand position field echo "Checking LaneChange message definition..." rg -A 10 "LaneChange.msg" --type md,txt # Check for other transformations of position fields for comparison echo "Looking for similar position transformations..." rg -A 3 -B 3 "inverse\(\) \* Point2\.new\(" --glob "*.py"Length of output: 17663
Action: Add inline documentation/validation for coordinate transformation consistency.
Please ensure that the position values from the lane_change message (i.e.
self.change_position.x
andself.change_position.y
) are in the coordinate system required by the local position transformation. Consider the following:
- Add an inline comment or reference to the design documentation (e.g., see
doc/research/paf24/intermediate_layer/DesignDocument_TopDownMap.md
) that clearly states the expected coordinate system.- Optionally, implement a validation or assertion to confirm that the
lane_change
message values are properly formatted before applying the transformation.- Compare this transformation with similar operations (e.g., in
local_planner
orradar_node
) to ensure consistency across the codebase.
540-546
:❓ Verification inconclusive
Verify vector addition safety for position calculation.
The code adds a forward vector to the transformed position, but without clear documentation of the coordinate system. Ensure that this addition is correctly applying a 5-meter offset in the direction of travel.
🏁 Script executed:
#!/bin/bash # Look for similar Vector2.forward() usage echo "Searching for Vector2.forward() usage..." rg -A 3 -B 3 "Vector2\.forward\(\)" --glob "*.py" echo "Checking Vector2 class definition..." rg -A 20 "class Vector2" --glob "*.py"Length of output: 6358
Clarify Coordinate System for 5-Meter Offset
The calculation in lane change (lines 540–546) applies a 5-meter offset by adding
Vector2.forward() * 5.0
to the transformed position. We observed that similar patterns appear in other parts of the codebase (e.g., in the pure pursuit controller, ACC, and mapping modules), which suggests thatVector2.forward()
is consistently used to generate a forward offset. However, the underlying coordinate system—specifically, whetherVector2.forward()
reliably returns a unit vector in the proper travel direction—is not clearly documented here.Please verify that:
Vector2.forward()
returns a unit vector aligned with the intended forward direction.- The transformation applied via
hero_transform.inverse()
correctly positions the offset relative to the vehicle's coordinate frame.- Any assumptions about the coordinate system are either documented or referenced elsewhere in the codebase.
434-439
:❓ Verification inconclusive
Inconsistent check method between Approach and Wait.
In Approach.update(), the lane free check uses
check_method="fallback"
(line 289) while in Wait.update(), it usescheck_method="lanemarking"
(line 438). This inconsistency could lead to different behavior between the two states.If the intentional difference is to have stricter checks during waiting vs. approaching, consider adding a comment explaining this design decision.
🏁 Script executed:
#!/bin/bash # Check for documentation of check_method parameter # Look for definitions or usage of check_method parameter echo "Looking for check_method documentation or usage..." rg -A 5 -B 5 "check_method" --glob "*.py" # Look for definition of is_lane_free method echo "Looking for is_lane_free method definition..." rg -A 10 "def is_lane_free" --glob "*.py"Length of output: 15400
Clarification Needed: Document Intentional Use of Different
check_method
ValuesThe repository intentionally uses both
"fallback"
and"lanemarking"
as valid options for thecheck_method
parameter (see documentation incode/mapping/ext_modules/mapping_common/map.py
). For example, inlane_change.py
one branch uses"fallback"
(whenself.change_detected
is true and the direction is left) while another branch uses"lanemarking"
. A similar pattern is observed in other behaviors (e.g., in Approach vs. Wait states).To avoid confusion, please verify that this deliberate difference in lane free-checks is intended. If so, consider adding an inline comment explaining why one state (or branch) uses
"fallback"
while another uses"lanemarking"
, clarifying the design rationale behind these choices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
code/planning/src/behavior_agent/behaviors/lane_change.py (2)
41-43
: Consider avoiding global mutable state forLANECHANGE_FREE
.
Using a global variable (LANECHANGE_FREE
) in multiple classes and methods can introduce hidden dependencies and make the control flow harder to reason about, potentially leading to race conditions in more complex or multithreaded contexts. Storing this state in the blackboard, or encapsulating it in a dedicated class or data structure, would improve maintainability and testability.
403-409
: Potential race condition usingLANECHANGE_FREE
withinWait
.
TheWait
behavior terminates immediately ifLANECHANGE_FREE
is set, but this global state could be updated asynchronously byAhead
orApproach
. If multiple updates happen at once, the final state might become inconsistent. Ensuring thatWait
verifies the lane status from the blackboard or another deterministic source would reduce the risk of synchronization issues.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
code/planning/src/behavior_agent/behaviors/lane_change.py
(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
code/planning/src/behavior_agent/behaviors/lane_change.py (1)
Learnt from: Johannes1098
PR: una-auxme/paf#731
File: code/planning/src/behavior_agent/behaviors/lane_change.py:567-568
Timestamp: 2025-03-03T22:19:36.933Z
Learning: In the behavior tree for lane change in `code/planning/src/behavior_agent/behaviors/lane_change.py`, the last sub-behavior (`Change`) intentionally returns `Status.FAILURE` when completed to signal termination of the subtree and exit the lane change behavior sequence.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Build and push image
🔇 Additional comments (4)
code/planning/src/behavior_agent/behaviors/lane_change.py (4)
68-69
: Re-initializingLANECHANGE_FREE
on eachAhead
initialization may cause logical confusion.
Every time theAhead
behavior starts,LANECHANGE_FREE
is set toFalse
. If other behaviors rely on this global flag’s prior state, the reset here could lead to unexpected transitions. Verify whether this repeated re-initialization accurately reflects the intended design.
128-140
: Confirm overtake end logic consistency.
When an overtake is already in progress and a left-lane change is requested, the code adapts the overtake end position rather than performing a separate lane change. Double-check that the newly computedend_transition_length
andend_pos
properly facilitate a safe, completed maneuver in all edge cases (e.g., slow-moving traffic).
157-177
: Validate stop mark usage during lane change.
The code creates a 20m-long stop mark slightly offset from the hero vehicle’s position. While this helps block the lane for oncoming or conflicting traffic, ensure that this offset correctly accounts for different road widths and does not inadvertently place the stop mark where it can cause collisions with adjacent lanes or sidewalks.
557-568
: ReturningStatus.FAILURE
upon successful lane change is intentional.
This return value can appear counterintuitive; however, based on prior conversations (), you are usingFAILURE
to terminate the lane change subtree. As long as the parent behavior is designed to interpret this as a completed lane change, no further changes are required.
# (as there could be no road till change point!) | ||
if self.change_detected and self.change_direction is LaneFreeDirection.LEFT: | ||
lc_free, lc_mask = tree.is_lane_free( | ||
right_lane=self.change_direction.value, | ||
lane_length=22.5, | ||
lane_transform=-5.0, | ||
check_method="fallback", | ||
) | ||
if isinstance(lc_mask, shapely.Polygon): | ||
add_debug_marker(debug_marker(lc_mask, color=LANECHANGE_MARKER_COLOR)) | ||
add_debug_entry(self.name, f"Lane change: Is lane free? {lc_free.name}") | ||
if lc_free is LaneFreeState.FREE: | ||
self.counter_lanefree += 1 | ||
# using a counter to account for inconsistencies | ||
if self.counter_lanefree > 1: | ||
# bool to skip Wait since oncoming is free | ||
LANECHANGE_FREE = True | ||
if self.change_direction is LaneFreeDirection.RIGHT: | ||
lanechange_offset = -2.5 | ||
else: | ||
lanechange_offset = 2.5 | ||
end_transition_length = min(15.0, self.change_distance + 9.0) | ||
request_start_overtake( | ||
proxy=self.start_overtake_proxy, | ||
offset=lanechange_offset, | ||
local_end_pos=Point2.new( | ||
self.change_distance + 10.0, lanechange_offset | ||
), | ||
end_transition_length=end_transition_length, | ||
) | ||
update_stop_marks( | ||
self.stop_proxy, | ||
id=LANECHANGE_STOPMARK_ID, | ||
reason="lane not blocked", | ||
is_global=False, | ||
marks=[], | ||
) | ||
self.curr_behavior_pub.publish(bs.lc_app_free.name) | ||
return debug_status( | ||
self.name, | ||
Status.SUCCESS, | ||
"Lane Change: Lane free, changing directly", | ||
) | ||
else: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Review the decision to skip lane-free checks for right-lane changes.
Currently, the lane-free check is only applied if self.change_direction
is LaneFreeDirection.LEFT
. This avoids early right-lane changes, but if the map triggers a right-lane change prematurely, the vehicle might still drift onto a walkway if no lane is available. Consider either adding a similar is_lane_free
check for the right-lane scenario or ensuring the logic defers any right-lane maneuver until the lane definitely exists and is safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
code/planning/src/behavior_agent/behaviors/lane_change.py (3)
41-42
: Document the purpose of the LANECHANGE_FREE global variable.The newly introduced global variable
LANECHANGE_FREE
is used to track lane change state across multiple behaviors, but lacks documentation explaining its purpose and expected usage patterns.Add a comment explaining that this global variable is used to coordinate state across the Ahead, Approach, Wait, and Change behaviors to indicate when a lane is free for changing.
161-176
: Consider adding a safety margin to the stop mark shape.The stop mark for a lane change is currently set to exactly match the needed space. Consider adding a small safety margin to the dimensions to account for imperfect localization or control.
- stop_mark_shape = Rectangle( - length=20.0, - width=2.5, - offset=Transform2D.new_translation( - Vector2.new( - local_pos.x() + 10.0, local_pos.y() + lane_pos * 2.5 - ) - ), - ) + # Add safety margins to stop mark to account for control inaccuracies + stop_mark_shape = Rectangle( + length=22.0, # +2.0 safety margin + width=3.0, # +0.5 safety margin + offset=Transform2D.new_translation( + Vector2.new( + local_pos.x() + 11.0, local_pos.y() + lane_pos * 2.5 + ) + ), + )
444-467
: Consider documenting the counter approach for lane state detection.The counter-based approach for confirming lane-free state is a good way to mitigate sensor noise and intermittent lane detection issues. However, it's not immediately obvious why this approach was chosen.
Add a comment explaining that the counter approach helps filter out transient false positives in lane-free detection due to sensor noise or detection inconsistencies, requiring multiple consecutive positive detections before taking action.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
code/planning/src/behavior_agent/behaviors/lane_change.py
(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
code/planning/src/behavior_agent/behaviors/lane_change.py (1)
Learnt from: Johannes1098
PR: una-auxme/paf#731
File: code/planning/src/behavior_agent/behaviors/lane_change.py:567-568
Timestamp: 2025-03-03T22:19:36.933Z
Learning: In the behavior tree for lane change in `code/planning/src/behavior_agent/behaviors/lane_change.py`, the last sub-behavior (`Change`) intentionally returns `Status.FAILURE` when completed to signal termination of the subtree and exit the lane change behavior sequence.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Build and push image
🔇 Additional comments (7)
code/planning/src/behavior_agent/behaviors/lane_change.py (7)
110-111
: LGTM! Issue fixed.The comparison logic now correctly checks if the lane change option equals
RoadOption.CHANGELANERIGHT
.
127-147
: Well-handled special case for lane changes during overtaking.This intelligent handling of lane changes to the left when already overtaking is a good solution. It avoids redundant maneuvers by adapting the existing overtake parameters rather than executing a separate lane change.
562-563
: LGTM! Intentional FAILURE return for behavior tree control flow.The
Status.FAILURE
return when the lane change is finished is intentional to signal termination of the subtree and exit the lane change behavior sequence, as confirmed in the learned feedback.
535-541
:❓ Verification inconclusive
Verify trajectory calculation logic during lane change.
The calculation to determine if the lane change is complete involves getting a point 5 meters behind the global change point. Ensure this logic works correctly for various lane geometries and vehicle approaches.
🏁 Script executed:
#!/bin/bash # Check for any existing tests or simulation scenarios involving lane changes # Look for test files related to lane changes fd "test.*lane.*change" --type f # Look for simulation scenarios that might test lane changes fd "lane.*change.*scenario" --type f fd "scenario.*lane.*change" --type fLength of output: 112
Action Required: Manually Verify Lane Change Trajectory Calculation
Our search for automated tests related to lane change scenarios returned no output. This suggests that the trajectory calculation logic hasn't been validated via tests yet. Please ensure that the transformation applied using_get_global_hero_transform()
combined with the addition ofVector2.forward() * 5.0
truly yields the intended 5-meter shift in various lane geometries and vehicle approach scenarios.
- Confirm that
_get_global_hero_transform()
provides correct global coordinates.- Verify that the transformation inversion and addition of the forward vector correctly computes the new local position.
- Consider adding or updating simulation tests to cover diverse lane change geometries.
93-94
:❓ Verification inconclusive
Validate the usage of lane_change.position.
This code now extracts the
position
field from thelane_change
message, which was newly added to theLaneChange
message type. Ensure that all publishers of this message include valid position information.
🏁 Script executed:
#!/bin/bash # Find all locations that publish to lane_change topics and check if they populate the position field # Search for lane_change publishers in the codebase echo "Looking for lane_change publishers..." rg -A 5 -B 5 "publish.*lane_change" --type pyLength of output: 132
ACTION REQUIRED: Verify that all lane_change publishers are setting the new position field properly.
The current change extracts
lane_change.position
from the message, but our automated search did not locate any code publishing to the lane_change topic that explicitly sets theposition
field. Please perform a manual review of the publisher implementations for theLaneChange
message to confirm that they correctly populate this field.
282-326
:❓ Verification inconclusive
Consider a different approach for right-lane change safety.
The current implementation intentionally skips lane-free checks for right-lane changes to avoid premature lane changes that could lead to driving on walkways. While this addresses the immediate concern, it might not detect obstacles on the target lane early enough.
Consider implementing a progressive checking approach for right-lane changes that still performs the lane-free check but at a progressively decreasing distance as the vehicle approaches the lane change point. This would allow early detection of obstacles while avoiding premature lane changes.
🏁 Script executed:
#!/bin/bash # Checking if lane-free check is implemented for other methods that could be adapted # Check if there are adaptive or progressive checking methods in the mapping code rg -A 5 "is_lane_free" --type pyLength of output: 6612
Action Required: Enhance Right-Lane Change Safety Checks via a Progressive Approach
The current implementation deliberately omits early lane-free checks for right-lane changes to prevent initiating premature maneuvers (and potential incursions onto walkways). While this prevents some risks, it also delays obstacle detection on the target lane when approaching the change point. In contrast, similar functions (as seen in the mapping module and overtaking behavior) use checks with various methods (like
"fallback"
and"lanemarking"
) but do not yet incorporate a dynamic, progressive distance approach.Suggestions:
- Evaluate updating the right-lane change logic (in
code/planning/src/behavior_agent/behaviors/lane_change.py
, lines 282–326) to include a progressive lane-free check. This could involve starting the check at a longer distance and then tightening the parameters (e.g., adjustinglane_length
orlane_transform
) as the vehicle nears the lane change point.- Review and consider adapting techniques similar to those in
code/mapping/ext_modules/mapping_common/map.py
where parameters likereduce_lane
are leveraged to dynamically adjust the lane-free evaluation.Please verify that this change will not introduce premature lane changes in other scenarios while still ensuring obstacles are detected early enough.
434-439
:❓ Verification inconclusive
Inconsistent lane-free check methods between Approach and Wait.
The
Approach
class uses "fallback" method while theWait
class uses "lanemarking" method for the lane-free check. These inconsistencies could lead to different behaviors in different phases.
🏁 Script executed:
#!/bin/bash # Check the implementation differences between lane-free check methods # Find the implementation of is_lane_free rg -A 20 "def is_lane_free" --type py # Look for documentation on the different check methods rg "check_method" --type py # Find usage patterns of the different methods rg "check_method=\"fallback\"" --type py rg "check_method=\"lanemarking\"" --type pyLength of output: 7730
Review Note: Verify Consistency of Lane-Free Check Methods
The usage of the
is_lane_free
method appears to vary across behavior modules. For example, in some parts of the code (including withinlane_change.py
andovertake.py
), the "fallback" method is used, while in other parts (such as the snippet shown inlane_change.py
and inleave_parking_space.py
), the "lanemarking" method is applied. The original comment mentioned that theApproach
behavior uses "fallback" whereas theWait
behavior relies on "lanemarking." Given that the underlying function supports several check methods ("rectangle", "lanemarking", and "fallback"), please verify that these differences reflect an intentional design choice rather than an oversight.Action Items:
- Confirm whether the distinct methods (“fallback” vs. “lanemarking”) are deliberately chosen for different phases (e.g., Approach vs. Wait) or if they should be unified.
- Review the configuration across the relevant behavior classes (including Approach, Wait, lane change, and overtake) to ensure consistent lane-checking criteria and predictable behavior.
- If the divergence is unintended, refactor the code to use a consistent check method or clearly document the rationale for the differences.
Description
Before changing lanes in the behavior lane change, a lane-free check should be performed.
The work started harmlessly -
BUT ended up in a complete rework of this behavior:
Fixes #688
Type of change
Does this PR introduce a breaking change?
Publisher "lane_change_distance" is now only "lane_change".
But changed the name everywhere (not used outside behavior tree and lane change)
Most important changes
code/perception/src/global_plan_distance_publisher.py
code/planning/src/behavior_agent/behavior_tree.py
code/planning/src/behavior_agent/behaviors/behavior_speed.py
code/planning/src/behavior_agent/behaviors/lane_change.py
code/planning/src/behavior_agent/behaviors/topics2blackboard.py
code/planning/src/local_planner/utils.py
code/perception/CMakeLists.txt
code/perception/msg/LaneChange.msg
build/agent_service.yaml
doc/general/architecture_current.md
doc/general/architecture_planned.md
doc/planning/motion_planning.md
Checklist:
Summary by CodeRabbit
New Features
Refactor
Documentation