Skip to content

Conversation

@ashleshp
Copy link
Collaborator

No description provided.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR represents "Release 3" of the cartesian planner, refactoring the package from a SLERP-based trajectory planner to a Spline-based implementation. The changes introduce new action/service interfaces for spline-based motion planning and add a raster scanning capability for surface inspection tasks.

Key changes:

  • Replaced SLERP interpolation with cubic spline-based trajectory generation
  • Added action server for executing spline-based motion plans
  • Added service for raster scan pattern generation and execution
  • Removed KDL-related dependencies in favor of direct tf_transformations usage

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
srv/PlanScanPath.srv New service definition for raster scan path planning with configurable scan parameters
package.xml Updated package description and dependencies; removed KDL dependencies, added rosidl_default_runtime
images/RasterPath.png Added visualization image for raster scan documentation
cartesian_planner/spline_planner.py New spline-based planner implementation with action server and raster scan service
cartesian_planner/slerp_planner.py Removed old SLERP-based implementation
action/PlanSpline.action New action definition for spline-based trajectory execution with progress feedback
README.md Updated documentation to reflect spline-based approach and raster scan feature
CMakeLists.txt Updated build configuration for new interfaces and Python package installation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

height = request.height if request.height > 0 else 0.80

start_pose = self._get_current_pose()
if start_pose is None or isinstance(start_pose, Exception):
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The condition isinstance(start_pose, Exception) is incorrect. The _get_current_pose method returns either a Pose object or None, never an Exception. This check will always be False and should be removed.

Suggested change
if start_pose is None or isinstance(start_pose, Exception):
if start_pose is None:

Copilot uses AI. Check for mistakes.
return []
spline = CubicSpline(t_knots, points, axis=0, bc_type="clamped")

spacing_along = max(spacing_along, 0.05)
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The reassignment of spacing_along here is redundant since it was already constrained to a minimum of 0.05 at line 206. This duplicate constraint should be removed or the comment should clarify why it's needed here.

Suggested change
spacing_along = max(spacing_along, 0.05)

Copilot uses AI. Check for mistakes.
response.message = "Raster execution failed"
return response

def _generate_raster(self, center: Pose, width: float, height: float, spacing_along: float, spacing_lines: float, orientation) -> List[Pose]:
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The parameter name orientation is ambiguous without type hints. Consider renaming it to fixed_orientation to match its usage in the calling code and improve clarity.

Suggested change
def _generate_raster(self, center: Pose, width: float, height: float, spacing_along: float, spacing_lines: float, orientation) -> List[Pose]:
def _generate_raster(self, center: Pose, width: float, height: float, spacing_along: float, spacing_lines: float, fixed_orientation) -> List[Pose]:

Copilot uses AI. Check for mistakes.
goal_pos = np.array([goal.position.x, goal.position.y, goal.position.z], dtype=float)
translation_distance = float(np.linalg.norm(goal_pos - start_pos))
if translation_distance < 1e-6:
return [], []
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The function returns a tuple of two empty lists when translation_distance is very small, but the caller expects only a single list of poses. This will cause the unpacking to fail. The return statement should be return [] instead of return [], [].

Suggested change
return [], []
return []

Copilot uses AI. Check for mistakes.
last = None
for t in t_samples:
pos = spline(t)
if last is not None and np.linalg.norm(pos - last) < spacing_along - 1e-4:
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The spacing filtering condition may cause unexpected behavior. The check np.linalg.norm(pos - last) < spacing_along - 1e-4 uses spacing_along - 1e-4 as a threshold, but this could skip valid waypoints if the distance is exactly at or near spacing_along. The condition should likely be < spacing_along * 0.5 or similar to filter only truly redundant points, or the logic should be reconsidered.

Suggested change
if last is not None and np.linalg.norm(pos - last) < spacing_along - 1e-4:
if last is not None and np.linalg.norm(pos - last) < 0.5 * spacing_along:

Copilot uses AI. Check for mistakes.
try:
executor.spin()
except (KeyboardInterrupt, ExternalShutdownException):
pass
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
pass
node.get_logger().info("Shutting down spline_planner executor due to external signal.")

Copilot uses AI. Check for mistakes.
@Robots4Sustainability Robots4Sustainability deleted a comment from Copilot AI Dec 17, 2025
@Robots4Sustainability Robots4Sustainability deleted a comment from Copilot AI Dec 17, 2025
@Robots4Sustainability Robots4Sustainability deleted a comment from Copilot AI Dec 17, 2025
@vamsikalagaturu
Copy link
Collaborator

@ashleshp you haven't added any references for your math, which I asked you last time. And, why didn't you use existing implementations of raster scan?

why did you made functions async and then waiting on them with await? it doesnt make sense. what is the requirement there?

you souldn't control the robot directly. you should send the trajectory and send updates to existing ones. but the control should happen by the control node.

raster_scan implementation seems semantically wrong in terms of "raster_scan" definition. you did S scan motion, which is not raster_scanning.

@ashleshp
Copy link
Collaborator Author

ashleshp commented Jan 16, 2026

@vamsikalagaturu

  1. The math code for the initial slerp implementation was mostly generated code as I mentioned in the email . The current implementation of slerp on main branch uses methods from scipy. But I now understand the math for slerp and spline (not derivations). By existing implementations of raster scan if you mean using of a library , I did not find any pytthon library that helps me implement raster scan with smooth curves.

  2. Because await lets other things still process/run , while testing on the robot I wanted to stop the motion mid way and Ctrl+C took some time to stop the motion.

  3. Yes I know that sending individual way-points repeatedly is not the right way but eddie interface action server did not support execution of Trajectory during the review as I was not working on that node so as a work around I kept sending individual waypoints. I think the appropriate way would be to use cartesian_control_msgs/CartesianTrajectory (Please correct me if I am wrong)

  4. The current code is not just for S like movement but also supports like below , It depends on height,width,line spacing parameters. But as you said in the review feedback the scan area should be detected from perception and then raster scan trajectory should be calculated

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants