python-motion-planning 2.0__tar.gz → 2.0.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/PKG-INFO +15 -15
  2. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/README.md +14 -14
  3. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/pyproject.toml +1 -1
  4. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/__init__.py +1 -1
  5. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/utils/geometry.py +29 -18
  6. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/__init__.py +9 -0
  7. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/bezier_curve.py +131 -0
  8. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/bspline_curve.py +271 -0
  9. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/cubic_spline.py +128 -0
  10. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/curve.py +64 -0
  11. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/dubins_curve.py +348 -0
  12. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/fem_pos_smooth.py +114 -0
  13. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/polynomial_curve.py +226 -0
  14. python_motion_planning-2.0.dev2/src/python_motion_planning/curve_generator/reeds_shepp.py +736 -0
  15. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/sample_search/rrt.py +5 -5
  16. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/sample_search/rrt_connect.py +2 -2
  17. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/sample_search/rrt_star.py +11 -31
  18. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning.egg-info/PKG-INFO +15 -15
  19. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning.egg-info/SOURCES.txt +10 -12
  20. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/__init__.py +0 -2
  21. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/base_curve_generator.py +0 -53
  22. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/__init__.py +0 -2
  23. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/point_based/__init__.py +0 -2
  24. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/point_based/bspline.py +0 -256
  25. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/point_based/cubic_spline.py +0 -115
  26. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/pose_based/__init__.py +0 -4
  27. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/pose_based/bezier.py +0 -121
  28. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/pose_based/dubins.py +0 -355
  29. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/pose_based/polynomial.py +0 -197
  30. python_motion_planning-2.0/src/python_motion_planning/traj_optimizer/curve_generator/pose_based/reeds_shepp.py +0 -606
  31. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/LICENSE +0 -0
  32. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/setup.cfg +0 -0
  33. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/__init__.py +0 -0
  34. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/__init__.py +0 -0
  35. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/map/__init__.py +0 -0
  36. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/map/base_map.py +0 -0
  37. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/map/grid.py +0 -0
  38. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/node.py +0 -0
  39. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/robot/__init__.py +0 -0
  40. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/robot/base_robot.py +0 -0
  41. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/robot/circular_robot.py +0 -0
  42. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/robot/diff_drive_robot.py +0 -0
  43. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/types.py +0 -0
  44. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/world/__init__.py +0 -0
  45. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/world/base_world.py +0 -0
  46. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/env/world/toy_simulator.py +0 -0
  47. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/utils/__init__.py +0 -0
  48. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/utils/child_tree.py +0 -0
  49. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/utils/frame_transformer.py +0 -0
  50. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/visualizer/__init__.py +0 -0
  51. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/visualizer/base_visualizer.py +0 -0
  52. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/visualizer/visualizer_2d.py +0 -0
  53. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/common/visualizer/visualizer_3d.py +0 -0
  54. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/__init__.py +0 -0
  55. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/base_controller.py +0 -0
  56. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/__init__.py +0 -0
  57. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/apf.py +0 -0
  58. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/dwa.py +0 -0
  59. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/path_tracker.py +0 -0
  60. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/pid.py +0 -0
  61. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/pure_pursuit.py +0 -0
  62. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/path_tracker/rpp.py +0 -0
  63. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/controller/random_controller.py +0 -0
  64. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/__init__.py +0 -0
  65. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/base_path_planner.py +0 -0
  66. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/__init__.py +0 -0
  67. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/a_star.py +0 -0
  68. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/dijkstra.py +0 -0
  69. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/gbfs.py +0 -0
  70. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/jps.py +0 -0
  71. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/lazy_theta_star.py +0 -0
  72. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/graph_search/theta_star.py +0 -0
  73. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/hybrid_search/__init__.py +0 -0
  74. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/hybrid_search/voronoi_planner.py +0 -0
  75. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning/path_planner/sample_search/__init__.py +0 -0
  76. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning.egg-info/dependency_links.txt +0 -0
  77. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning.egg-info/requires.txt +0 -0
  78. {python_motion_planning-2.0 → python_motion_planning-2.0.dev2}/src/python_motion_planning.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-motion-planning
3
- Version: 2.0
3
+ Version: 2.0.dev2
4
4
  Summary: Motion planning algorithms for Python
