python-motion-planning 2.0.dev2__py3-none-any.whl → 2.0.1__py3-none-any.whl

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 (31) hide show
  1. python_motion_planning/__init__.py +1 -1
  2. python_motion_planning/common/env/map/grid.py +394 -129
  3. python_motion_planning/common/utils/geometry.py +18 -29
  4. python_motion_planning/path_planner/sample_search/rrt.py +5 -5
  5. python_motion_planning/path_planner/sample_search/rrt_connect.py +2 -2
  6. python_motion_planning/path_planner/sample_search/rrt_star.py +31 -11
  7. python_motion_planning/traj_optimizer/__init__.py +2 -0
  8. python_motion_planning/traj_optimizer/base_curve_generator.py +53 -0
  9. python_motion_planning/traj_optimizer/curve_generator/__init__.py +2 -0
  10. python_motion_planning/traj_optimizer/curve_generator/point_based/__init__.py +2 -0
  11. python_motion_planning/traj_optimizer/curve_generator/point_based/bspline.py +256 -0
  12. python_motion_planning/traj_optimizer/curve_generator/point_based/cubic_spline.py +115 -0
  13. python_motion_planning/traj_optimizer/curve_generator/pose_based/__init__.py +4 -0
  14. python_motion_planning/traj_optimizer/curve_generator/pose_based/bezier.py +121 -0
  15. python_motion_planning/traj_optimizer/curve_generator/pose_based/dubins.py +355 -0
  16. python_motion_planning/traj_optimizer/curve_generator/pose_based/polynomial.py +197 -0
  17. python_motion_planning/traj_optimizer/curve_generator/pose_based/reeds_shepp.py +606 -0
  18. {python_motion_planning-2.0.dev2.dist-info → python_motion_planning-2.0.1.dist-info}/METADATA +22 -15
  19. {python_motion_planning-2.0.dev2.dist-info → python_motion_planning-2.0.1.dist-info}/RECORD +22 -20
  20. {python_motion_planning-2.0.dev2.dist-info → python_motion_planning-2.0.1.dist-info}/WHEEL +1 -1
  21. python_motion_planning/curve_generator/__init__.py +0 -9
  22. python_motion_planning/curve_generator/bezier_curve.py +0 -131
  23. python_motion_planning/curve_generator/bspline_curve.py +0 -271
  24. python_motion_planning/curve_generator/cubic_spline.py +0 -128
  25. python_motion_planning/curve_generator/curve.py +0 -64
  26. python_motion_planning/curve_generator/dubins_curve.py +0 -348
  27. python_motion_planning/curve_generator/fem_pos_smooth.py +0 -114
  28. python_motion_planning/curve_generator/polynomial_curve.py +0 -226
  29. python_motion_planning/curve_generator/reeds_shepp.py +0 -736
  30. {python_motion_planning-2.0.dev2.dist-info → python_motion_planning-2.0.1.dist-info}/licenses/LICENSE +0 -0
  31. {python_motion_planning-2.0.dev2.dist-info → python_motion_planning-2.0.1.dist-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.dev2
3
+ Version: 2.0.1
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
@@ -685,6 +685,7 @@ Requires-Python: >=3.6
685
685
  Description-Content-Type: text/markdown
686
686
  License-File: LICENSE
687
687
  Requires-Dist: numpy
688
+ Requires-Dist: numba
688
689
  Requires-Dist: scipy
689
690
  Requires-Dist: matplotlib
690
691
  Requires-Dist: osqp
@@ -697,6 +698,8 @@ Dynamic: license-file
697
698
 
698
699
  # Introduction
699
700
 
701
+ `Python Motion Planning` repository provides the implementations of common `Motion planning` algorithms, including path planners on N-D grid, controllers for path-tracking, trajectory optimizers, a visualizer based on matplotlib and a toy physical simulator to test controllers.
702
+
700
703
  `Motion planning` plans the state sequence of the robot without conflict between the start and goal.
701
704
 
702
705
  `Motion planning` mainly includes `Path planning` and `Trajectory planning`.
@@ -704,8 +707,6 @@ Dynamic: license-file
704
707
  * `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.
705
708
  * `Trajectory planning`: It plans the motion state to approach the global path based on kinematics, dynamics constraints and path sequence.
706
709
 
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
710
  The theory analysis can be found at [motion-planning](https://blog.csdn.net/frigidwinter/category_11410243.html).
710
711
 
711
712
  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,7 +733,8 @@ python_motion_planning
732
733
  | ├─graph_search
733
734
  | ├─sample_search
734
735
  | └─hybrid_search
735
- └─curve_generator
736
+ └─traj_optimizer
737
+ └─curve_generator
736
738
  ```
737
739
 
738
740
  ## Install
@@ -746,7 +748,7 @@ conda activate pmp
746
748
  To install the repository, please run the following command in shell.
747
749
 
748
750
  ```shell
749
- pip install python-motion-planning==2.0.dev2
751
+ pip install python-motion-planning
750
752
  ```
751
753
 
752
754
  ## Run
@@ -803,7 +805,7 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
803
805
  | **PID** |![pid_2d.gif](assets/pid_2d.gif)|Not implemented
804
806
  | **APF** |![apf_2d.gif](assets/apf_2d.gif)|Not implemented
805
807
  | **DWA** |![dwa_2d.gif](assets/dwa_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
+ | **RPP** |![rpp_2d.gif](assets/rpp_2d.gif)|Not implemented
807
809
  | **LQR** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
808
810
  | **MPC** |Implemented in [V1.1.1](https://github.com/ai-winter/python_motion_planning/tree/v1.1.1), not migrated|Not implemented
809
811
  | **MPPI** |Not implemented|Not implemented
@@ -812,19 +814,22 @@ In the following demos, the blue robot 1 is the `CircularRobot`, and the orange
812
814
  | **DQN** |Not implemented|Not implemented
813
815
  | **DDPG** |Implemented in [V1.0](https://github.com/ai-winter/python_motion_planning/tree/v1.0), not migrated|Not implemented
814
816
 
815
- ## Curve Generator
817
+ ## Trajectory Optimizer
818
+ ### Curve Generator
819
+ #### Point-based
816
820
 
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).
821
+ |Generator|2D|3D|
822
+ | ------- | -------------------------------------------------------- | --------------------------------------------------------
823
+ | **Cubic Spline** |![cubic_spline_2d.svg](assets/cubic_spline_2d.svg)|Not implemented
824
+ | **BSpline** |![bspline_2d.svg](assets/bspline_2d.svg)|Not implemented
818
825
 
826
+ #### Pose-based
819
827
  |Generator|2D|3D|
820
828
  | ------- | -------------------------------------------------------- | --------------------------------------------------------
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
829
+ | **Polynomia** | ![polynomial_2d.svg](assets/polynomial_2d.svg)|Not implemented
830
+ | **Bezier** |![bezier_2d.svg](assets/bezier_2d.svg)|Not implemented
831
+ | **Dubins** |![dubins_2d.svg](assets/dubins_2d.svg)|Not implemented
832
+ | **Reeds-Shepp** |![reeds_shepp_2d.svg](assets/reeds_shepp_2d.svg)|Not implemented
828
833
 
829
834
  # Future Works
830
835
 
@@ -834,6 +839,8 @@ The visualization of the curve generators has not been implemented in current ve
834
839
 
835
840
  * Path planning on topological map.
836
841
 
842
+ * Sample search with Dubins or Reeds-Shepp curves.
843
+
837
844
  * Application on ROS2.
838
845
 
839
846
  * Application in mainstream robot simulation environments (e.g. Gazebo, Carla, Airsim, PyBullet, MuJoCo, Issac Sim).
@@ -1,11 +1,11 @@
1
- python_motion_planning/__init__.py,sha256=xE1YRraUctbm14jTr4vEkHepRQMsm_gatKRTjDwTGi8,109
1
+ python_motion_planning/__init__.py,sha256=qsRVlO3n-WSdeyH6NvduCQJ_G0Yqrml7F_juvs2UnJ4,108
2
2
  python_motion_planning/common/__init__.py,sha256=9CeruPgGOBOtro9EafPEhK5VKTav2OWeNbMLJCBwuNg,67
3
3
  python_motion_planning/common/env/__init__.py,sha256=Q8qIUcn5fvtLrmrc3SXStQoEwwrNMF-IofKotFermBk,129
4
4
  python_motion_planning/common/env/node.py,sha256=6I10JpU4tjK4aZEMWN7Dttz41QKskNFoe7gBR4aSyII,2727
5
5
  python_motion_planning/common/env/types.py,sha256=h5HtPrffu5qH_F1G4V1g8eXBPTPuDW-nFFfEFECVGYo,380
6
6
  python_motion_planning/common/env/map/__init__.py,sha256=5bVsJd2mrghKMj7erXfgc8V4NahXHe6zXngG9fMCjo0,44
7
7
  python_motion_planning/common/env/map/base_map.py,sha256=tX-9iO3RwbdvhGUHDtPNQUj8h-HNONjopXCLyUdtfQE,3321
8
- python_motion_planning/common/env/map/grid.py,sha256=pDQJyH5pGhRzhpk-a0j6N-EiveD35uqxHBIkjA3tdPU,20060
8
+ python_motion_planning/common/env/map/grid.py,sha256=-QDhKpKrjE4Hi-NZPWIgPiiZagJCZH_dw8QgpHgLor4,28441
9
9
  python_motion_planning/common/env/robot/__init__.py,sha256=njq1_k2uWikGH2AjtxoFDdmxqsM1YY5B9nVtIheyx6Y,122
10
10
  python_motion_planning/common/env/robot/base_robot.py,sha256=KEajU9iFCnrzDOFp3Vm3SMWJWQgGJAYLT4VB6IMX2Is,7913
11
11
  python_motion_planning/common/env/robot/circular_robot.py,sha256=6SS3XP91WfQlccxbtyVLjmPQjgesP9cFaxXg6txkxVI,1512
@@ -16,7 +16,7 @@ python_motion_planning/common/env/world/toy_simulator.py,sha256=J2JrZhQD-lCd4TB2
16
16
  python_motion_planning/common/utils/__init__.py,sha256=wYzKTiyKgYfl5cTO0pUHF1zkr8Q9VhhEwKcRy1xSSdM,114
17
17
  python_motion_planning/common/utils/child_tree.py,sha256=f6ypaZ-d7mJpWOaVH99KriJuzjDc6q353USsO7D5F9g,625
18
18
  python_motion_planning/common/utils/frame_transformer.py,sha256=D9xaOUcxCPLvTl9oJHRSuhue84i88nMiuI-3ns0i7Ao,7609
19
- python_motion_planning/common/utils/geometry.py,sha256=C-y_K2ZVixytqdsCYezH2FD-pyaZzoIVBQPmwIbWZJU,3149
19
+ python_motion_planning/common/utils/geometry.py,sha256=FFYM_eVAgJ3wA7H8MRXNvwXliGd6dKo4WU8fzbwdCXE,2693
20
20
  python_motion_planning/common/visualizer/__init__.py,sha256=HWWbLehtqEl0q_hEO28tEMDH-v8lXqduN-EJ7mo9LEI,90
21
21
  python_motion_planning/common/visualizer/base_visualizer.py,sha256=sjkH8lbyW8q9BVIEaQBTF10M27d73cpQqdTAPbEBFD0,5518
22
22
  python_motion_planning/common/visualizer/visualizer_2d.py,sha256=mqaKFZEtNHOCm82I1nCbCOhDP444JSySq1BzQCnPyEM,15656
@@ -31,15 +31,6 @@ python_motion_planning/controller/path_tracker/path_tracker.py,sha256=5p_MhqRWpM
31
31
  python_motion_planning/controller/path_tracker/pid.py,sha256=pqZggmTWaNd7XrlqfaK4wtBk9syg8PnIC7vOEnfN9S8,2403
32
32
  python_motion_planning/controller/path_tracker/pure_pursuit.py,sha256=gsfiMXZx3RwHIwmI2CSu4fTZNFKbZP31cXMgKUdDjs8,2405
33
33
  python_motion_planning/controller/path_tracker/rpp.py,sha256=e7qRIaUfeiVfVoiY5k797Yk9RK-Q7gnegmaOB7_BVP4,4181
34
- python_motion_planning/curve_generator/__init__.py,sha256=6eeN0NBlAndBhjk-ol3Yaa-0om2lNG7n43BASRfeV9k,370
35
- python_motion_planning/curve_generator/bezier_curve.py,sha256=E0J4bBxVaYZCRViKG4kEcZn9Scua0AJlrh-_RiycpSw,3705
36
- python_motion_planning/curve_generator/bspline_curve.py,sha256=bUDIOcCYgKgfznMwEL_TQQ82sTUlB_sOFZhi3hAw0FQ,9418
37
- python_motion_planning/curve_generator/cubic_spline.py,sha256=S5p3uNWDTgHR6JqLEMDEnr9A3A0KjyqH0aNBCQVmVFw,3452
38
- python_motion_planning/curve_generator/curve.py,sha256=xf7G5lDGTCVUBoSK8Oa14fmdf_AANOZVqdSmAKlwu-A,1543
39
- python_motion_planning/curve_generator/dubins_curve.py,sha256=EPKF7gRZT-Omc88RWmrDfQzGBzFZzxqzmdlemMBfnLM,11041
40
- python_motion_planning/curve_generator/fem_pos_smooth.py,sha256=8K2OI6YBP40T9zXp6uXdQ8dggLqHdsR9VXoqP_-hawk,3512
41
- python_motion_planning/curve_generator/polynomial_curve.py,sha256=h247Zk23ae-n3lQqZuWBp-rNs7eDBNJSD_hGtQmr69s,7602
42
- python_motion_planning/curve_generator/reeds_shepp.py,sha256=_-0_fo85vwmQVfBvsZ3-MzK96gAzzKn-kSwwskW8JIk,21511
43
34
  python_motion_planning/path_planner/__init__.py,sha256=Y0Im0cJ3iuUOYJyAOYvA_IavaNTNowb7SE6atrdJqX0,121
44
35
  python_motion_planning/path_planner/base_path_planner.py,sha256=YZcLqAIkLJtp5MWoT5zPmzxv05xUlnDpfuzN-CgPQuc,3640
45
36
  python_motion_planning/path_planner/graph_search/__init__.py,sha256=ugZpHV12dY-yb8d1jx4NepdRzQKn2qNKS6yWEBlvWy0,146
@@ -52,11 +43,22 @@ python_motion_planning/path_planner/graph_search/theta_star.py,sha256=JxxWukRTI4
52
43
  python_motion_planning/path_planner/hybrid_search/__init__.py,sha256=RCvNhSq6nskZPCc7jo9Y5MOzrD4f7TL9RfVUCHgpeq4,30
53
44
  python_motion_planning/path_planner/hybrid_search/voronoi_planner.py,sha256=sDTE-IFMf2035mUIRulEIOF0NiZSrwhW_bWrCiPetu4,7897
54
45
  python_motion_planning/path_planner/sample_search/__init__.py,sha256=RYz6o_xmdsoErMGdBKvXEK4w-48P_ogi1bJsdJmUupk,71
55
- python_motion_planning/path_planner/sample_search/rrt.py,sha256=adag-et3pyn-SuGyOimjroXfOyuJiT3Yhrr_HEIhJic,8649
56
- python_motion_planning/path_planner/sample_search/rrt_connect.py,sha256=KZewgIWiecQMy5EmSkdXb2KBjv8HA9NwF-6K8-Snck4,9666
57
- python_motion_planning/path_planner/sample_search/rrt_star.py,sha256=0cHLXbz3PuZbHXguAJny7si7id7EfXYAYZcSLg52zcE,10030
58
- python_motion_planning-2.0.dev2.dist-info/licenses/LICENSE,sha256=a4N8el8H0UrdAJzCeVgj9HklpT3VkZfsy4aL1SAifJE,35793
59
- python_motion_planning-2.0.dev2.dist-info/METADATA,sha256=P2njUua7bkdTT08yDVrWEIkf87sTUsIJQLpucancBE0,49711
60
- python_motion_planning-2.0.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
61
- python_motion_planning-2.0.dev2.dist-info/top_level.txt,sha256=VtZTYZios8VncYIkec7tOVdYqj5oMRmoeBb9RcJHluY,23
62
- python_motion_planning-2.0.dev2.dist-info/RECORD,,
46
+ python_motion_planning/path_planner/sample_search/rrt.py,sha256=hFBN1RaAnBn_ap7V2IPdkkKJIaMEIc7bHGALxoMkV-I,8682
47
+ python_motion_planning/path_planner/sample_search/rrt_connect.py,sha256=2GYQS5InB-jWr74c_dDGnLLCkIIeLnIrJmgfBfNNtOw,9670
48
+ python_motion_planning/path_planner/sample_search/rrt_star.py,sha256=f32G0h3_ds0cWvukNDRtDUoLZy0_KYpALcqCQcTxP1w,11223
49
+ python_motion_planning/traj_optimizer/__init__.py,sha256=0HeRril2pkNw1uUdro2HuV5z3eouQaC-kh6_uHOTzZg,69
50
+ python_motion_planning/traj_optimizer/base_curve_generator.py,sha256=m7-EZOIH5lOFiMVyvh5LYemjnWsiw0yRAvYUWG5mIFQ,1619
51
+ python_motion_planning/traj_optimizer/curve_generator/__init__.py,sha256=q40AJi09Wgv84NEU7fkdcSdNIGwoKy42Bsnt7YHaOdY,55
52
+ python_motion_planning/traj_optimizer/curve_generator/point_based/__init__.py,sha256=3V3ddQ0RfWs9oS57MUioGqzmMhPEXdVxbHkL9t_KlSM,53
53
+ python_motion_planning/traj_optimizer/curve_generator/point_based/bspline.py,sha256=GRcRHCC56Kdm74LFv96ANzHdaBxihTCfL-sk87rD3h8,9110
54
+ python_motion_planning/traj_optimizer/curve_generator/point_based/cubic_spline.py,sha256=sArmL1kLKHc-NRLFtczwpO6ATmuI3SB_FHTgSk826wI,3962
55
+ python_motion_planning/traj_optimizer/curve_generator/pose_based/__init__.py,sha256=muLe-_uENMf_btwqmVsRP0Ikbryut3Wl0_0BxNRhhbU,101
56
+ python_motion_planning/traj_optimizer/curve_generator/pose_based/bezier.py,sha256=BuLp6MzbyhuElD4qnos_nQQi9HvRVxx2AI5xPuUf2_I,4405
57
+ python_motion_planning/traj_optimizer/curve_generator/pose_based/dubins.py,sha256=76ujAOJHl3o4HkV1e5wuZEyz9wxzaGkDizDUx3M9C0w,13895
58
+ python_motion_planning/traj_optimizer/curve_generator/pose_based/polynomial.py,sha256=kjDkVskkfFHERZdJx6GU_GrRTJmrGHuX383W2s1oECI,7381
59
+ python_motion_planning/traj_optimizer/curve_generator/pose_based/reeds_shepp.py,sha256=I6KjYZvG4lOE2N9_vp1hSzJuan4SOrpuQF2L57owII4,22970
60
+ python_motion_planning-2.0.1.dist-info/licenses/LICENSE,sha256=a4N8el8H0UrdAJzCeVgj9HklpT3VkZfsy4aL1SAifJE,35793
61
+ python_motion_planning-2.0.1.dist-info/METADATA,sha256=61r3x6QoQCBJIHm1yt10khJLLdTw5P7zEXHZGkZwr7Y,49587
62
+ python_motion_planning-2.0.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
63
+ python_motion_planning-2.0.1.dist-info/top_level.txt,sha256=VtZTYZios8VncYIkec7tOVdYqj5oMRmoeBb9RcJHluY,23
64
+ python_motion_planning-2.0.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (82.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,9 +0,0 @@
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"]
@@ -1,131 +0,0 @@
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
-
@@ -1,271 +0,0 @@
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)]