@@ -511,90 +511,83 @@ inline void savitskyGolayFilter(
511511}
512512
513513/* *
514- * @brief Find the first pose at which there is an in-place rotation in the path
515- * @param path Path to check
516- * @param rotation_threshold Minimum rotation angle to consider this an in-place rotation
517- * @return Index after the rotation sequence if found, path size if no rotation detected
514+ * @brief Find the iterator of the first pose at which there is an inversion or in-place rotation in the path
515+ * @param path to check for inversion or rotation
516+ * @param rotation_threshold Minimum rotation angle to consider an in-place rotation (0 to disable rotation check)
517+ * @return the first point after the inversion or rotation found in the path
518518 */
519- inline unsigned int findFirstPathRotation (
520- const nav_msgs::msg::Path & path,
521- float rotation_threshold)
519+ inline unsigned int findFirstPathInversion (
520+ nav_msgs::msg::Path & path,
521+ float rotation_threshold = 0 . 0f )
522522{
523523 if (path.poses .size () < 2 ) {
524524 return path.poses .size ();
525525 }
526526
527- // Iterate through path to find first in-place rotation
528- for (unsigned int idx = 0 ; idx < path.poses .size () - 1 ; ++idx) {
529- float dx = path.poses [idx + 1 ].pose .position .x - path.poses [idx].pose .position .x ;
530- float dy = path.poses [idx + 1 ].pose .position .y - path.poses [idx].pose .position .y ;
531- float translation = sqrtf (dx * dx + dy * dy);
532-
533- // Check if poses are at roughly the same location
534- if (translation < 1e-3 ) {
535- float yaw1 = tf2::getYaw (path.poses [idx].pose .orientation );
536- float yaw2 = tf2::getYaw (path.poses [idx + 1 ].pose .orientation );
537- float rotation = fabs (angles::shortest_angular_distance (yaw1, yaw2));
538-
539- // Check if this meets the minimum rotation threshold
540- if (rotation > rotation_threshold) {
541- // Found start of in-place rotation, now find where it ends
542- unsigned int end_idx = idx + 1 ;
543-
544- // Continue while we have minimal translation (still rotating in place)
545- while (end_idx < path.poses .size () - 1 ) {
546- float next_dx = path.poses [end_idx + 1 ].pose .position .x -
547- path.poses [end_idx].pose .position .x ;
548- float next_dy = path.poses [end_idx + 1 ].pose .position .y -
549- path.poses [end_idx].pose .position .y ;
550- float next_translation = sqrtf (next_dx * next_dx + next_dy * next_dy);
551-
552- if (next_translation >= 1e-3 ) {
553- break ; // End of in-place rotation sequence
527+ unsigned int first_constraint = path.poses .size ();
528+
529+ // Check for in-place rotation first (if enabled)
530+ if (rotation_threshold > 0 .0f ) {
531+ for (unsigned int idx = 0 ; idx < path.poses .size () - 1 ; ++idx) {
532+ float dx = path.poses [idx + 1 ].pose .position .x - path.poses [idx].pose .position .x ;
533+ float dy = path.poses [idx + 1 ].pose .position .y - path.poses [idx].pose .position .y ;
534+ float translation = sqrtf (dx * dx + dy * dy);
535+
536+ // Check if poses are at roughly the same location
537+ if (translation < 1e-3 ) {
538+ float yaw1 = tf2::getYaw (path.poses [idx].pose .orientation );
539+ float yaw2 = tf2::getYaw (path.poses [idx + 1 ].pose .orientation );
540+ float rotation = fabs (angles::shortest_angular_distance (yaw1, yaw2));
541+
542+ // Check if this meets the minimum rotation threshold
543+ if (rotation > rotation_threshold) {
544+ // Found start of in-place rotation, now find where it ends
545+ unsigned int end_idx = idx + 1 ;
546+
547+ // Continue while we have minimal translation (still rotating in place)
548+ while (end_idx < path.poses .size () - 1 ) {
549+ float next_dx = path.poses [end_idx + 1 ].pose .position .x -
550+ path.poses [end_idx].pose .position .x ;
551+ float next_dy = path.poses [end_idx + 1 ].pose .position .y -
552+ path.poses [end_idx].pose .position .y ;
553+ float next_translation = sqrtf (next_dx * next_dx + next_dy * next_dy);
554+
555+ if (next_translation >= 1e-3 ) {
556+ break ; // End of in-place rotation sequence
557+ }
558+ end_idx++;
554559 }
555- end_idx++;
556- }
557560
558- return end_idx;
561+ first_constraint = end_idx;
562+ break ;
563+ }
559564 }
560565 }
561566 }
562567
563- return path.poses .size (); // No significant rotation detected
564- }
565-
566- /* *
567- * @brief Find the iterator of the first pose at which there is an inversion on the path,
568- * @param path to check for inversion
569- * @return the first point after the inversion found in the path
570- */
571- inline unsigned int findFirstPathInversion (nav_msgs::msg::Path & path)
572- {
573- // At least 3 poses for a possible inversion
574- if (path.poses .size () < 3 ) {
575- return path.poses .size ();
576- }
577-
578- // Iterating through the path to determine the position of the path inversion
579- for (unsigned int idx = 1 ; idx < path.poses .size () - 1 ; ++idx) {
580- // We have two vectors for the dot product OA and AB. Determining the vectors.
581- float oa_x = path.poses [idx].pose .position .x -
582- path.poses [idx - 1 ].pose .position .x ;
583- float oa_y = path.poses [idx].pose .position .y -
584- path.poses [idx - 1 ].pose .position .y ;
585- float ab_x = path.poses [idx + 1 ].pose .position .x -
586- path.poses [idx].pose .position .x ;
587- float ab_y = path.poses [idx + 1 ].pose .position .y -
588- path.poses [idx].pose .position .y ;
589-
590- // Checking for the existence of cusp, in the path, using the dot product.
591- float dot_product = (oa_x * ab_x) + (oa_y * ab_y);
592- if (dot_product < 0 .0f ) {
593- return idx + 1 ;
568+ // Check for inversion (at least 3 poses needed)
569+ if (path.poses .size () >= 3 ) {
570+ for (unsigned int idx = 1 ; idx < path.poses .size () - 1 ; ++idx) {
571+ // We have two vectors for the dot product OA and AB. Determining the vectors.
572+ float oa_x = path.poses [idx].pose .position .x -
573+ path.poses [idx - 1 ].pose .position .x ;
574+ float oa_y = path.poses [idx].pose .position .y -
575+ path.poses [idx - 1 ].pose .position .y ;
576+ float ab_x = path.poses [idx + 1 ].pose .position .x -
577+ path.poses [idx].pose .position .x ;
578+ float ab_y = path.poses [idx + 1 ].pose .position .y -
579+ path.poses [idx].pose .position .y ;
580+
581+ // Checking for the existence of cusp, in the path, using the dot product.
582+ float dot_product = (oa_x * ab_x) + (oa_y * ab_y);
583+ if (dot_product < 0 .0f ) {
584+ first_constraint = std::min (first_constraint, idx + 1 );
585+ break ;
586+ }
594587 }
595588 }
596589
597- return path. poses . size () ;
590+ return first_constraint ;
598591}
599592
600593/* *
@@ -609,15 +602,7 @@ inline unsigned int removePosesAfterFirstInversion(
609602{
610603 nav_msgs::msg::Path cropped_path = path;
611604
612- // Check for in-place rotation first (if enabled)
613- unsigned int first_constraint = path.poses .size ();
614- if (rotation_threshold > 0 .0f ) {
615- first_constraint = findFirstPathRotation (cropped_path, rotation_threshold);
616- }
617-
618- // Check for inversion and take whichever comes first
619- const unsigned int first_after_inversion = findFirstPathInversion (cropped_path);
620- first_constraint = std::min (first_constraint, first_after_inversion);
605+ const unsigned int first_constraint = findFirstPathInversion (cropped_path, rotation_threshold);
621606
622607 if (first_constraint == path.poses .size ()) {
623608 return 0u ; // No constraint found
0 commit comments