5
5
  Maintainer-email: Wu Maojia <omige@mail.nwpu.edu.cn>, Yang Haodong <913982779@qq.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -697,8 +697,6 @@ Dynamic: license-file
697
697
 
698
698
  # Introduction
699
699
 
700
- `Python Motion Planning` repository provides the implementations of common `Motion planning` algorithms, including path planners on N-D grid, controllers for path-tracking, curve generators, a visualizer based on matplotlib and a toy physical simulator to test controllers.
701
-
702
700
  `Motion planning` plans the state sequence of the robot without conflict between the start and goal.
703
701
 
704
702
  `Motion planning` mainly includes `Path planning` and `Trajectory planning`.
@@ -706,6 +704,8 @@ Dynamic: license-file
706
704
  * `Path Planning`: It's based on path constraints (such as obstacles), planning the optimal path sequence for the robot to travel without conflict between the start and goal.
707
705
  * `Trajectory planning`: It plans the motion state to approach the global path based on kinematics, dynamics constraints and path sequence.
708
706
 
707
+ This repository provides the implementations of common `Motion planning` algorithms, including path planners on N-D grid and controllers for path-tracking, a visualizer based on matplotlib and a toy physical simulator to test controllers.
708
+
709
709
  The theory analysis can be found at [motion-planning](https://blog.csdn.net/frigidwinter/category_11410243.html).
710
710
 
711
711
  We also provide [ROS C++](https://github.com/ai-winter/ros_motion_planning) version and [Matlab](https://github.com/ai-winter/matlab_motion_planning) version.
@@ -732,8 +732,7 @@ python_motion_planning
732
732
  | ├─graph_search
733
733
  | ├─sample_search
734
734
  | └─hybrid_search
735
- └─traj_optimizer
736
- | └─curve_generator
735
+ └─curve_generator
737
736
  ```
738
737
 
739
738
  ## Install
@@ -747,7 +746,7 @@ conda activate pmp
747
746
  To install the repository, please run the following command in shell.
748
747
 
749
748
  ```shell
750
- pip install python-motion-planning
749
+ pip install python-motion-planning==2.0.dev2
751
750
  ```
752
751
 
753
752
  ## Run
@@ -804,7 +803,7 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
804
803
  | **PID** |![pid_2d.gif](assets/pid_2d.gif)|Not implemented
805
804
  | **APF** |![apf_2d.gif](assets/apf_2d.gif)|Not implemented
806
805
  | **DWA** |![dwa_2d.gif](assets/dwa_2d.gif)|Not implemented
807
- | **RPP** |![rpp_2d.gif](assets/rpp_2d.gif)|Not implemented
806
+ | **RPP** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
808
807
  | **LQR** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
809
808
  | **MPC** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
810
809
  | **MPPI** |Not implemented|Not implemented
@@ -815,14 +814,17 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
815
814
 
816
815
  ## Curve Generator
817
816
 
817
+ The visualization of the curve generators has not been implemented in current version. They can be visualized in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1).
818
+
818
819
  |Generator|2D|3D|
819
820
  | ------- | -------------------------------------------------------- | --------------------------------------------------------
820
- | **Polynomia** | ![polynomial_2d.svg](assets/polynomial_2d.svg)|Not implemented
821
- | **Bezier** |![bezier_2d.svg](assets/bezier_2d.svg)|Not implemented
822
- | **Cubic Spline** |![cubic_spline_2d.svg](assets/cubic_spline_2d.svg)|Not implemented
823
- | **BSpline** |![bspline_2d.svg](assets/bspline_2d.svg)|Not implemented
824
- | **Dubins** |![dubins_2d.svg](assets/dubins_2d.svg)|Not implemented
825
- | **Reeds-Shepp** |![reeds_shepp_2d.svg](assets/reeds_shepp_2d.svg)|Not implemented
821
+ | **Polynomia** | ![polynomial_curve_python.gif](assets/polynomial_curve_python.gif)|Not implemented
822
+ | **Bezier** |![bezier_curve_python.png](assets/bezier_curve_python.png)|Not implemented
823
+ | **Cubic Spline** |![cubic_spline_python.png](assets/cubic_spline_python.png)|Not implemented
824
+ | **BSpline** |![bspline_curve_python.png](assets/bspline_curve_python.png)|Not implemented
825
+ | **Dubins** |![dubins_curve_python.png](assets/dubins_curve_python.png)|Not implemented
826
+ | **Reeds-Shepp** |![reeds_shepp_python.png](assets/reeds_shepp_python.gif)|Not implemented
827
+ | **Fem-Pos Smoother** |![fem_pos_smoother_python.png](assets/fem_pos_smoother_python.png)|Not implemented
826
828
 
827
829
  # Future Works
828
830
 
@@ -832,8 +834,6 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
832
834
 
833
835
  * Path planning on topological map.
834
836
 
835
- * Sample search with Dubins or Reeds-Shepp curves.
836
-
837
837
  * Application on ROS2.
838
838
 
839
839
  * Application in mainstream robot simulation environments (e.g. Gazebo, Carla, Airsim, PyBullet, MuJoCo, Issac Sim).
@@ -1,8 +1,6 @@
1
1
 
2
2
  # Introduction
3
3
 
4
- `Python Motion Planning` repository provides the implementations of common `Motion planning` algorithms, including path planners on N-D grid, controllers for path-tracking, curve generators, a visualizer based on matplotlib and a toy physical simulator to test controllers.
5
-
6
4
  `Motion planning` plans the state sequence of the robot without conflict between the start and goal.
7
5
 
8
6
  `Motion planning` mainly includes `Path planning` and `Trajectory planning`.
@@ -10,6 +8,8 @@
10
8
  * `Path Planning`: It's based on path constraints (such as obstacles), planning the optimal path sequence for the robot to travel without conflict between the start and goal.
11
9
  * `Trajectory planning`: It plans the motion state to approach the global path based on kinematics, dynamics constraints and path sequence.
12
10
 
11
+ This repository provides the implementations of common `Motion planning` algorithms, including path planners on N-D grid and controllers for path-tracking, a visualizer based on matplotlib and a toy physical simulator to test controllers.
12
+
13
13
  The theory analysis can be found at [motion-planning](https://blog.csdn.net/frigidwinter/category_11410243.html).
14
14
 
15
15
  We also provide [ROS C++](https://github.com/ai-winter/ros_motion_planning) version and [Matlab](https://github.com/ai-winter/matlab_motion_planning) version.
@@ -36,8 +36,7 @@ python_motion_planning
36
36
  | ├─graph_search
37
37
  | ├─sample_search
38
38
  | └─hybrid_search
39
- └─traj_optimizer
40
- | └─curve_generator
39
+ └─curve_generator
41
40
  ```
42
41
 
43
42
  ## Install
@@ -51,7 +50,7 @@ conda activate pmp
51
50
  To install the repository, please run the following command in shell.
52
51
 
53
52
  ```shell
54
- pip install python-motion-planning
53
+ pip install python-motion-planning==2.0.dev2
55
54
  ```
56
55
 
57
56
  ## Run
@@ -108,7 +107,7 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
108
107
  | **PID** |![pid_2d.gif](assets/pid_2d.gif)|Not implemented
109
108
  | **APF** |![apf_2d.gif](assets/apf_2d.gif)|Not implemented
110
109
  | **DWA** |![dwa_2d.gif](assets/dwa_2d.gif)|Not implemented
111
- | **RPP** |![rpp_2d.gif](assets/rpp_2d.gif)|Not implemented
110
+ | **RPP** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
112
111
  | **LQR** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
113
112
  | **MPC** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
114
113
  | **MPPI** |Not implemented|Not implemented
@@ -119,14 +118,17 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
119
118
 
120
119
  ## Curve Generator
121
120
 
121
+ The visualization of the curve generators has not been implemented in current version. They can be visualized in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1).
122
+
122
123
  |Generator|2D|3D|
123
124
  | ------- | -------------------------------------------------------- | --------------------------------------------------------
124
- | **Polynomia** | ![polynomial_2d.svg](assets/polynomial_2d.svg)|Not implemented
125
- | **Bezier** |![bezier_2d.svg](assets/bezier_2d.svg)|Not implemented
126
- | **Cubic Spline** |![cubic_spline_2d.svg](assets/cubic_spline_2d.svg)|Not implemented
127
- | **BSpline** |![bspline_2d.svg](assets/bspline_2d.svg)|Not implemented
128
- | **Dubins** |![dubins_2d.svg](assets/dubins_2d.svg)|Not implemented
129
- | **Reeds-Shepp** |![reeds_shepp_2d.svg](assets/reeds_shepp_2d.svg)|Not implemented
125
+ | **Polynomia** | ![polynomial_curve_python.gif](assets/polynomial_curve_python.gif)|Not implemented
126
+ | **Bezier** |![bezier_curve_python.png](assets/bezier_curve_python.png)|Not implemented
127
+ | **Cubic Spline** |![cubic_spline_python.png](assets/cubic_spline_python.png)|Not implemented
128
+ | **BSpline** |![bspline_curve_python.png](assets/bspline_curve_python.png)|Not implemented
129
+ | **Dubins** |![dubins_curve_python.png](assets/dubins_curve_python.png)|Not implemented
130
+ | **Reeds-Shepp** |![reeds_shepp_python.png](assets/reeds_shepp_python.gif)|Not implemented
131
+ | **Fem-Pos Smoother** |![fem_pos_smoother_python.png](assets/fem_pos_smoother_python.png)|Not implemented
130
132
 
131
133
  # Future Works
132
134
 
@@ -136,8 +138,6 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
136
138
 
137
139
  * Path planning on topological map.
138
140
 
139
- * Sample search with Dubins or Reeds-Shepp curves.
140
-
141
141
  * Application on ROS2.
142
142
 
143
143
  * Application in mainstream robot simulation environments (e.g. Gazebo, Carla, Airsim, PyBullet, MuJoCo, Issac Sim).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-motion-planning"
7
- version = "2.0"
7
+ version = "2.0.dev2"
8
8
  description = "Motion planning algorithms for Python"
9
9
  maintainers = [
10
10
  {name = "Wu Maojia", email = "omige@mail.nwpu.edu.cn"},
@@ -1,4 +1,4 @@
1
1
  from .common import *
2
2
  from .path_planner import *
3
3
  from .controller import *
4
- from .traj_optimizer import *
4
+ from .curve_generator import *
@@ -35,31 +35,42 @@ class Geometry:
35
35
  else:
36
36
  raise ValueError("Invalid distance type")
37
37
 
38
- @staticmethod
39
- def mod_to_2pi(orient: np.ndarray) -> np.ndarray:
40
- """
41
- Regularize orientation to be within [0, 2*pi)
38
+ # @staticmethod
39
+ # def angle(v1: tuple, v2: tuple) -> float:
40
+ # """
41
+ # Calculate the angle between two vectors
42
42
 
43
- Args:
44
- orient: the orientation angle
43
+ # Args:
44
+ # v1: First vector
45
+ # v2: Second vector
45
46
 
46
- Returns:
47
- new_orient: modded orientation
48
- """
49
- return np.mod(orient, 2 * np.pi)
47
+ # Returns:
48
+ # angle_rad: Angle in rad between the two vectors
49
+ # """
50
+ # if len(v1) != len(v2):
51
+ # raise ValueError("Dimension mismatch")
52
+
53
+ # dot_product = sum(a * b for a, b in zip(v1, v2))
54
+ # v1_norm = math.sqrt(sum(a**2 for a in v1))
55
+ # v2_norm = math.sqrt(sum(b**2 for b in v2))
56
+
57
+ # if v1_norm == 0 or v2_norm == 0:
58
+ # raise ValueError("Zero vector cannot calculate angle")
59
+
60
+ # cos_theta = dot_product / (v1_norm * v2_norm)
61
+
62
+ # cos_theta = min(1.0, max(-1.0, cos_theta))
63
+
64
+ # angle_rad = math.acos(cos_theta)
65
+
66
+ # return angle_rad
50
67
 
51
68
  @staticmethod
52
69
  def regularize_orient(orient: np.ndarray) -> np.ndarray:
53
70
  """
54
71
  Regularize orientation to be within (-pi, pi]
55
-
56
- Args:
57
- orient: the orientation angle
58
-
59
- Returns:
60
- new_orient: regularized orientation
61
72
  """
62
- return -np.mod(-orient + np.pi, 2 * np.pi) + np.pi
73
+ return np.mod(orient + np.pi, 2 * np.pi) - np.pi
63
74
 
64
75
  @staticmethod
65
76
  def add_orient_to_2d_path(path: List[Tuple[float, float]]) -> List[Tuple[float, float, float]]:
@@ -91,4 +102,4 @@ class Geometry:
91
102
  last_x, last_y = path[-1]
92
103
  path_with_orient.append((last_x, last_y, path_with_orient[-1][2]))
93
104
 
94
- return path_with_orient
105
+ return path_with_orient
@@ -0,0 +1,9 @@
1
+ from .polynomial_curve import Polynomial
2
+ from .bezier_curve import Bezier
3
+ from .bspline_curve import BSpline
4
+ from .dubins_curve import Dubins
5
+ from .reeds_shepp import ReedsShepp
6
+ from .cubic_spline import CubicSpline
7
+ from .fem_pos_smooth import FemPosSmoother
8
+
9
+ __all__ = ["Polynomial", "Dubins", "ReedsShepp", "Bezier", "CubicSpline", "BSpline", "FemPosSmoother"]
@@ -0,0 +1,131 @@
1
+ """
2
+ @file: bezier_curve.py
3
+ @breif: Bezier curve generation
4
+ @author: Winter
5
+ @update: 2023.7.25
6
+ """
7
+ import numpy as np
8
+
9
+ from scipy.special import comb
10
+ # from python_motion_planning.utils import Plot
11
+ from .curve import Curve
12
+
13
+ class Bezier(Curve):
14
+ """
15
+ Class for Bezier curve generation.
16
+
17
+ Parameters:
18
+ step (float): Simulation or interpolation size
19
+ offset (float): The offset of control points
20
+
21
+ Examples:
22
+ >>> from python_motion_planning.curve_generation import Bezier
23
+ >>> points = [(0, 0, 0), (10, 10, -90), (20, 5, 60)]
24
+ >>> generator = Bezier(step, offset)
25
+ >>> generator.run(points)
26
+ """
27
+ def __init__(self, step: float, offset: float) -> None:
28
+ super().__init__(step)
29
+ self.offset = offset
30
+
31
+ def __str__(self) -> str:
32
+ return "Bezier Curve"
33
+
34
+ def generation(self, start_pose: tuple, goal_pose: tuple):
35
+ """
36
+ Generate the Bezier Curve.
37
+
38
+ Parameters:
39
+ start_pose (tuple): Initial pose (x, y, yaw)
40
+ goal_pose (tuple): Target pose (x, y, yaw)
41
+
42
+ Returns:
43
+ x_list (list): x of the trajectory
44
+ y_list (list): y of the trajectory
45
+ yaw_list (list): yaw of the trajectory
46
+ """
47
+ sx, sy, _ = start_pose
48
+ gx, gy, _ = goal_pose
49
+ n_points = int(np.hypot(sx - gx, sy - gy) / self.step)
50
+ control_points = self.getControlPoints(start_pose, goal_pose)
51
+
52
+ return [self.bezier(t, control_points) for t in np.linspace(0, 1, n_points)], \
53
+ control_points
54
+
55
+ def bezier(self, t: float, control_points: list) ->np.ndarray:
56
+ """
57
+ Calculate the Bezier curve point.
58
+
59
+ Parameters:
60
+ t (float): scale factor
61
+ control_points (list[tuple]): control points
62
+
63
+ Returns:
64
+ point (np.array): point in Bezier curve with t
65
+ """
66
+ n = len(control_points) - 1
67
+ control_points = np.array(control_points)
68
+ return np.sum([comb(n, i) * t ** i * (1 - t) ** (n - i) *
69
+ control_points[i] for i in range(n + 1)], axis=0)
70
+
71
+ def getControlPoints(self, start_pose: tuple, goal_pose: tuple):
72
+ """
73
+ Calculate control points heuristically.
74
+
75
+ Parameters:
76
+ start_pose (tuple): Initial pose (x, y, yaw)
77
+ goal_pose (tuple): Target pose (x, y, yaw)
78
+
79
+ Returns:
80
+ control_points (list[tuple]): Control points
81
+ """
82
+ sx, sy, syaw = start_pose
83
+ gx, gy, gyaw = goal_pose
84
+
85
+ dist = np.hypot(sx - gx, sy - gy) / self.offset
86
+ return [(sx, sy),
87
+ (sx + dist * np.cos(syaw), sy + dist * np.sin(syaw)),
88
+ (gx - dist * np.cos(gyaw), gy - dist * np.sin(gyaw)),
89
+ (gx, gy)]
90
+
91
+ # def run(self, points: list):
92
+ # """
93
+ # Running both generation and animation.
94
+
95
+ # Parameters:
96
+ # points (list[tuple]): path points
97
+ # """
98
+ # assert len(points) >= 2, "Number of points should be at least 2."
99
+ # import matplotlib.pyplot as plt
100
+
101
+ # # generation
102
+ # path_x, path_y = [], []
103
+ # path_control_x, path_control_y = [], []
104
+ # for i in range(len(points) - 1):
105
+ # path, control_points = self.generation(
106
+ # (points[i][0], points[i][1], np.deg2rad(points[i][2])),
107
+ # (points[i + 1][0], points[i + 1][1], np.deg2rad(points[i + 1][2])))
108
+
109
+ # for pt in path:
110
+ # path_x.append(pt[0])
111
+ # path_y.append(pt[1])
112
+
113
+ # path_control_x.append(points[i][0])
114
+ # path_control_y.append(points[i][1])
115
+
116
+ # for pt in control_points:
117
+ # path_control_x.append(pt[0])
118
+ # path_control_y.append(pt[1])
119
+
120
+ # # animation
121
+ # plt.figure("curve generation")
122
+ # plt.plot(path_x, path_y, linewidth=2, c="#1f77b4")
123
+ # plt.plot(path_control_x, path_control_y, '--o', c='#dddddd', label="Control Points")
124
+ # for x, y, theta in points:
125
+ # Plot.plotArrow(x, y, np.deg2rad(theta), 2, 'blueviolet')
126
+
127
+ # plt.axis("equal")
128
+ # plt.legend()
129
+ # plt.title(str(self))
130
+ # plt.show()
131
+
@@ -0,0 +1,271 @@
1
+ """
2
+ @file: bspline_curve.py
3
+ @breif: B-Spline curve generation
4
+ @author: Winter
5
+ @update: 2023.7.29
6
+ """
7
+ import math
8
+ import numpy as np
9
+
10
+ from .curve import Curve
11
+
12
+ class BSpline(Curve):
13
+ """
14
+ Class for B-Spline curve generation.
15
+
16
+ Parameters:
17
+ step (float): Simulation or interpolation size
18
+ k (int): Degree of curve
19
+
20
+ Examples:
21
+ >>> from python_motion_planning.curve_generation import BSpline
22
+ >>> points = [(0, 0, 0), (10, 10, -90), (20, 5, 60)]
23
+ >>> generator = BSpline(step, k)
24
+ >>> generator.run(points)
25
+ """
26
+ def __init__(self, step: float, k: int, param_mode: str="centripetal",
27
+ spline_mode: str="interpolation") -> None:
28
+ super().__init__(step)
29
+ self.k = k
30
+
31
+ assert param_mode == "centripetal" or param_mode == "chord_length" \
32
+ or param_mode == "uniform_spaced", "Parameter selection mode error!"
33
+ self.param_mode = param_mode
34
+
35
+ assert spline_mode == "interpolation" or spline_mode == "approximation", \
36
+ "Spline mode selection error!"
37
+ self.spline_mode = spline_mode
38
+
39
+ def __str__(self) -> str:
40
+ return "B-Spline Curve"
41
+
42
+ def baseFunction(self, i: int, k: int, t: float, knot: list):
43
+ """
44
+ Calculate base function using Cox-deBoor function.
45
+
46
+ Parameters:
47
+ i (int): The index of base function
48
+ k (int): The degree of curve
49
+ t (float): parameter
50
+ knot (list[float]): knot vector
51
+
52
+ Returns:
53
+ Nik_t (float): The value of base function Nik(t)
54
+ """
55
+ Nik_t = 0
56
+ if k == 0:
57
+ Nik_t = 1.0 if t >= knot[i] and t < knot[i + 1] else 0.0
58
+ else:
59
+ length1 = knot[i + k] - knot[i]
60
+ length2 = knot[i + k + 1] - knot[i + 1]
61
+ if not length1 and not length2:
62
+ Nik_t = 0
63
+ elif not length1:
64
+ Nik_t = (knot[i + k + 1] - t) / length2 * self.baseFunction(i + 1, k - 1, t, knot)
65
+ elif not length2:
66
+ Nik_t = (t - knot[i]) / length1 * self.baseFunction(i, k - 1, t, knot)
67
+ else:
68
+ Nik_t = (t - knot[i]) / length1 * self.baseFunction(i, k - 1, t, knot) + \
69
+ (knot[i + k + 1] - t) / length2 * self.baseFunction(i + 1, k - 1, t, knot)
70
+ return Nik_t
71
+
72
+ def paramSelection(self, points: list):
73
+ """
74
+ Calculate parameters using the `uniform spaced` or `chrod length`
75
+ or `centripetal` method.
76
+
77
+ Parameters:
78
+ points (list[tuple]): path points
79
+
80
+ Returns:
81
+ Parameters (list[float]): The parameters of given points
82
+ """
83
+ n = len(points)
84
+ x_list = [pt[0] for pt in points]
85
+ y_list = [pt[1] for pt in points]
86
+ dx, dy = np.diff(x_list), np.diff(y_list)
87
+
88
+ if self.param_mode == "uniform_spaced":
89
+ return np.linspace(0, 1, n).tolist()
90
+
91
+ elif self.param_mode == "chord_length":
92
+ parameters = np.zeros(n)
93
+ s = np.cumsum([math.hypot(idx, idy) for (idx, idy) in zip(dx, dy)])
94
+ for i in range(1, n):
95
+ parameters[i] = s[i - 1] / s[-1]
96
+ return parameters.tolist()
97
+
98
+ elif self.param_mode == "centripetal":
99
+ alpha = 0.5
100
+ s = np.cumsum([math.pow(math.hypot(idx, idy), alpha) for (idx, idy) in zip(dx, dy)])
101
+ parameters = np.zeros(n)
102
+ for i in range(1, n):
103
+ parameters[i] = s[i - 1] / s[-1]
104
+ return parameters.tolist()
105
+
106
+ def knotGeneration(self, param: list, n: int):
107
+ """
108
+ Generate knot vector.
109
+
110
+ Parameters:
111
+ param (list[float]): The parameters of given points
112
+ n (int): The number of data points
113
+
114
+ Returns:
115
+ knot (list[float]): The knot vector
116
+ """
117
+ m = n + self.k + 1
118
+ knot = np.zeros(m)
119
+ for i in range(self.k + 1):
120
+ knot[i] = 0
121
+ for i in range(n, m):
122
+ knot[i] = 1
123
+ for i in range(self.k + 1, n):
124
+ for j in range(i - self.k, i):
125
+ knot[i] = knot[i] + param[j]
126
+ knot[i] = knot[i] / self.k
127
+ return knot.tolist()
128
+
129
+ def interpolation(self, points: list, param: list, knot: list):
130
+ """
131
+ Given a set of N data points, D0, D1, ..., Dn and a degree k,
132
+ find a B-spline curve of degree k defined by N control points
133
+ that passes all data points in the given order.
134
+
135
+ Parameters:
136
+ points (list[tuple]): path points
137
+ param (list[float]): The parameters of given points
138
+ knot (list[float]): The knot vector
139
+
140
+ Returns:
141
+ control_points (np.ndarray): The control points
142
+ """
143
+ n = len(points)
144
+ N = np.zeros((n, n))
145
+
146
+ for i in range(n):
147
+ for j in range(n):
148
+ N[i][j] = self.baseFunction(j, self.k, param[i], knot)
149
+ N[n-1][n-1] = 1
150
+ N_inv = np.linalg.inv(N)
151
+
152
+ D = np.array(points)
153
+
154
+ return N_inv @ D
155
+
156
+ def approximation(self, points: list, param: list, knot: list):
157
+ """
158
+ Given a set of N data points, D0, D1, ..., Dn, a degree k,
159
+ and a number H, where N > H > k >= 1, find a B-spline curve
160
+ of degree k defined by H control points that satisfies the
161
+ following conditions:
162
+ 1. this curve contains the first and last data points;
163
+ 2. this curve approximates the data polygon in the sense
164
+ of least square
165
+
166
+ Parameters:
167
+ points (list[tuple]): path points
168
+ param (list[float]): The parameters of given points
169
+ knot (list[float]): The knot vector
170
+
171
+ Returns:
172
+ control_points (np.ndarray): The control points
173
+ """
174
+ n = len(points)
175
+ D = np.array(points)
176
+
177
+ # heuristically setting the number of control points
178
+ h = n - 1
179
+
180
+ N = np.zeros((n, h))
181
+ for i in range(n):
182
+ for j in range(h):
183
+ N[i][j] = self.baseFunction(j, self.k, param[i], knot)
184
+ N_ = N[1 : n - 1, 1 : h - 1]
185
+
186
+ qk = np.zeros((n - 2, 2))
187
+ for i in range(1, n - 1):
188
+ qk[i - 1] = D[i, :] - N[i][0] * D[0, :] - N[i][h - 1] * D[-1, :]
189
+ Q = N_.T @ qk
190
+
191
+ P = np.linalg.inv(N_.T @ N_) @ Q
192
+ P = np.insert(P, 0, D[0, :], axis=0)
193
+ P = np.insert(P, len(P), D[-1, :], axis=0)
194
+
195
+ return P
196
+
197
+ def generation(self, t, k, knot, control_pts):
198
+ """
199
+ Generate the B-spline curve.
200
+
201
+ Parameters:
202
+ t (np.ndarray): The parameter values
203
+ k (int): The degree of the B-spline curve
204
+ knot (list[float]): The knot vector
205
+ control_pts (np.ndarray): The control points
206
+
207
+ Returns:
208
+ curve (np.ndarray): The B-spline curve
209
+ """
210
+ N = np.zeros((len(t), len(control_pts)))
211
+
212
+ for i in range(len(t)):
213
+ for j in range(len(control_pts)):
214
+ N[i][j] = self.baseFunction(j, k, t[i], knot)
215
+ N[len(t) - 1][len(control_pts) - 1] = 1
216
+
217
+ return N @ control_pts
218
+
219
+ # def run(self, points: list, display: bool = True):
220
+ # """
221
+ # Running both generation and animation.
222
+
223
+ # Parameters:
224
+ # points (list[tuple]): path points
225
+ # """
226
+ # assert len(points) >= 2, "Number of points should be at least 2."
227
+ # import matplotlib.pyplot as plt
228
+
229
+ # if len(points[0]) > 2:
230
+ # points = [(points[i][0], points[i][1]) for i in range(len(points))]
231
+
232
+ # t = np.linspace(0, 1, int(1 / self.step))
233
+ # params = self.paramSelection(points)
234
+ # knot = self.knotGeneration(params, len(points))
235
+
236
+ # if self.spline_mode == "interpolation":
237
+ # control_pts = self.interpolation(points, params, knot)
238
+ # elif self.spline_mode == "approximation":
239
+ # control_pts = self.approximation(points, params, knot)
240
+ # h = len(control_pts)
241
+ # new_points = [(control_pts[i][0], control_pts[i][1])
242
+ # for i in range(h)]
243
+ # params = self.paramSelection(new_points)
244
+ # knot = self.knotGeneration(params, h)
245
+ # else:
246
+ # raise NotImplementedError
247
+
248
+ # control_x = control_pts[:, 0].tolist()
249
+ # control_y = control_pts[:, 1].tolist()
250
+
251
+ # path = self.generation(t, self.k, knot, control_pts)
252
+ # path_x = path[:, 0].tolist()
253
+ # path_y = path[:, 1].tolist()
254
+
255
+ # if display:
256
+ # # animation
257
+ # plt.figure("curve generation")
258
+
259
+ # # static
260
+ # plt.figure("curve generation")
261
+ # plt.plot(path_x, path_y, linewidth=2, c="#1f77b4")
262
+ # plt.plot(control_x, control_y, '--o', c='#dddddd', label="Control Points")
263
+ # for x, y in points:
264
+ # plt.plot(x, y, "xr", linewidth=2)
265
+ # plt.axis("equal")
266
+ # plt.legend()
267
+ # plt.title(str(self))
268
+
269
+ # plt.show()
270
+
271
+ # return [(ix, iy) for (ix, iy) in zip(path_x, path_y)]