├── .circleci └── config.yml ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.md ├── codeql │ └── codeql-config.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── Linux_CI.yml │ ├── MacOS_CI.yml │ ├── circleci-artifacts-redirector.yml │ ├── codeql.yml │ └── gh-pages.yml ├── .gitignore ├── .lgtm.yml ├── AerialNavigation ├── __init__.py ├── drone_3d_trajectory_following │ ├── Quadrotor.py │ ├── TrajectoryGenerator.py │ ├── __init__.py │ └── drone_3d_trajectory_following.py └── rocket_powered_landing │ └── rocket_powered_landing.py ├── ArmNavigation ├── __init__.py ├── arm_obstacle_navigation │ ├── arm_obstacle_navigation.py │ └── arm_obstacle_navigation_2.py ├── n_joint_arm_3d │ ├── NLinkArm3d.py │ ├── __init__.py │ ├── random_forward_kinematics.py │ └── random_inverse_kinematics.py ├── n_joint_arm_to_point_control │ ├── NLinkArm.py │ ├── __init__.py │ └── n_joint_arm_to_point_control.py ├── rrt_star_seven_joint_arm_control │ └── rrt_star_seven_joint_arm_control.py └── two_joint_arm_to_point_control │ └── two_joint_arm_to_point_control.py ├── Bipedal ├── __init__.py └── bipedal_planner │ ├── __init__.py │ └── bipedal_planner.py ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Control ├── __init__.py ├── inverted_pendulum │ ├── inverted_pendulum_lqr_control.py │ └── inverted_pendulum_mpc_control.py └── move_to_pose │ ├── __init__.py │ ├── move_to_pose.py │ └── move_to_pose_robot.py ├── LICENSE ├── Localization ├── __init__.py ├── cubature_kalman_filter │ └── cubature_kalman_filter.py ├── ensemble_kalman_filter │ └── ensemble_kalman_filter.py ├── extended_kalman_filter │ └── extended_kalman_filter.py ├── histogram_filter │ └── histogram_filter.py ├── particle_filter │ └── particle_filter.py └── unscented_kalman_filter │ └── unscented_kalman_filter.py ├── Mapping ├── __init__.py ├── circle_fitting │ └── circle_fitting.py ├── gaussian_grid_map │ └── gaussian_grid_map.py ├── grid_map_lib │ ├── __init__.py │ └── grid_map_lib.py ├── kmeans_clustering │ └── kmeans_clustering.py ├── lidar_to_grid_map │ ├── lidar01.csv │ └── lidar_to_grid_map.py ├── raycasting_grid_map │ └── raycasting_grid_map.py └── rectangle_fitting │ ├── __init_.py │ ├── rectangle_fitting.py │ └── simulator.py ├── PathPlanning ├── AStar │ ├── a_star.py │ ├── a_star_searching_from_two_side.py │ └── a_star_variants.py ├── BSplinePath │ └── bspline_path.py ├── BatchInformedRRTStar │ └── batch_informed_rrtstar.py ├── BezierPath │ └── bezier_path.py ├── BidirectionalAStar │ └── bidirectional_a_star.py ├── BidirectionalBreadthFirstSearch │ └── bidirectional_breadth_first_search.py ├── BreadthFirstSearch │ └── breadth_first_search.py ├── BugPlanning │ └── bug.py ├── ClosedLoopRRTStar │ ├── closed_loop_rrt_star_car.py │ ├── pure_pursuit.py │ └── unicycle_model.py ├── ClothoidPath │ └── clothoid_path_planner.py ├── CubicSpline │ ├── __init__.py │ ├── cubic_spline_planner.py │ └── spline_continuity.py ├── DStar │ └── dstar.py ├── DStarLite │ └── d_star_lite.py ├── DepthFirstSearch │ └── depth_first_search.py ├── Dijkstra │ └── dijkstra.py ├── DubinsPath │ ├── __init__.py │ └── dubins_path_planner.py ├── DynamicMovementPrimitives │ └── dynamic_movement_primitives.py ├── DynamicWindowApproach │ └── dynamic_window_approach.py ├── Eta3SplinePath │ └── eta3_spline_path.py ├── Eta3SplineTrajectory │ └── eta3_spline_trajectory.py ├── FlowField │ └── flowfield.py ├── FrenetOptimalTrajectory │ └── frenet_optimal_trajectory.py ├── GreedyBestFirstSearch │ └── greedy_best_first_search.py ├── GridBasedSweepCPP │ └── grid_based_sweep_coverage_path_planner.py ├── HybridAStar │ ├── __init__.py │ ├── car.py │ ├── dynamic_programming_heuristic.py │ ├── hybrid_a_star.py │ ├── my_hybrid_a_star.py │ ├── robot.py │ ├── tempCodeRunnerFile.py │ └── test.py ├── InformedRRTStar │ └── informed_rrt_star.py ├── LQRPlanner │ └── lqr_planner.py ├── LQRRRTStar │ └── lqr_rrt_star.py ├── ModelPredictiveTrajectoryGenerator │ ├── __init__.py │ ├── lookup_table_generator.py │ ├── motion_model.py │ └── trajectory_generator.py ├── PotentialFieldPlanning │ └── potential_field_planning.py ├── ProbabilisticRoadMap │ └── probabilistic_road_map.py ├── QuinticPolynomialsPlanner │ └── quintic_polynomials_planner.py ├── RRT │ ├── __init__.py │ ├── rrt.py │ ├── rrt_with_pathsmoothing.py │ ├── rrt_with_sobol_sampler.py │ └── sobol │ │ ├── __init__.py │ │ └── sobol.py ├── RRTDubins │ ├── __init__.py │ └── rrt_dubins.py ├── RRTStar │ ├── __init__.py │ └── rrt_star.py ├── RRTStarDubins │ └── rrt_star_dubins.py ├── RRTStarReedsShepp │ └── rrt_star_reeds_shepp.py ├── ReedsSheppPath │ └── reeds_shepp_path_planning.py ├── SpiralSpanningTreeCPP │ ├── map │ │ ├── test.png │ │ ├── test_2.png │ │ └── test_3.png │ └── spiral_spanning_tree_coverage_path_planner.py ├── StateLatticePlanner │ ├── __init__.py │ ├── lookup_table.csv │ └── state_lattice_planner.py ├── VisibilityRoadMap │ ├── __init__.py │ ├── geometry.py │ └── visibility_road_map.py ├── VoronoiRoadMap │ ├── __init__.py │ ├── dijkstra_search.py │ └── voronoi_road_map.py ├── WavefrontCPP │ ├── map │ │ ├── test.png │ │ ├── test_2.png │ │ └── test_3.png │ └── wavefront_coverage_path_planner.py └── __init__.py ├── PathTracking ├── __init__.py ├── cgmres_nmpc │ └── cgmres_nmpc.py ├── lqr_speed_steer_control │ └── lqr_speed_steer_control.py ├── lqr_steer_control │ ├── __init__.py │ └── lqr_steer_control.py ├── model_predictive_speed_and_steer_control │ └── model_predictive_speed_and_steer_control.py ├── pure_pursuit │ └── pure_pursuit.py ├── rear_wheel_feedback │ └── rear_wheel_feedback.py └── stanley_controller │ └── stanley_controller.py ├── README.md ├── SECURITY.md ├── SLAM ├── EKFSLAM │ └── ekf_slam.py ├── FastSLAM1 │ └── fast_slam1.py ├── FastSLAM2 │ └── fast_slam2.py ├── GraphBasedSLAM │ ├── data │ │ ├── README.rst │ │ └── input_INTEL.g2o │ ├── graph_based_slam.py │ └── graphslam │ │ ├── __init__.py │ │ ├── edge │ │ ├── __init__.py │ │ └── edge_odometry.py │ │ ├── graph.py │ │ ├── load.py │ │ ├── pose │ │ ├── __init__.py │ │ └── se2.py │ │ ├── util.py │ │ └── vertex.py ├── __init__.py └── iterative_closest_point │ └── iterative_closest_point.py ├── __init__.py ├── _config.yml ├── appveyor.yml ├── docs ├── Makefile ├── README.md ├── _static │ ├── .gitkeep │ ├── custom.css │ └── img │ │ └── doc_ci.png ├── _templates │ └── layout.html ├── conf.py ├── doc_requirements.txt ├── getting_started_main.rst ├── how_to_contribute_main.rst ├── index_main.rst ├── make.bat └── modules │ ├── aerial_navigation │ ├── aerial_navigation_main.rst │ ├── drone_3d_trajectory_following │ │ └── drone_3d_trajectory_following_main.rst │ └── rocket_powered_landing │ │ └── rocket_powered_landing_main.rst │ ├── appendix │ ├── Kalmanfilter_basics_2_files │ │ └── Kalmanfilter_basics_2_5_0.png │ ├── Kalmanfilter_basics_2_main.rst │ ├── Kalmanfilter_basics_files │ │ ├── Kalmanfilter_basics_14_1.png │ │ ├── Kalmanfilter_basics_16_0.png │ │ ├── Kalmanfilter_basics_19_1.png │ │ ├── Kalmanfilter_basics_21_1.png │ │ ├── Kalmanfilter_basics_22_0.png │ │ └── Kalmanfilter_basics_28_1.png │ ├── Kalmanfilter_basics_main.rst │ └── appendix_main.rst │ ├── arm_navigation │ ├── Planar_Two_Link_IK_files │ │ ├── Planar_Two_Link_IK_12_0.png │ │ ├── Planar_Two_Link_IK_5_0.png │ │ ├── Planar_Two_Link_IK_7_0.png │ │ └── Planar_Two_Link_IK_9_0.png │ ├── arm_navigation_main.rst │ ├── n_joint_arm_to_point_control_main.rst │ ├── obstacle_avoidance_arm_navigation_main.rst │ └── planar_two_link_ik_main.rst │ ├── bipedal │ ├── bipedal_main.rst │ └── bipedal_planner │ │ └── bipedal_planner_main.rst │ ├── control │ ├── control_main.rst │ ├── inverted_pendulum_control │ │ ├── inverted-pendulum.png │ │ └── inverted_pendulum_control_main.rst │ └── move_to_a_pose_control │ │ └── move_to_a_pose_control_main.rst │ ├── introduction_main.rst │ ├── localization │ ├── ensamble_kalman_filter_localization_files │ │ └── ensamble_kalman_filter_localization_main.rst │ ├── extended_kalman_filter_localization_files │ │ ├── extended_kalman_filter_localization_1_0.png │ │ └── extended_kalman_filter_localization_main.rst │ ├── histogram_filter_localization │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ └── histogram_filter_localization_main.rst │ ├── localization_main.rst │ ├── particle_filter_localization │ │ └── particle_filter_localization_main.rst │ └── unscented_kalman_filter_localization │ │ └── unscented_kalman_filter_localization_main.rst │ ├── mapping │ ├── circle_fitting │ │ └── circle_fitting_main.rst │ ├── gaussian_grid_map │ │ └── gaussian_grid_map_main.rst │ ├── k_means_object_clustering │ │ └── k_means_object_clustering_main.rst │ ├── lidar_to_grid_map_tutorial │ │ ├── grid_map_example.png │ │ ├── lidar_to_grid_map_tutorial_12_0.png │ │ ├── lidar_to_grid_map_tutorial_14_1.png │ │ ├── lidar_to_grid_map_tutorial_5_0.png │ │ ├── lidar_to_grid_map_tutorial_7_0.png │ │ ├── lidar_to_grid_map_tutorial_8_0.png │ │ └── lidar_to_grid_map_tutorial_main.rst │ ├── mapping_main.rst │ ├── ray_casting_grid_map │ │ └── ray_casting_grid_map_main.rst │ └── rectangle_fitting │ │ └── rectangle_fitting_main.rst │ ├── path_planning │ ├── bezier_path │ │ ├── Figure_1.png │ │ ├── Figure_2.png │ │ └── bezier_path_main.rst │ ├── bspline_path │ │ ├── approx_and_curvature.png │ │ ├── approximation1.png │ │ ├── basis_functions.png │ │ ├── bspline_path_main.rst │ │ ├── bspline_path_planning.png │ │ ├── interp_and_curvature.png │ │ └── interpolation1.png │ ├── bugplanner │ │ └── bugplanner_main.rst │ ├── closed_loop_rrt_star_car │ │ ├── Figure_1.png │ │ ├── Figure_3.png │ │ ├── Figure_4.png │ │ └── Figure_5.png │ ├── clothoid_path │ │ └── clothoid_path_main.rst │ ├── coverage_path │ │ └── coverage_path_main.rst │ ├── cubic_spline │ │ ├── cubic_spline_1d.png │ │ ├── cubic_spline_2d_curvature.png │ │ ├── cubic_spline_2d_path.png │ │ ├── cubic_spline_2d_yaw.png │ │ ├── cubic_spline_main.rst │ │ ├── spline.png │ │ └── spline_continuity.png │ ├── dubins_path │ │ ├── RLR.jpg │ │ ├── RSR.jpg │ │ ├── dubins_path.jpg │ │ └── dubins_path_main.rst │ ├── dynamic_window_approach │ │ └── dynamic_window_approach_main.rst │ ├── eta3_spline │ │ └── eta3_spline_main.rst │ ├── frenet_frame_path │ │ └── frenet_frame_path_main.rst │ ├── grid_base_search │ │ └── grid_base_search_main.rst │ ├── hybridastar │ │ └── hybridastar_main.rst │ ├── lqr_path │ │ └── lqr_path_main.rst │ ├── model_predictive_trajectory_generator │ │ ├── lookup_table.png │ │ └── model_predictive_trajectory_generator_main.rst │ ├── path_planning_main.rst │ ├── prm_planner │ │ └── prm_planner_main.rst │ ├── quintic_polynomials_planner │ │ └── quintic_polynomials_planner_main.rst │ ├── reeds_shepp_path │ │ └── reeds_shepp_path_main.rst │ ├── rrt │ │ ├── figure_1.png │ │ ├── rrt_main.rst │ │ ├── rrt_star.rst │ │ ├── rrt_star │ │ │ └── rrt_star_1_0.png │ │ └── rrt_star_reeds_shepp │ │ │ └── figure_1.png │ ├── state_lattice_planner │ │ ├── Figure_1.png │ │ ├── Figure_2.png │ │ ├── Figure_3.png │ │ ├── Figure_4.png │ │ ├── Figure_5.png │ │ ├── Figure_6.png │ │ └── state_lattice_planner_main.rst │ ├── visibility_road_map_planner │ │ ├── step0.png │ │ ├── step1.png │ │ ├── step2.png │ │ ├── step3.png │ │ └── visibility_road_map_planner_main.rst │ └── vrm_planner │ │ └── vrm_planner_main.rst │ ├── path_tracking │ ├── cgmres_nmpc │ │ ├── cgmres_nmpc_1_0.png │ │ ├── cgmres_nmpc_2_0.png │ │ ├── cgmres_nmpc_3_0.png │ │ ├── cgmres_nmpc_4_0.png │ │ └── cgmres_nmpc_main.rst │ ├── lqr_speed_and_steering_control │ │ └── lqr_speed_and_steering_control_main.rst │ ├── lqr_steering_control │ │ └── lqr_steering_control_main.rst │ ├── model_predictive_speed_and_steering_control │ │ └── model_predictive_speed_and_steering_control_main.rst │ ├── path_tracking_main.rst │ ├── pure_pursuit_tracking │ │ └── pure_pursuit_tracking_main.rst │ ├── rear_wheel_feedback_control │ │ └── rear_wheel_feedback_control_main.rst │ └── stanley_control │ │ └── stanley_control_main.rst │ ├── slam │ ├── FastSLAM1 │ │ ├── FastSLAM1_12_0.png │ │ ├── FastSLAM1_12_1.png │ │ ├── FastSLAM1_1_0.png │ │ └── FastSLAM1_main.rst │ ├── FastSLAM2 │ │ └── FastSLAM2_main.rst │ ├── ekf_slam │ │ ├── ekf_slam_1_0.png │ │ └── ekf_slam_main.rst │ ├── graph_slam │ │ ├── graphSLAM_SE2_example.rst │ │ ├── graphSLAM_SE2_example_files │ │ │ ├── Graph_SLAM_optimization.gif │ │ │ ├── graphSLAM_SE2_example_13_0.png │ │ │ ├── graphSLAM_SE2_example_15_0.png │ │ │ ├── graphSLAM_SE2_example_16_0.png │ │ │ ├── graphSLAM_SE2_example_4_0.png │ │ │ ├── graphSLAM_SE2_example_8_0.png │ │ │ └── graphSLAM_SE2_example_9_0.png │ │ ├── graphSLAM_doc.rst │ │ ├── graphSLAM_doc_files │ │ │ ├── graphSLAM_doc_11_1.png │ │ │ ├── graphSLAM_doc_11_2.png │ │ │ ├── graphSLAM_doc_2_0.png │ │ │ ├── graphSLAM_doc_2_2.png │ │ │ ├── graphSLAM_doc_4_0.png │ │ │ └── graphSLAM_doc_9_1.png │ │ ├── graphSLAM_formulation.rst │ │ └── graph_slam_main.rst │ ├── iterative_closest_point_matching │ │ └── iterative_closest_point_matching_main.rst │ └── slam_main.rst │ └── utils │ ├── plot │ ├── curvature_plot.png │ └── plot_main.rst │ └── utils_main.rst ├── icon.png ├── mypy.ini ├── requirements ├── environment.yml └── requirements.txt ├── runtests.sh ├── tests ├── __init__.py ├── conftest.py ├── test_LQR_planner.py ├── test_a_star.py ├── test_a_star_searching_two_side.py ├── test_a_star_variants.py ├── test_batch_informed_rrt_star.py ├── test_bezier_path.py ├── test_bipedal_planner.py ├── test_breadth_first_search.py ├── test_bspline_path.py ├── test_bug.py ├── test_cgmres_nmpc.py ├── test_circle_fitting.py ├── test_closed_loop_rrt_star_car.py ├── test_clothoidal_paths.py ├── test_cubature_kalman_filter.py ├── test_d_star_lite.py ├── test_depth_first_search.py ├── test_diff_codestyle.py ├── test_dijkstra.py ├── test_drone_3d_trajectory_following.py ├── test_dstar.py ├── test_dubins_path_planning.py ├── test_dynamic_movement_primitives.py ├── test_dynamic_window_approach.py ├── test_ekf_slam.py ├── test_eta3_spline_path.py ├── test_extended_kalman_filter.py ├── test_fast_slam1.py ├── test_fast_slam2.py ├── test_flow_field.py ├── test_frenet_optimal_trajectory.py ├── test_gaussian_grid_map.py ├── test_graph_based_slam.py ├── test_greedy_best_first_search.py ├── test_grid_based_sweep_coverage_path_planner.py ├── test_grid_map_lib.py ├── test_histogram_filter.py ├── test_hybrid_a_star.py ├── test_informed_rrt_star.py ├── test_inverted_pendulum_lqr_control.py ├── test_inverted_pendulum_mpc_control.py ├── test_iterative_closest_point.py ├── test_kmeans_clustering.py ├── test_lqr_rrt_star.py ├── test_lqr_speed_steer_control.py ├── test_lqr_steer_control.py ├── test_model_predictive_speed_and_steer_control.py ├── test_move_to_pose.py ├── test_move_to_pose_robot.py ├── test_mypy_type_check.py ├── test_n_joint_arm_to_point_control.py ├── test_particle_filter.py ├── test_potential_field_planning.py ├── test_probabilistic_road_map.py ├── test_pure_pursuit.py ├── test_quintic_polynomials_planner.py ├── test_raycasting_grid_map.py ├── test_rear_wheel_feedback.py ├── test_rectangle_fitting.py ├── test_reeds_shepp_path_planning.py ├── test_rocket_powered_landing.py ├── test_rrt.py ├── test_rrt_dubins.py ├── test_rrt_star.py ├── test_rrt_star_dubins.py ├── test_rrt_star_reeds_shepp.py ├── test_rrt_star_seven_joint_arm.py ├── test_rrt_with_sobol_sampler.py ├── test_spiral_spanning_tree_coverage_path_planner.py ├── test_stanley_controller.py ├── test_state_lattice_planner.py ├── test_two_joint_arm_to_point_control.py ├── test_unscented_kalman_filter.py ├── test_utils.py ├── test_visibility_road_map_planner.py ├── test_voronoi_road_map_planner.py └── test_wavefront_coverage_path_planner.py ├── users_comments.md └── utils ├── __init__.py ├── angle.py └── plot.py /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | python: circleci/python@1.4.0 5 | 6 | jobs: 7 | build_doc: 8 | docker: 9 | - image: cimg/python:3.10 10 | steps: 11 | - checkout 12 | - run: 13 | name: doc_build 14 | command: | 15 | python --version 16 | python -m venv venv 17 | . venv/bin/activate 18 | pip install -r requirements/requirements.txt 19 | pip install -r docs/doc_requirements.txt 20 | cd docs;make html 21 | - store_artifacts: 22 | path: docs/_build/html/ 23 | destination: html 24 | 25 | workflows: 26 | main: 27 | jobs: 28 | - build_doc 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | github: AtsushiSakai 3 | patreon: myenigma 4 | custom: https://www.paypal.me/myenigmapay/ 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Screenshots** 17 | If applicable, add screenshots to help explain your problem. 18 | 19 | **Desktop (please complete the following information):** 20 | - Python version (This repo only supports Python 3.9.x or higher). 21 | - Each library version 22 | - OS version 23 | -------------------------------------------------------------------------------- /.github/codeql/codeql-config.yml: -------------------------------------------------------------------------------- 1 | name: "Extended CodeQL Config" 2 | 3 | # This file adds additional queries to the default configuration to make it equivalent to what LGTM checks. 4 | queries: 5 | - name: Security and quality queries 6 | uses: security-and-quality 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: pip 4 | directory: "/requirements" 5 | schedule: 6 | interval: weekly 7 | time: "20:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 11 | 12 | #### Reference issue 13 | 14 | 15 | #### What does this implement/fix? 16 | 17 | 18 | #### Additional information 19 | 20 | 21 | #### CheckList 22 | - [ ] Did you add an unittest for your new example or defect fix? 23 | - [ ] Did you add documents for your new example? 24 | - [ ] All CIs are green? (You can check it after submitting) 25 | -------------------------------------------------------------------------------- /.github/workflows/Linux_CI.yml: -------------------------------------------------------------------------------- 1 | name: Linux_CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | python-version: [ '3.10.6' ] # For mypy error Ref: https://github.com/python/mypy/issues/13627 16 | 17 | name: Python ${{ matrix.python-version }} CI 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - run: git fetch --prune --unshallow 22 | 23 | - name: Setup python 24 | uses: actions/setup-python@v2 25 | with: 26 | python-version: ${{ matrix.python-version }} 27 | - name: Install dependencies 28 | run: | 29 | python --version 30 | python -m pip install --upgrade pip 31 | python -m pip install -r requirements/requirements.txt 32 | - name: do all unit tests 33 | run: bash runtests.sh 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/workflows/MacOS_CI.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: MacOS_CI 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: 10 | - master 11 | pull_request: 12 | 13 | 14 | jobs: 15 | build: 16 | runs-on: macos-latest 17 | strategy: 18 | matrix: 19 | python-version: [ '3.10.6' ] # For mypy error Ref: https://github.com/python/mypy/issues/13627 20 | name: Python ${{ matrix.python-version }} CI 21 | steps: 22 | - uses: actions/checkout@v2 23 | - run: git fetch --prune --unshallow 24 | 25 | - name: Update bash 26 | run: brew install bash 27 | 28 | - name: Setup python 29 | uses: actions/setup-python@v2 30 | with: 31 | python-version: ${{ matrix.python-version }} 32 | 33 | - name: Install dependencies 34 | run: | 35 | python --version 36 | python -m pip install --upgrade pip 37 | pip install -r requirements/requirements.txt 38 | - name: do all unit tests 39 | run: bash runtests.sh -------------------------------------------------------------------------------- /.github/workflows/circleci-artifacts-redirector.yml: -------------------------------------------------------------------------------- 1 | name: circleci-artifacts-redirector-action 2 | on: [status] 3 | jobs: 4 | circleci_artifacts_redirector_job: 5 | runs-on: ubuntu-latest 6 | name: Run CircleCI artifacts redirector!! 7 | steps: 8 | - name: run-circleci-artifacts-redirector 9 | uses: larsoner/circleci-artifacts-redirector-action@0.3.1 10 | with: 11 | repo-token: ${{ secrets.GITHUB_TOKEN }} 12 | artifact-path: 0/html/index.html 13 | circleci-jobs: build_doc 14 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "Code scanning - action" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | schedule: 9 | - cron: '0 19 * * 0' 10 | 11 | jobs: 12 | CodeQL-Build: 13 | 14 | # CodeQL runs on ubuntu-latest and windows-latest 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v2 20 | with: 21 | # We must fetch at least the immediate parents so that if this is 22 | # a pull request then we can checkout the head. 23 | fetch-depth: 2 24 | 25 | # Initializes the CodeQL tools for scanning. 26 | - name: Initialize CodeQL 27 | uses: github/codeql-action/init@v1 28 | with: 29 | config-file: ./.github/codeql/codeql-config.yml 30 | # Override language selection by uncommenting this and choosing your languages 31 | # with: 32 | # languages: go, javascript, csharp, python, cpp, java 33 | 34 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 35 | # If this step fails, then you should remove it and run the build manually (see below) 36 | - name: Autobuild 37 | uses: github/codeql-action/autobuild@v1 38 | 39 | # ℹ️ Command-line programs to run using the OS shell. 40 | # 📚 https://git.io/JvXDl 41 | 42 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 43 | # and modify them (or add more) to build your code if your project 44 | # uses a compiled language 45 | 46 | #- run: | 47 | # make bootstrap 48 | # make release 49 | 50 | - name: Perform CodeQL Analysis 51 | uses: github/codeql-action/analyze@v1 52 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Pages 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Setup python 11 | uses: actions/setup-python@v3 12 | - name: Checkout 13 | uses: actions/checkout@master 14 | with: 15 | fetch-depth: 0 # otherwise, you will fail to push refs to dest repo 16 | - name: Install dependencies 17 | run: | 18 | python --version 19 | python -m pip install --upgrade pip 20 | python -m pip install -r requirements/requirements.txt 21 | - name: Build and Commit 22 | uses: sphinx-notes/pages@v2 23 | with: 24 | requirements_path: ./docs/doc_requirements.txt 25 | - name: Push changes 26 | uses: ad-m/github-push-action@master 27 | with: 28 | github_token: ${{ secrets.GITHUB_TOKEN }} 29 | branch: gh-pages 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.csv 2 | *.gif 3 | *.g2o 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | _build/ 10 | .idea/ 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | env/ 18 | build/ 19 | develop-eggs/ 20 | dist/ 21 | downloads/ 22 | eggs/ 23 | .eggs/ 24 | lib/ 25 | lib64/ 26 | parts/ 27 | sdist/ 28 | var/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | 33 | .DS_Store 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *,cover 54 | .hypothesis/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | #Ipython Notebook 70 | .ipynb_checkpoints 71 | 72 | matplotrecorder/* 73 | .vscode/settings.json 74 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | extraction: 2 | python: 3 | python_setup: 4 | version: 3 5 | -------------------------------------------------------------------------------- /AerialNavigation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/AerialNavigation/__init__.py -------------------------------------------------------------------------------- /AerialNavigation/drone_3d_trajectory_following/Quadrotor.py: -------------------------------------------------------------------------------- 1 | """ 2 | Class for plotting a quadrotor 3 | 4 | Author: Daniel Ingram (daniel-s-ingram) 5 | """ 6 | 7 | from math import cos, sin 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | 11 | class Quadrotor(): 12 | def __init__(self, x=0, y=0, z=0, roll=0, pitch=0, yaw=0, size=0.25, show_animation=True): 13 | self.p1 = np.array([size / 2, 0, 0, 1]).T 14 | self.p2 = np.array([-size / 2, 0, 0, 1]).T 15 | self.p3 = np.array([0, size / 2, 0, 1]).T 16 | self.p4 = np.array([0, -size / 2, 0, 1]).T 17 | 18 | self.x_data = [] 19 | self.y_data = [] 20 | self.z_data = [] 21 | self.show_animation = show_animation 22 | 23 | if self.show_animation: 24 | plt.ion() 25 | fig = plt.figure() 26 | # for stopping simulation with the esc key. 27 | fig.canvas.mpl_connect('key_release_event', 28 | lambda event: [exit(0) if event.key == 'escape' else None]) 29 | 30 | self.ax = fig.add_subplot(111, projection='3d') 31 | 32 | self.update_pose(x, y, z, roll, pitch, yaw) 33 | 34 | def update_pose(self, x, y, z, roll, pitch, yaw): 35 | self.x = x 36 | self.y = y 37 | self.z = z 38 | self.roll = roll 39 | self.pitch = pitch 40 | self.yaw = yaw 41 | self.x_data.append(x) 42 | self.y_data.append(y) 43 | self.z_data.append(z) 44 | 45 | if self.show_animation: 46 | self.plot() 47 | 48 | def transformation_matrix(self): 49 | x = self.x 50 | y = self.y 51 | z = self.z 52 | roll = self.roll 53 | pitch = self.pitch 54 | yaw = self.yaw 55 | return np.array( 56 | [[cos(yaw) * cos(pitch), -sin(yaw) * cos(roll) + cos(yaw) * sin(pitch) * sin(roll), sin(yaw) * sin(roll) + cos(yaw) * sin(pitch) * cos(roll), x], 57 | [sin(yaw) * cos(pitch), cos(yaw) * cos(roll) + sin(yaw) * sin(pitch) 58 | * sin(roll), -cos(yaw) * sin(roll) + sin(yaw) * sin(pitch) * cos(roll), y], 59 | [-sin(pitch), cos(pitch) * sin(roll), cos(pitch) * cos(yaw), z] 60 | ]) 61 | 62 | def plot(self): # pragma: no cover 63 | T = self.transformation_matrix() 64 | 65 | p1_t = np.matmul(T, self.p1) 66 | p2_t = np.matmul(T, self.p2) 67 | p3_t = np.matmul(T, self.p3) 68 | p4_t = np.matmul(T, self.p4) 69 | 70 | plt.cla() 71 | 72 | self.ax.plot([p1_t[0], p2_t[0], p3_t[0], p4_t[0]], 73 | [p1_t[1], p2_t[1], p3_t[1], p4_t[1]], 74 | [p1_t[2], p2_t[2], p3_t[2], p4_t[2]], 'k.') 75 | 76 | self.ax.plot([p1_t[0], p2_t[0]], [p1_t[1], p2_t[1]], 77 | [p1_t[2], p2_t[2]], 'r-') 78 | self.ax.plot([p3_t[0], p4_t[0]], [p3_t[1], p4_t[1]], 79 | [p3_t[2], p4_t[2]], 'r-') 80 | 81 | self.ax.plot(self.x_data, self.y_data, self.z_data, 'b:') 82 | 83 | plt.xlim(-5, 5) 84 | plt.ylim(-5, 5) 85 | self.ax.set_zlim(0, 10) 86 | 87 | plt.pause(0.001) 88 | -------------------------------------------------------------------------------- /AerialNavigation/drone_3d_trajectory_following/TrajectoryGenerator.py: -------------------------------------------------------------------------------- 1 | """ 2 | Generates a quintic polynomial trajectory. 3 | 4 | Author: Daniel Ingram (daniel-s-ingram) 5 | """ 6 | 7 | import numpy as np 8 | 9 | class TrajectoryGenerator(): 10 | def __init__(self, start_pos, des_pos, T, start_vel=[0,0,0], des_vel=[0,0,0], start_acc=[0,0,0], des_acc=[0,0,0]): 11 | self.start_x = start_pos[0] 12 | self.start_y = start_pos[1] 13 | self.start_z = start_pos[2] 14 | 15 | self.des_x = des_pos[0] 16 | self.des_y = des_pos[1] 17 | self.des_z = des_pos[2] 18 | 19 | self.start_x_vel = start_vel[0] 20 | self.start_y_vel = start_vel[1] 21 | self.start_z_vel = start_vel[2] 22 | 23 | self.des_x_vel = des_vel[0] 24 | self.des_y_vel = des_vel[1] 25 | self.des_z_vel = des_vel[2] 26 | 27 | self.start_x_acc = start_acc[0] 28 | self.start_y_acc = start_acc[1] 29 | self.start_z_acc = start_acc[2] 30 | 31 | self.des_x_acc = des_acc[0] 32 | self.des_y_acc = des_acc[1] 33 | self.des_z_acc = des_acc[2] 34 | 35 | self.T = T 36 | 37 | def solve(self): 38 | A = np.array( 39 | [[0, 0, 0, 0, 0, 1], 40 | [self.T**5, self.T**4, self.T**3, self.T**2, self.T, 1], 41 | [0, 0, 0, 0, 1, 0], 42 | [5*self.T**4, 4*self.T**3, 3*self.T**2, 2*self.T, 1, 0], 43 | [0, 0, 0, 2, 0, 0], 44 | [20*self.T**3, 12*self.T**2, 6*self.T, 2, 0, 0] 45 | ]) 46 | 47 | b_x = np.array( 48 | [[self.start_x], 49 | [self.des_x], 50 | [self.start_x_vel], 51 | [self.des_x_vel], 52 | [self.start_x_acc], 53 | [self.des_x_acc] 54 | ]) 55 | 56 | b_y = np.array( 57 | [[self.start_y], 58 | [self.des_y], 59 | [self.start_y_vel], 60 | [self.des_y_vel], 61 | [self.start_y_acc], 62 | [self.des_y_acc] 63 | ]) 64 | 65 | b_z = np.array( 66 | [[self.start_z], 67 | [self.des_z], 68 | [self.start_z_vel], 69 | [self.des_z_vel], 70 | [self.start_z_acc], 71 | [self.des_z_acc] 72 | ]) 73 | 74 | self.x_c = np.linalg.solve(A, b_x) 75 | self.y_c = np.linalg.solve(A, b_y) 76 | self.z_c = np.linalg.solve(A, b_z) -------------------------------------------------------------------------------- /AerialNavigation/drone_3d_trajectory_following/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pathlib 3 | sys.path.append(str(pathlib.Path(__file__).parent)) 4 | -------------------------------------------------------------------------------- /ArmNavigation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/ArmNavigation/__init__.py -------------------------------------------------------------------------------- /ArmNavigation/n_joint_arm_3d/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pathlib 3 | sys.path.append(str(pathlib.Path(__file__).parent)) 4 | -------------------------------------------------------------------------------- /ArmNavigation/n_joint_arm_3d/random_forward_kinematics.py: -------------------------------------------------------------------------------- 1 | """ 2 | Forward Kinematics for an n-link arm in 3D 3 | Author: Takayuki Murooka (takayuki5168) 4 | """ 5 | import math 6 | from NLinkArm3d import NLinkArm 7 | import random 8 | 9 | 10 | def random_val(min_val, max_val): 11 | return min_val + random.random() * (max_val - min_val) 12 | 13 | 14 | def main(): 15 | print("Start solving Forward Kinematics 10 times") 16 | # init NLinkArm with Denavit-Hartenberg parameters of PR2 17 | n_link_arm = NLinkArm([[0., -math.pi / 2, .1, 0.], 18 | [math.pi / 2, math.pi / 2, 0., 0.], 19 | [0., -math.pi / 2, 0., .4], 20 | [0., math.pi / 2, 0., 0.], 21 | [0., -math.pi / 2, 0., .321], 22 | [0., math.pi / 2, 0., 0.], 23 | [0., 0., 0., 0.]]) 24 | # execute FK 10 times 25 | for _ in range(10): 26 | n_link_arm.set_joint_angles( 27 | [random_val(-1, 1) for _ in range(len(n_link_arm.link_list))]) 28 | 29 | n_link_arm.forward_kinematics(plot=True) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /ArmNavigation/n_joint_arm_3d/random_inverse_kinematics.py: -------------------------------------------------------------------------------- 1 | """ 2 | Inverse Kinematics for an n-link arm in 3D 3 | Author: Takayuki Murooka (takayuki5168) 4 | """ 5 | import math 6 | from NLinkArm3d import NLinkArm 7 | import random 8 | 9 | 10 | def random_val(min_val, max_val): 11 | return min_val + random.random() * (max_val - min_val) 12 | 13 | 14 | def main(): 15 | print("Start solving Inverse Kinematics 10 times") 16 | # init NLinkArm with Denavit-Hartenberg parameters of PR2 17 | n_link_arm = NLinkArm([[0., -math.pi / 2, .1, 0.], 18 | [math.pi / 2, math.pi / 2, 0., 0.], 19 | [0., -math.pi / 2, 0., .4], 20 | [0., math.pi / 2, 0., 0.], 21 | [0., -math.pi / 2, 0., .321], 22 | [0., math.pi / 2, 0., 0.], 23 | [0., 0., 0., 0.]]) 24 | # execute IK 10 times 25 | for _ in range(10): 26 | n_link_arm.inverse_kinematics([random_val(-0.5, 0.5), 27 | random_val(-0.5, 0.5), 28 | random_val(-0.5, 0.5), 29 | random_val(-0.5, 0.5), 30 | random_val(-0.5, 0.5), 31 | random_val(-0.5, 0.5)], plot=True) 32 | 33 | 34 | if __name__ == "__main__": 35 | main() 36 | -------------------------------------------------------------------------------- /ArmNavigation/n_joint_arm_to_point_control/NLinkArm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Class for controlling and plotting an arm with an arbitrary number of links. 3 | 4 | Author: Daniel Ingram 5 | """ 6 | 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | 10 | 11 | class NLinkArm(object): 12 | def __init__(self, link_lengths, joint_angles, goal, show_animation): 13 | self.show_animation = show_animation 14 | self.n_links = len(link_lengths) 15 | if self.n_links != len(joint_angles): 16 | raise ValueError() 17 | 18 | self.link_lengths = np.array(link_lengths) 19 | self.joint_angles = np.array(joint_angles) 20 | self.points = [[0, 0] for _ in range(self.n_links + 1)] 21 | 22 | self.lim = sum(link_lengths) 23 | self.goal = np.array(goal).T 24 | 25 | if show_animation: # pragma: no cover 26 | self.fig = plt.figure() 27 | self.fig.canvas.mpl_connect('button_press_event', self.click) 28 | 29 | plt.ion() 30 | plt.show() 31 | 32 | self.update_points() 33 | 34 | def update_joints(self, joint_angles): 35 | self.joint_angles = joint_angles 36 | 37 | self.update_points() 38 | 39 | def update_points(self): 40 | for i in range(1, self.n_links + 1): 41 | self.points[i][0] = self.points[i - 1][0] + \ 42 | self.link_lengths[i - 1] * \ 43 | np.cos(np.sum(self.joint_angles[:i])) 44 | self.points[i][1] = self.points[i - 1][1] + \ 45 | self.link_lengths[i - 1] * \ 46 | np.sin(np.sum(self.joint_angles[:i])) 47 | 48 | self.end_effector = np.array(self.points[self.n_links]).T 49 | if self.show_animation: # pragma: no cover 50 | self.plot() 51 | 52 | def plot(self): # pragma: no cover 53 | plt.cla() 54 | # for stopping simulation with the esc key. 55 | plt.gcf().canvas.mpl_connect('key_release_event', 56 | lambda event: [exit(0) if event.key == 'escape' else None]) 57 | 58 | for i in range(self.n_links + 1): 59 | if i is not self.n_links: 60 | plt.plot([self.points[i][0], self.points[i + 1][0]], 61 | [self.points[i][1], self.points[i + 1][1]], 'r-') 62 | plt.plot(self.points[i][0], self.points[i][1], 'ko') 63 | 64 | plt.plot(self.goal[0], self.goal[1], 'gx') 65 | 66 | plt.plot([self.end_effector[0], self.goal[0]], [ 67 | self.end_effector[1], self.goal[1]], 'g--') 68 | 69 | plt.xlim([-self.lim, self.lim]) 70 | plt.ylim([-self.lim, self.lim]) 71 | plt.draw() 72 | plt.pause(0.0001) 73 | 74 | def click(self, event): 75 | self.goal = np.array([event.xdata, event.ydata]).T 76 | self.plot() 77 | -------------------------------------------------------------------------------- /ArmNavigation/n_joint_arm_to_point_control/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/ArmNavigation/n_joint_arm_to_point_control/__init__.py -------------------------------------------------------------------------------- /Bipedal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Bipedal/__init__.py -------------------------------------------------------------------------------- /Bipedal/bipedal_planner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Bipedal/bipedal_planner/__init__.py -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at asakaig@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Python 2 | 3 | :+1::tada: First of off, thanks very much for taking the time to contribute! :tada::+1: 4 | 5 | The following is a set of guidelines for contributing to PythonRobotics. 6 | 7 | These are mostly guidelines, not rules. 8 | 9 | Use your best judgment, and feel free to propose changes to this document in a pull request. 10 | 11 | # Before contributing 12 | 13 | ## Taking a look at the paper. 14 | 15 | Please check this paper to understand the philosophy of this project. 16 | 17 | - [\[1808\.10703\] PythonRobotics: a Python code collection of robotics algorithms](https://arxiv.org/abs/1808.10703) ([BibTeX](https://github.com/AtsushiSakai/PythonRoboticsPaper/blob/master/python_robotics.bib)) 18 | 19 | ## Check your Python version. 20 | 21 | We only accept a PR for Python 3.8.x or higher. 22 | 23 | We will not accept a PR for Python 2.x. 24 | -------------------------------------------------------------------------------- /Control/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Control/__init__.py -------------------------------------------------------------------------------- /Control/move_to_pose/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Control/move_to_pose/__init__.py -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 - 2022 Atsushi Sakai and other contributors: 4 | https://github.com/AtsushiSakai/PythonRobotics/contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Localization/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Localization/__init__.py -------------------------------------------------------------------------------- /Mapping/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Mapping/__init__.py -------------------------------------------------------------------------------- /Mapping/gaussian_grid_map/gaussian_grid_map.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | 2D gaussian grid map sample 4 | 5 | author: Atsushi Sakai (@Atsushi_twi) 6 | 7 | """ 8 | 9 | import math 10 | import numpy as np 11 | import matplotlib.pyplot as plt 12 | from scipy.stats import norm 13 | 14 | EXTEND_AREA = 10.0 # [m] grid map extention length 15 | 16 | show_animation = True 17 | 18 | 19 | def generate_gaussian_grid_map(ox, oy, xyreso, std): 20 | 21 | minx, miny, maxx, maxy, xw, yw = calc_grid_map_config(ox, oy, xyreso) 22 | 23 | gmap = [[0.0 for i in range(yw)] for i in range(xw)] 24 | 25 | for ix in range(xw): 26 | for iy in range(yw): 27 | 28 | x = ix * xyreso + minx 29 | y = iy * xyreso + miny 30 | 31 | # Search minimum distance 32 | mindis = float("inf") 33 | for (iox, ioy) in zip(ox, oy): 34 | d = math.hypot(iox - x, ioy - y) 35 | if mindis >= d: 36 | mindis = d 37 | 38 | pdf = (1.0 - norm.cdf(mindis, 0.0, std)) 39 | gmap[ix][iy] = pdf 40 | 41 | return gmap, minx, maxx, miny, maxy 42 | 43 | 44 | def calc_grid_map_config(ox, oy, xyreso): 45 | minx = round(min(ox) - EXTEND_AREA / 2.0) 46 | miny = round(min(oy) - EXTEND_AREA / 2.0) 47 | maxx = round(max(ox) + EXTEND_AREA / 2.0) 48 | maxy = round(max(oy) + EXTEND_AREA / 2.0) 49 | xw = int(round((maxx - minx) / xyreso)) 50 | yw = int(round((maxy - miny) / xyreso)) 51 | 52 | return minx, miny, maxx, maxy, xw, yw 53 | 54 | 55 | def draw_heatmap(data, minx, maxx, miny, maxy, xyreso): 56 | x, y = np.mgrid[slice(minx - xyreso / 2.0, maxx + xyreso / 2.0, xyreso), 57 | slice(miny - xyreso / 2.0, maxy + xyreso / 2.0, xyreso)] 58 | plt.pcolor(x, y, data, vmax=1.0, cmap=plt.cm.Blues) 59 | plt.axis("equal") 60 | 61 | 62 | def main(): 63 | print(__file__ + " start!!") 64 | 65 | xyreso = 0.5 # xy grid resolution 66 | STD = 5.0 # standard diviation for gaussian distribution 67 | 68 | for i in range(5): 69 | ox = (np.random.rand(4) - 0.5) * 10.0 70 | oy = (np.random.rand(4) - 0.5) * 10.0 71 | gmap, minx, maxx, miny, maxy = generate_gaussian_grid_map( 72 | ox, oy, xyreso, STD) 73 | 74 | if show_animation: # pragma: no cover 75 | plt.cla() 76 | # for stopping simulation with the esc key. 77 | plt.gcf().canvas.mpl_connect('key_release_event', 78 | lambda event: [exit(0) if event.key == 'escape' else None]) 79 | draw_heatmap(gmap, minx, maxx, miny, maxy, xyreso) 80 | plt.plot(ox, oy, "xr") 81 | plt.plot(0.0, 0.0, "ob") 82 | plt.pause(1.0) 83 | 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /Mapping/grid_map_lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/Mapping/grid_map_lib/__init__.py -------------------------------------------------------------------------------- /Mapping/rectangle_fitting/__init_.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pathlib 3 | sys.path.append(str(pathlib.Path(__file__).parent)) 4 | -------------------------------------------------------------------------------- /PathPlanning/ClosedLoopRRTStar/unicycle_model.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Unicycle model class 4 | 5 | author Atsushi Sakai 6 | 7 | """ 8 | 9 | import math 10 | import numpy as np 11 | 12 | dt = 0.05 # [s] 13 | L = 0.9 # [m] 14 | steer_max = np.deg2rad(40.0) 15 | curvature_max = math.tan(steer_max) / L 16 | curvature_max = 1.0 / curvature_max + 1.0 17 | 18 | accel_max = 5.0 19 | 20 | 21 | class State: 22 | 23 | def __init__(self, x=0.0, y=0.0, yaw=0.0, v=0.0): 24 | self.x = x 25 | self.y = y 26 | self.yaw = yaw 27 | self.v = v 28 | 29 | 30 | def update(state, a, delta): 31 | 32 | state.x = state.x + state.v * math.cos(state.yaw) * dt 33 | state.y = state.y + state.v * math.sin(state.yaw) * dt 34 | state.yaw = state.yaw + state.v / L * math.tan(delta) * dt 35 | state.yaw = pi_2_pi(state.yaw) 36 | state.v = state.v + a * dt 37 | 38 | return state 39 | 40 | 41 | def pi_2_pi(angle): 42 | return (angle + math.pi) % (2 * math.pi) - math.pi 43 | 44 | 45 | if __name__ == '__main__': # pragma: no cover 46 | print("start unicycle simulation") 47 | import matplotlib.pyplot as plt 48 | 49 | T = 100 50 | a = [1.0] * T 51 | delta = [np.deg2rad(1.0)] * T 52 | # print(delta) 53 | # print(a, delta) 54 | 55 | state = State() 56 | 57 | x = [] 58 | y = [] 59 | yaw = [] 60 | v = [] 61 | 62 | for (ai, di) in zip(a, delta): 63 | state = update(state, ai, di) 64 | 65 | x.append(state.x) 66 | y.append(state.y) 67 | yaw.append(state.yaw) 68 | v.append(state.v) 69 | 70 | plt.subplots(1) 71 | plt.plot(x, y) 72 | plt.axis("equal") 73 | plt.grid(True) 74 | 75 | plt.subplots(1) 76 | plt.plot(v) 77 | plt.grid(True) 78 | 79 | plt.show() 80 | -------------------------------------------------------------------------------- /PathPlanning/CubicSpline/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/CubicSpline/__init__.py -------------------------------------------------------------------------------- /PathPlanning/CubicSpline/spline_continuity.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from scipy import interpolate 5 | 6 | 7 | class Spline2D: 8 | 9 | def __init__(self, x, y, kind="cubic"): 10 | self.s = self.__calc_s(x, y) 11 | self.sx = interpolate.interp1d(self.s, x, kind=kind) 12 | self.sy = interpolate.interp1d(self.s, y, kind=kind) 13 | 14 | def __calc_s(self, x, y): 15 | self.ds = np.hypot(np.diff(x), np.diff(y)) 16 | s = [0.0] 17 | s.extend(np.cumsum(self.ds)) 18 | return s 19 | 20 | def calc_position(self, s): 21 | x = self.sx(s) 22 | y = self.sy(s) 23 | return x, y 24 | 25 | 26 | def main(): 27 | x = [-2.5, 0.0, 2.5, 5.0, 7.5, 3.0, -1.0] 28 | y = [0.7, -6, -5, -3.5, 0.0, 5.0, -2.0] 29 | ds = 0.1 # [m] distance of each interpolated points 30 | 31 | plt.subplots(1) 32 | plt.plot(x, y, "xb", label="Data points") 33 | 34 | for (kind, label) in [("linear", "C0 (Linear spline)"), 35 | ("quadratic", "C0 & C1 (Quadratic spline)"), 36 | ("cubic", "C0 & C1 & C2 (Cubic spline)")]: 37 | rx, ry = [], [] 38 | sp = Spline2D(x, y, kind=kind) 39 | s = np.arange(0, sp.s[-1], ds) 40 | for i_s in s: 41 | ix, iy = sp.calc_position(i_s) 42 | rx.append(ix) 43 | ry.append(iy) 44 | plt.plot(rx, ry, "-", label=label) 45 | 46 | plt.grid(True) 47 | plt.axis("equal") 48 | plt.xlabel("x[m]") 49 | plt.ylabel("y[m]") 50 | plt.legend() 51 | plt.show() 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /PathPlanning/DubinsPath/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/DubinsPath/__init__.py -------------------------------------------------------------------------------- /PathPlanning/HybridAStar/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | sys.path.append(os.path.dirname(os.path.abspath(__file__))) 5 | -------------------------------------------------------------------------------- /PathPlanning/HybridAStar/car.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Car model for Hybrid A* path planning 4 | 5 | author: Zheng Zh (@Zhengzh) 6 | 7 | """ 8 | 9 | import sys 10 | import pathlib 11 | root_dir = pathlib.Path(__file__).parent.parent.parent 12 | sys.path.append(str(root_dir)) 13 | 14 | from math import cos, sin, tan, pi 15 | 16 | import matplotlib.pyplot as plt 17 | import numpy as np 18 | 19 | from utils.angle import rot_mat_2d 20 | 21 | WB = 3.0 # rear to front wheel 22 | W = 2.0 # width of car 23 | LF = 3.3 # distance from rear to vehicle front end 24 | LB = 1.0 # distance from rear to vehicle back end 25 | MAX_STEER = pi/5 # [rad] maximum steering angle 26 | 27 | BUBBLE_DIST = (LF - LB) / 2.0 # distance from rear to center of vehicle. 28 | BUBBLE_R = np.hypot((LF + LB) / 2.0, W / 2.0) # bubble radius 29 | 30 | # vehicle rectangle vertices 31 | VRX = [LF, LF, -LB, -LB, LF] 32 | VRY = [W / 2, -W / 2, -W / 2, W / 2, W / 2] 33 | 34 | 35 | def check_car_collision(x_list, y_list, yaw_list, ox, oy, kd_tree): 36 | for i_x, i_y, i_yaw in zip(x_list, y_list, yaw_list): 37 | cx = i_x + BUBBLE_DIST * cos(i_yaw) 38 | cy = i_y + BUBBLE_DIST * sin(i_yaw) 39 | 40 | ids = kd_tree.query_ball_point([cx, cy], BUBBLE_R) 41 | 42 | if not ids: 43 | continue 44 | 45 | if not rectangle_check(i_x, i_y, i_yaw, 46 | [ox[i] for i in ids], [oy[i] for i in ids]): 47 | return False # collision 48 | 49 | return True # no collision 50 | 51 | 52 | def rectangle_check(x, y, yaw, ox, oy): 53 | # transform obstacles to base link frame 54 | rot = rot_mat_2d(yaw) 55 | for iox, ioy in zip(ox, oy): 56 | tx = iox - x 57 | ty = ioy - y 58 | converted_xy = np.stack([tx, ty]).T @ rot 59 | rx, ry = converted_xy[0], converted_xy[1] 60 | 61 | if not (rx > LF or rx < -LB or ry > W / 2.0 or ry < -W / 2.0): 62 | return False # no collision 63 | 64 | return True # collision 65 | 66 | 67 | def plot_arrow(x, y, yaw, length=1.0, width=0.5, fc="r", ec="k"): 68 | """Plot arrow.""" 69 | if not isinstance(x, float): 70 | for (i_x, i_y, i_yaw) in zip(x, y, yaw): 71 | plot_arrow(i_x, i_y, i_yaw) 72 | else: 73 | plt.arrow(x, y, length * cos(yaw), length * sin(yaw), 74 | fc=fc, ec=ec, head_width=width, head_length=width, alpha=0.4) 75 | 76 | 77 | def plot_car(x, y, yaw): 78 | car_color = '-k' 79 | c, s = cos(yaw), sin(yaw) 80 | rot = rot_mat_2d(-yaw) 81 | car_outline_x, car_outline_y = [], [] 82 | for rx, ry in zip(VRX, VRY): 83 | converted_xy = np.stack([rx, ry]).T @ rot 84 | car_outline_x.append(converted_xy[0]+x) 85 | car_outline_y.append(converted_xy[1]+y) 86 | 87 | arrow_x, arrow_y, arrow_yaw = c * 1.5 + x, s * 1.5 + y, yaw 88 | plot_arrow(arrow_x, arrow_y, arrow_yaw) 89 | 90 | plt.plot(car_outline_x, car_outline_y, car_color) 91 | 92 | 93 | def pi_2_pi(angle): 94 | return (angle + pi) % (2 * pi) - pi 95 | 96 | 97 | def move(x, y, yaw, distance, steer, L=WB): 98 | x += distance * cos(yaw) 99 | y += distance * sin(yaw) 100 | yaw += pi_2_pi(distance * tan(steer) / L) # distance/2 101 | # yaw += pi_2_pi(steer) 102 | 103 | return x, y, yaw 104 | 105 | 106 | def main(): 107 | x, y, yaw = 0., 0., 1. 108 | plt.axis('equal') 109 | plot_car(x, y, yaw) 110 | plt.show() 111 | 112 | 113 | if __name__ == '__main__': 114 | main() 115 | -------------------------------------------------------------------------------- /PathPlanning/HybridAStar/robot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pathlib 3 | root_dir = pathlib.Path(__file__).parent.parent.parent 4 | sys.path.append(str(root_dir)) 5 | 6 | from math import cos, sin, tan, pi 7 | 8 | import matplotlib.pyplot as plt 9 | import numpy as np 10 | 11 | from utils.angle import rot_mat_2d 12 | 13 | R = 1.74 # robot raduis 14 | WD = 1.07*2 # wheel distance 15 | MAX_STEER = pi/4 # [rad] maximum steering angle 16 | 17 | def check_collision(x_list, y_list, kd_tree): 18 | for i_x, i_y in zip(x_list, y_list): 19 | if (kd_tree.query_ball_point([i_x, i_y], R)): 20 | return True # collision 21 | 22 | return False # no collision 23 | 24 | def plot_arrow(x, y, yaw, length=2.0, width=0.5, fc="r", ec="k"): 25 | """Plot arrow.""" 26 | if not isinstance(x, float): 27 | for (i_x, i_y, i_yaw) in zip(x, y, yaw): 28 | plot_arrow(i_x, i_y, i_yaw) 29 | else: 30 | plt.arrow(x, y, length * cos(yaw), length * sin(yaw), 31 | fc=fc, ec=ec, head_width=width, head_length=width, alpha=0.4) 32 | 33 | def plot_robot(x, y, yaw): 34 | color = 'k' 35 | circle = plt.Circle((x, y), R, color=color, fill=False) 36 | plt.gca().add_patch(circle) 37 | plot_arrow(x, y, yaw) 38 | 39 | def pi_2_pi(angle): 40 | return (angle + pi) % (2 * pi) - pi 41 | 42 | def move(x, y, yaw, distance, steer): 43 | x += distance * cos(yaw) 44 | y += distance * sin(yaw) 45 | yaw += pi_2_pi(steer) 46 | 47 | return x, y, yaw 48 | 49 | def main(): 50 | x, y, yaw = 0., 0., 1. 51 | plt.axis('equal') 52 | plot_robot(x, y, yaw) 53 | plt.show() 54 | 55 | if __name__ == '__main__': 56 | main() -------------------------------------------------------------------------------- /PathPlanning/HybridAStar/tempCodeRunnerFile.py: -------------------------------------------------------------------------------- 1 | def calc_motion_inputs(): 2 | for steer in np.concatenate((np.linspace(-MAX_STEER, MAX_STEER, 3 | N_STEER), [0.0])): 4 | for d in [1, -1]: 5 | yield [steer, d] -------------------------------------------------------------------------------- /PathPlanning/HybridAStar/test.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | heap = [10, 33, 13] 4 | 5 | # Insert elements into the heap 6 | heapq.heappush(heap, 4) 7 | heapq.heappush(heap, 5) 8 | heapq.heappush(heap, 3) 9 | heapq.heappush(heap, 2) 10 | heapq.heappush(heap, 1) 11 | 12 | print(heap) 13 | 14 | heapq.heappop(heap) 15 | 16 | print(heap) -------------------------------------------------------------------------------- /PathPlanning/ModelPredictiveTrajectoryGenerator/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/ModelPredictiveTrajectoryGenerator/__init__.py -------------------------------------------------------------------------------- /PathPlanning/ModelPredictiveTrajectoryGenerator/lookup_table_generator.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Lookup Table generation for model predictive trajectory generator 4 | 5 | author: Atsushi Sakai 6 | 7 | """ 8 | import sys 9 | import pathlib 10 | path_planning_dir = pathlib.Path(__file__).parent.parent 11 | sys.path.append(str(path_planning_dir)) 12 | 13 | from matplotlib import pyplot as plt 14 | import numpy as np 15 | import math 16 | 17 | from ModelPredictiveTrajectoryGenerator import trajectory_generator,\ 18 | motion_model 19 | 20 | 21 | def calc_states_list(max_yaw=np.deg2rad(-30.0)): 22 | 23 | x = np.arange(10.0, 30.0, 5.0) 24 | y = np.arange(0.0, 20.0, 2.0) 25 | yaw = np.arange(-max_yaw, max_yaw, max_yaw) 26 | 27 | states = [] 28 | for iyaw in yaw: 29 | for iy in y: 30 | for ix in x: 31 | states.append([ix, iy, iyaw]) 32 | print("n_state:", len(states)) 33 | 34 | return states 35 | 36 | 37 | def search_nearest_one_from_lookup_table(tx, ty, tyaw, lookup_table): 38 | mind = float("inf") 39 | minid = -1 40 | 41 | for (i, table) in enumerate(lookup_table): 42 | 43 | dx = tx - table[0] 44 | dy = ty - table[1] 45 | dyaw = tyaw - table[2] 46 | d = math.sqrt(dx ** 2 + dy ** 2 + dyaw ** 2) 47 | if d <= mind: 48 | minid = i 49 | mind = d 50 | 51 | # print(minid) 52 | 53 | return lookup_table[minid] 54 | 55 | 56 | def save_lookup_table(file_name, table): 57 | np.savetxt(file_name, np.array(table), 58 | fmt='%s', delimiter=",", header="x,y,yaw,s,km,kf", comments="") 59 | 60 | print("lookup table file is saved as " + file_name) 61 | 62 | 63 | def generate_lookup_table(): 64 | states = calc_states_list(max_yaw=np.deg2rad(-30.0)) 65 | k0 = 0.0 66 | 67 | # x, y, yaw, s, km, kf 68 | lookup_table = [[1.0, 0.0, 0.0, 1.0, 0.0, 0.0]] 69 | 70 | for state in states: 71 | best_p = search_nearest_one_from_lookup_table( 72 | state[0], state[1], state[2], lookup_table) 73 | 74 | target = motion_model.State(x=state[0], y=state[1], yaw=state[2]) 75 | init_p = np.array( 76 | [np.hypot(state[0], state[1]), best_p[4], best_p[5]]).reshape(3, 1) 77 | 78 | x, y, yaw, p = trajectory_generator.optimize_trajectory(target, 79 | k0, init_p) 80 | 81 | if x is not None: 82 | print("find good path") 83 | lookup_table.append( 84 | [x[-1], y[-1], yaw[-1], float(p[0]), float(p[1]), float(p[2])]) 85 | 86 | print("finish lookup table generation") 87 | 88 | save_lookup_table("lookup_table.csv", lookup_table) 89 | 90 | for table in lookup_table: 91 | x_c, y_c, yaw_c = motion_model.generate_trajectory( 92 | table[3], table[4], table[5], k0) 93 | plt.plot(x_c, y_c, "-r") 94 | x_c, y_c, yaw_c = motion_model.generate_trajectory( 95 | table[3], -table[4], -table[5], k0) 96 | plt.plot(x_c, y_c, "-r") 97 | 98 | plt.grid(True) 99 | plt.axis("equal") 100 | plt.show() 101 | 102 | print("Done") 103 | 104 | 105 | def main(): 106 | generate_lookup_table() 107 | 108 | 109 | if __name__ == '__main__': 110 | main() 111 | -------------------------------------------------------------------------------- /PathPlanning/ModelPredictiveTrajectoryGenerator/motion_model.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | import scipy.interpolate 4 | 5 | # motion parameter 6 | L = 1.0 # wheel base 7 | ds = 0.1 # course distanse 8 | v = 10.0 / 3.6 # velocity [m/s] 9 | 10 | 11 | class State: 12 | 13 | def __init__(self, x=0.0, y=0.0, yaw=0.0, v=0.0): 14 | self.x = x 15 | self.y = y 16 | self.yaw = yaw 17 | self.v = v 18 | 19 | 20 | def pi_2_pi(angle): 21 | return (angle + math.pi) % (2 * math.pi) - math.pi 22 | 23 | 24 | def update(state, v, delta, dt, L): 25 | 26 | state.v = v 27 | state.x = state.x + state.v * math.cos(state.yaw) * dt 28 | state.y = state.y + state.v * math.sin(state.yaw) * dt 29 | state.yaw = state.yaw + state.v / L * math.tan(delta) * dt 30 | state.yaw = pi_2_pi(state.yaw) 31 | 32 | return state 33 | 34 | 35 | def generate_trajectory(s, km, kf, k0): 36 | 37 | n = s / ds 38 | time = s / v # [s] 39 | 40 | if isinstance(time, type(np.array([]))): time = time[0] 41 | if isinstance(km, type(np.array([]))): km = km[0] 42 | if isinstance(kf, type(np.array([]))): kf = kf[0] 43 | 44 | tk = np.array([0.0, time / 2.0, time]) 45 | kk = np.array([k0, km, kf]) 46 | t = np.arange(0.0, time, time / n) 47 | fkp = scipy.interpolate.interp1d(tk, kk, kind="quadratic") 48 | kp = [fkp(ti) for ti in t] 49 | dt = float(time / n) 50 | 51 | # plt.plot(t, kp) 52 | # plt.show() 53 | 54 | state = State() 55 | x, y, yaw = [state.x], [state.y], [state.yaw] 56 | 57 | for ikp in kp: 58 | state = update(state, v, ikp, dt, L) 59 | x.append(state.x) 60 | y.append(state.y) 61 | yaw.append(state.yaw) 62 | 63 | return x, y, yaw 64 | 65 | 66 | def generate_last_state(s, km, kf, k0): 67 | 68 | n = s / ds 69 | time = s / v # [s] 70 | 71 | if isinstance(time, type(np.array([]))): time = time[0] 72 | if isinstance(km, type(np.array([]))): km = km[0] 73 | if isinstance(kf, type(np.array([]))): kf = kf[0] 74 | 75 | tk = np.array([0.0, time / 2.0, time]) 76 | kk = np.array([k0, km, kf]) 77 | t = np.arange(0.0, time, time / n) 78 | fkp = scipy.interpolate.interp1d(tk, kk, kind="quadratic") 79 | kp = [fkp(ti) for ti in t] 80 | dt = time / n 81 | 82 | # plt.plot(t, kp) 83 | # plt.show() 84 | 85 | state = State() 86 | 87 | _ = [update(state, v, ikp, dt, L) for ikp in kp] 88 | 89 | return state.x, state.y, state.yaw 90 | -------------------------------------------------------------------------------- /PathPlanning/RRT/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/RRT/__init__.py -------------------------------------------------------------------------------- /PathPlanning/RRT/sobol/__init__.py: -------------------------------------------------------------------------------- 1 | from .sobol import i4_sobol as sobol_quasirand 2 | -------------------------------------------------------------------------------- /PathPlanning/RRTDubins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/RRTDubins/__init__.py -------------------------------------------------------------------------------- /PathPlanning/RRTStar/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/RRTStar/__init__.py -------------------------------------------------------------------------------- /PathPlanning/SpiralSpanningTreeCPP/map/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/SpiralSpanningTreeCPP/map/test.png -------------------------------------------------------------------------------- /PathPlanning/SpiralSpanningTreeCPP/map/test_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/SpiralSpanningTreeCPP/map/test_2.png -------------------------------------------------------------------------------- /PathPlanning/SpiralSpanningTreeCPP/map/test_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/SpiralSpanningTreeCPP/map/test_3.png -------------------------------------------------------------------------------- /PathPlanning/StateLatticePlanner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/StateLatticePlanner/__init__.py -------------------------------------------------------------------------------- /PathPlanning/VisibilityRoadMap/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/VisibilityRoadMap/__init__.py -------------------------------------------------------------------------------- /PathPlanning/VisibilityRoadMap/geometry.py: -------------------------------------------------------------------------------- 1 | class Geometry: 2 | 3 | class Point: 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | @staticmethod 9 | def is_seg_intersect(p1, q1, p2, q2): 10 | 11 | def on_segment(p, q, r): 12 | if ((q.x <= max(p.x, r.x)) and (q.x >= min(p.x, r.x)) and 13 | (q.y <= max(p.y, r.y)) and (q.y >= min(p.y, r.y))): 14 | return True 15 | return False 16 | 17 | def orientation(p, q, r): 18 | val = (float(q.y - p.y) * (r.x - q.x)) - ( 19 | float(q.x - p.x) * (r.y - q.y)) 20 | if val > 0: 21 | return 1 22 | if val < 0: 23 | return 2 24 | return 0 25 | 26 | # Find the 4 orientations required for 27 | # the general and special cases 28 | o1 = orientation(p1, q1, p2) 29 | o2 = orientation(p1, q1, q2) 30 | o3 = orientation(p2, q2, p1) 31 | o4 = orientation(p2, q2, q1) 32 | 33 | if (o1 != o2) and (o3 != o4): 34 | return True 35 | if (o1 == 0) and on_segment(p1, p2, q1): 36 | return True 37 | if (o2 == 0) and on_segment(p1, q2, q1): 38 | return True 39 | if (o3 == 0) and on_segment(p2, p1, q2): 40 | return True 41 | if (o4 == 0) and on_segment(p2, q1, q2): 42 | return True 43 | 44 | return False 45 | -------------------------------------------------------------------------------- /PathPlanning/VoronoiRoadMap/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/VoronoiRoadMap/__init__.py -------------------------------------------------------------------------------- /PathPlanning/WavefrontCPP/map/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/WavefrontCPP/map/test.png -------------------------------------------------------------------------------- /PathPlanning/WavefrontCPP/map/test_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/WavefrontCPP/map/test_2.png -------------------------------------------------------------------------------- /PathPlanning/WavefrontCPP/map/test_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/WavefrontCPP/map/test_3.png -------------------------------------------------------------------------------- /PathPlanning/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathPlanning/__init__.py -------------------------------------------------------------------------------- /PathTracking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathTracking/__init__.py -------------------------------------------------------------------------------- /PathTracking/lqr_steer_control/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/PathTracking/lqr_steer_control/__init__.py -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | In this project, we are only support latest code. 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | latest | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | If you find any security related problem, let us know by creating an issue about it. 14 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/data/README.rst: -------------------------------------------------------------------------------- 1 | Acknowledgments and References 2 | ============================== 3 | 4 | Thanks to Luca Larlone for allowing inclusion of the `Intel dataset `_ in this repo. 5 | 6 | 1. Carlone, L. and Censi, A., 2014. `From angular manifolds to the integer lattice: Guaranteed orientation estimation with application to pose graph optimization `_. IEEE Transactions on Robotics, 30(2), pp.475-492. 7 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/graphslam/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Jeff Irion and contributors 2 | # 3 | # This file originated from the `graphslam` package: 4 | # 5 | # https://github.com/JeffLIrion/python-graphslam 6 | 7 | """Graph SLAM solver in Python. 8 | 9 | """ 10 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/graphslam/edge/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Jeff Irion and contributors 2 | # 3 | # This file originated from the `graphslam` package: 4 | # 5 | # https://github.com/JeffLIrion/python-graphslam 6 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/graphslam/load.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Jeff Irion and contributors 2 | # 3 | # This file originated from the `graphslam` package: 4 | # 5 | # https://github.com/JeffLIrion/python-graphslam 6 | 7 | """Functions for loading graphs. 8 | 9 | """ 10 | 11 | import logging 12 | 13 | import numpy as np 14 | 15 | from .edge.edge_odometry import EdgeOdometry 16 | from .graph import Graph 17 | from .pose.se2 import PoseSE2 18 | from .util import upper_triangular_matrix_to_full_matrix 19 | from .vertex import Vertex 20 | 21 | _LOGGER = logging.getLogger(__name__) 22 | 23 | 24 | def load_g2o_se2(infile): 25 | """Load an :math:`SE(2)` graph from a .g2o file. 26 | 27 | Parameters 28 | ---------- 29 | infile : str 30 | The path to the .g2o file 31 | 32 | Returns 33 | ------- 34 | Graph 35 | The loaded graph 36 | 37 | """ 38 | edges = [] 39 | vertices = [] 40 | 41 | with open(infile) as f: 42 | for line in f.readlines(): 43 | if line.startswith("VERTEX_SE2"): 44 | numbers = line[10:].split() 45 | arr = np.array([float(number) for number in numbers[1:]], 46 | dtype=float) 47 | p = PoseSE2(arr[:2], arr[2]) 48 | v = Vertex(int(numbers[0]), p) 49 | vertices.append(v) 50 | continue 51 | 52 | if line.startswith("EDGE_SE2"): 53 | numbers = line[9:].split() 54 | arr = np.array([float(number) for number in numbers[2:]], 55 | dtype=float) 56 | vertex_ids = [int(numbers[0]), int(numbers[1])] 57 | estimate = PoseSE2(arr[:2], arr[2]) 58 | information = upper_triangular_matrix_to_full_matrix(arr[3:], 3) 59 | e = EdgeOdometry(vertex_ids, information, estimate) 60 | edges.append(e) 61 | continue 62 | 63 | if line.strip(): 64 | _LOGGER.warning("Line not supported -- '%s'", line.rstrip()) 65 | 66 | return Graph(edges, vertices) 67 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/graphslam/pose/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Jeff Irion and contributors 2 | # 3 | # This file originated from the `graphslam` package: 4 | # 5 | # https://github.com/JeffLIrion/python-graphslam 6 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/graphslam/util.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Jeff Irion and contributors 2 | # 3 | # This file originated from the `graphslam` package: 4 | # 5 | # https://github.com/JeffLIrion/python-graphslam 6 | 7 | """Utility functions used throughout the package. 8 | 9 | """ 10 | 11 | import numpy as np 12 | 13 | 14 | TWO_PI = 2 * np.pi 15 | 16 | 17 | def neg_pi_to_pi(angle): 18 | r"""Normalize ``angle`` to be in :math:`[-\pi, \pi)`. 19 | 20 | Parameters 21 | ---------- 22 | angle : float 23 | An angle (in radians) 24 | 25 | Returns 26 | ------- 27 | float 28 | The angle normalized to :math:`[-\pi, \pi)` 29 | 30 | """ 31 | return (angle + np.pi) % (TWO_PI) - np.pi 32 | 33 | 34 | def solve_for_edge_dimensionality(n): 35 | r"""Solve for the dimensionality of an edge. 36 | 37 | In a .g2o file, an edge is specified as `` ``, where only the upper triangular portion of the matrix is provided. 38 | 39 | This solves the problem: 40 | 41 | .. math:: 42 | 43 | d + \frac{d (d + 1)}{2} = n 44 | 45 | Returns 46 | ------- 47 | int 48 | The dimensionality of the edge 49 | 50 | """ 51 | return int(round(np.sqrt(2 * n + 2.25) - 1.5)) 52 | 53 | 54 | def upper_triangular_matrix_to_full_matrix(arr, n): 55 | """Given an upper triangular matrix, return the full matrix. 56 | 57 | Parameters 58 | ---------- 59 | arr : np.ndarray 60 | The upper triangular portion of the matrix 61 | n : int 62 | The size of the matrix 63 | 64 | Returns 65 | ------- 66 | mat : np.ndarray 67 | The full matrix 68 | 69 | """ 70 | triu0 = np.triu_indices(n, 0) 71 | tril1 = np.tril_indices(n, -1) 72 | 73 | mat = np.zeros((n, n), dtype=float) 74 | mat[triu0] = arr 75 | mat[tril1] = mat.T[tril1] 76 | 77 | return mat 78 | -------------------------------------------------------------------------------- /SLAM/GraphBasedSLAM/graphslam/vertex.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Jeff Irion and contributors 2 | # 3 | # This file originated from the `graphslam` package: 4 | # 5 | # https://github.com/JeffLIrion/python-graphslam 6 | 7 | """A ``Vertex`` class. 8 | 9 | """ 10 | 11 | import matplotlib.pyplot as plt 12 | 13 | 14 | # pylint: disable=too-few-public-methods 15 | class Vertex: 16 | """A class for representing a vertex in Graph SLAM. 17 | 18 | Parameters 19 | ---------- 20 | vertex_id : int 21 | The vertex's unique ID 22 | pose : graphslam.pose.se2.PoseSE2 23 | The pose associated with the vertex 24 | vertex_index : int, None 25 | The vertex's index in the graph's ``vertices`` list 26 | 27 | Attributes 28 | ---------- 29 | id : int 30 | The vertex's unique ID 31 | index : int, None 32 | The vertex's index in the graph's ``vertices`` list 33 | pose : graphslam.pose.se2.PoseSE2 34 | The pose associated with the vertex 35 | 36 | """ 37 | def __init__(self, vertex_id, pose, vertex_index=None): 38 | self.id = vertex_id 39 | self.pose = pose 40 | self.index = vertex_index 41 | 42 | def to_g2o(self): 43 | """Export the vertex to the .g2o format. 44 | 45 | Returns 46 | ------- 47 | str 48 | The vertex in .g2o format 49 | 50 | """ 51 | return "VERTEX_SE2 {} {} {} {}\n".format(self.id, self.pose[0], self.pose[1], self.pose[2]) 52 | 53 | def plot(self, color='r', marker='o', markersize=3): 54 | """Plot the vertex. 55 | 56 | Parameters 57 | ---------- 58 | color : str 59 | The color that will be used to plot the vertex 60 | marker : str 61 | The marker that will be used to plot the vertex 62 | markersize : int 63 | The size of the plotted vertex 64 | 65 | """ 66 | x, y = self.pose.position 67 | plt.plot(x, y, color=color, marker=marker, markersize=markersize) 68 | -------------------------------------------------------------------------------- /SLAM/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/SLAM/__init__.py -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/__init__.py -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate 2 | show_downloads: true 3 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2022 2 | 3 | environment: 4 | global: 5 | # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the 6 | # /E:ON and /V:ON options are not enabled in the batch script intepreter 7 | # See: http://stackoverflow.com/a/13751649/163740 8 | CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd" 9 | 10 | matrix: 11 | - PYTHON_DIR: C:\Python310-x64 12 | 13 | branches: 14 | only: 15 | - master 16 | 17 | init: 18 | - "ECHO %PYTHON_DIR%" 19 | 20 | install: 21 | # If there is a newer build queued for the same PR, cancel this one. 22 | # The AppVeyor 'rollout builds' option is supposed to serve the same 23 | # purpose but it is problematic because it tends to cancel builds pushed 24 | # directly to master instead of just PR builds (or the converse). 25 | # credits: JuliaLang developers. 26 | - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` 27 | https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` 28 | Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` 29 | throw "There are newer queued builds for this pull request, failing early." } 30 | - ECHO "Filesystem root:" 31 | - ps: "ls \"C:/\"" 32 | 33 | # Prepend newly installed Python to the PATH of this build (this cannot be 34 | # done from inside the powershell script as it would require to restart 35 | # the parent CMD process). 36 | - SET PATH=%PYTHON_DIR%;%PYTHON_DIR%\\Scripts;%PATH% 37 | - SET PATH=%PYTHON%;%PYTHON%\Scripts;%PYTHON%\Library\bin;%PATH% 38 | - SET PATH=%PATH%;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin 39 | - "python -m pip install --upgrade pip" 40 | - "python -m pip install -r requirements/requirements.txt" 41 | - "python -m pip install pytest-xdist" 42 | 43 | # Check that we have the expected version and architecture for Python 44 | - "python --version" 45 | - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" 46 | 47 | build: off 48 | 49 | test_script: 50 | - "pytest tests -n auto -Werror --durations=0" 51 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = PythonRobotics 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## Python Robotics Documentation 2 | 3 | This folder contains documentation for the Python Robotics project. 4 | 5 | 6 | ### Build the Documentation 7 | 8 | #### Install Sphinx and Theme 9 | 10 | ``` 11 | pip install sphinx sphinx-autobuild sphinx-rtd-theme 12 | ``` 13 | 14 | #### Building the Docs 15 | 16 | In the `docs/` folder: 17 | ``` 18 | make html 19 | ``` 20 | 21 | if you want to building each time a file is changed: 22 | 23 | ``` 24 | sphinx-autobuild . _build/html 25 | ``` 26 | 27 | #### Check the generated doc 28 | 29 | Open the index.html file under docs/_build/ 30 | -------------------------------------------------------------------------------- /docs/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/_static/.gitkeep -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Necessary parts from 3 | * Sphinx stylesheet -- basic theme 4 | * absent from sphinx_rtd_theme 5 | * (see https://github.com/readthedocs/sphinx_rtd_theme/issues/301) 6 | * Ref https://github.com/PyAbel/PyAbel/commit/7e4dee81eac3f0a6955a85a4a42cf04a4e0d995c 7 | */ 8 | 9 | /* -- math display ---------------------------------------------------------- */ 10 | 11 | span.eqno { 12 | float: right; 13 | } 14 | 15 | span.eqno a.headerlink { 16 | position: absolute; 17 | z-index: 1; 18 | visibility: hidden; 19 | } 20 | 21 | div.math:hover a.headerlink { 22 | visibility: visible; 23 | } 24 | -------------------------------------------------------------------------------- /docs/_static/img/doc_ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/_static/img/doc_ci.png -------------------------------------------------------------------------------- /docs/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {% block sidebartitle %} 4 | {{ super() }} 5 | 7 | 8 | 14 | 17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /docs/doc_requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx == 4.3.2 # For sphinx documentation 2 | sphinx_rtd_theme == 1.0.0 3 | IPython == 7.31.1 # For sphinx documentation 4 | sphinxcontrib-napoleon == 0.7 # For auto doc 5 | -------------------------------------------------------------------------------- /docs/getting_started_main.rst: -------------------------------------------------------------------------------- 1 | .. _`getting started`: 2 | 3 | Getting Started 4 | =============== 5 | 6 | What is this? 7 | ------------- 8 | 9 | This is an Open Source Software (OSS) project: PythonRobotics, which is a Python code collection of robotics algorithms. 10 | 11 | The focus of the project is on autonomous navigation, and the goal is for beginners in robotics to understand the basic ideas behind each algorithm. 12 | 13 | In this project, the algorithms which are practical and widely used in both academia and industry are selected. 14 | 15 | Each sample code is written in Python3 and only depends on some standard modules for readability and ease of use. 16 | 17 | It includes intuitive animations to understand the behavior of the simulation. 18 | 19 | 20 | See this paper for more details: 21 | 22 | - PythonRobotics: a Python code collection of robotics algorithms: https://arxiv.org/abs/1808.10703 23 | 24 | .. _`Requirements`: 25 | 26 | Requirements 27 | ------------- 28 | 29 | - `Python 3.10.x`_ 30 | - `NumPy`_ 31 | - `SciPy`_ 32 | - `Matplotlib`_ 33 | - `cvxpy`_ 34 | 35 | For development: 36 | 37 | - pytest (for unit tests) 38 | - pytest-xdist (for parallel unit tests) 39 | - mypy (for type check) 40 | - sphinx (for document generation) 41 | - pycodestyle (for code style check) 42 | 43 | .. _`Python 3.10.x`: https://www.python.org/ 44 | .. _`NumPy`: https://numpy.org/ 45 | .. _`SciPy`: https://scipy.org/ 46 | .. _`Matplotlib`: https://matplotlib.org/ 47 | .. _`cvxpy`: https://www.cvxpy.org/ 48 | 49 | 50 | How to use 51 | ---------- 52 | 53 | 1. Clone this repo and go into dir. 54 | 55 | .. code-block:: 56 | 57 | >$ git clone https://github.com/AtsushiSakai/PythonRobotics.git 58 | 59 | >$ cd PythonRobotics 60 | 61 | 62 | 2. Install the required libraries. 63 | 64 | using conda : 65 | 66 | .. code-block:: 67 | 68 | >$ conda env create -f requirements/environment.yml 69 | 70 | using pip : 71 | 72 | .. code-block:: 73 | 74 | >$ pip install -r requirements/requirements.txt 75 | 76 | 77 | 3. Execute python script in each directory. 78 | 79 | 4. Add star to this repo if you like it 😃. 80 | 81 | -------------------------------------------------------------------------------- /docs/index_main.rst: -------------------------------------------------------------------------------- 1 | .. PythonRobotics documentation master file, created by 2 | sphinx-quickstart on Sat Sep 15 13:15:55 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to PythonRobotics's documentation! 7 | ========================================== 8 | 9 | Python codes for robotics algorithm. The project is on `GitHub`_. 10 | 11 | This is a Python code collection of robotics algorithms. 12 | 13 | Features: 14 | 15 | 1. Easy to read for understanding each algorithm's basic idea. 16 | 17 | 2. Widely used and practical algorithms are selected. 18 | 19 | 3. Minimum dependency. 20 | 21 | See this paper for more details: 22 | 23 | - `[1808.10703] PythonRobotics: a Python code collection of robotics 24 | algorithms`_ (`BibTeX`_) 25 | 26 | 27 | .. _`[1808.10703] PythonRobotics: a Python code collection of robotics algorithms`: https://arxiv.org/abs/1808.10703 28 | .. _BibTeX: https://github.com/AtsushiSakai/PythonRoboticsPaper/blob/master/python_robotics.bib 29 | .. _GitHub: https://github.com/AtsushiSakai/PythonRobotics 30 | 31 | 32 | .. toctree:: 33 | :maxdepth: 2 34 | :caption: Contents 35 | 36 | getting_started 37 | modules/introduction 38 | modules/localization/localization 39 | modules/mapping/mapping 40 | modules/slam/slam 41 | modules/path_planning/path_planning 42 | modules/path_tracking/path_tracking 43 | modules/arm_navigation/arm_navigation 44 | modules/aerial_navigation/aerial_navigation 45 | modules/bipedal/bipedal 46 | modules/control/control 47 | modules/utils/utils 48 | modules/appendix/appendix 49 | how_to_contribute 50 | 51 | 52 | Indices and tables 53 | ================== 54 | 55 | * :ref:`genindex` 56 | * :ref:`modindex` 57 | * :ref:`search` 58 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=PythonRobotics 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/modules/aerial_navigation/aerial_navigation_main.rst: -------------------------------------------------------------------------------- 1 | .. _aerial_navigation: 2 | 3 | Aerial Navigation 4 | ================= 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | drone_3d_trajectory_following/drone_3d_trajectory_following 11 | rocket_powered_landing/rocket_powered_landing 12 | 13 | -------------------------------------------------------------------------------- /docs/modules/aerial_navigation/drone_3d_trajectory_following/drone_3d_trajectory_following_main.rst: -------------------------------------------------------------------------------- 1 | Drone 3d trajectory following 2 | ----------------------------- 3 | 4 | This is a 3d trajectory following simulation for a quadrotor. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/AerialNavigation/drone_3d_trajectory_following/animation.gif 7 | -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_2_files/Kalmanfilter_basics_2_5_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_2_files/Kalmanfilter_basics_2_5_0.png -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_14_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_14_1.png -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_16_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_16_0.png -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_19_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_19_1.png -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_21_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_21_1.png -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_22_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_22_0.png -------------------------------------------------------------------------------- /docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_28_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/appendix/Kalmanfilter_basics_files/Kalmanfilter_basics_28_1.png -------------------------------------------------------------------------------- /docs/modules/appendix/appendix_main.rst: -------------------------------------------------------------------------------- 1 | .. _appendix: 2 | 3 | Appendix 4 | ============== 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | Kalmanfilter_basics 11 | Kalmanfilter_basics_2 12 | 13 | -------------------------------------------------------------------------------- /docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_12_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_12_0.png -------------------------------------------------------------------------------- /docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_5_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_5_0.png -------------------------------------------------------------------------------- /docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_7_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_7_0.png -------------------------------------------------------------------------------- /docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_9_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/arm_navigation/Planar_Two_Link_IK_files/Planar_Two_Link_IK_9_0.png -------------------------------------------------------------------------------- /docs/modules/arm_navigation/arm_navigation_main.rst: -------------------------------------------------------------------------------- 1 | .. _arm_navigation: 2 | 3 | Arm Navigation 4 | ============== 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | planar_two_link_ik 11 | n_joint_arm_to_point_control 12 | obstacle_avoidance_arm_navigation 13 | -------------------------------------------------------------------------------- /docs/modules/arm_navigation/n_joint_arm_to_point_control_main.rst: -------------------------------------------------------------------------------- 1 | N joint arm to point control 2 | ---------------------------- 3 | 4 | N joint arm to a point control simulation. 5 | 6 | This is a interactive simulation. 7 | 8 | You can set the goal position of the end effector with left-click on the 9 | plotting area. 10 | 11 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/ArmNavigation/n_joint_arm_to_point_control/animation.gif 12 | 13 | In this simulation N = 10, however, you can change it. 14 | -------------------------------------------------------------------------------- /docs/modules/arm_navigation/obstacle_avoidance_arm_navigation_main.rst: -------------------------------------------------------------------------------- 1 | Arm navigation with obstacle avoidance 2 | -------------------------------------- 3 | 4 | Arm navigation with obstacle avoidance simulation. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/ArmNavigation/arm_obstacle_navigation/animation.gif -------------------------------------------------------------------------------- /docs/modules/bipedal/bipedal_main.rst: -------------------------------------------------------------------------------- 1 | .. _bipedal: 2 | 3 | Bipedal 4 | ================= 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | bipedal_planner/bipedal_planner 11 | 12 | -------------------------------------------------------------------------------- /docs/modules/bipedal/bipedal_planner/bipedal_planner_main.rst: -------------------------------------------------------------------------------- 1 | Bipedal Planner 2 | ----------------------------- 3 | 4 | Bipedal Walking with modifying designated footsteps 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Bipedal/bipedal_planner/animation.gif 7 | -------------------------------------------------------------------------------- /docs/modules/control/control_main.rst: -------------------------------------------------------------------------------- 1 | .. _control: 2 | 3 | Control 4 | ================= 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | inverted_pendulum_control/inverted_pendulum_control 11 | move_to_a_pose_control/move_to_a_pose_control 12 | 13 | -------------------------------------------------------------------------------- /docs/modules/control/inverted_pendulum_control/inverted-pendulum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/control/inverted_pendulum_control/inverted-pendulum.png -------------------------------------------------------------------------------- /docs/modules/control/inverted_pendulum_control/inverted_pendulum_control_main.rst: -------------------------------------------------------------------------------- 1 | Inverted Pendulum Control 2 | ----------------------------- 3 | 4 | An inverted pendulum on a cart consists of a mass :math:`m` at the top of a pole of length :math:`l` pivoted on a 5 | horizontally moving base as shown in the adjacent. 6 | 7 | The objective of the control system is to balance the inverted pendulum by applying a force to the cart that the pendulum is attached to. 8 | 9 | Modeling 10 | ~~~~~~~~~~~~ 11 | 12 | .. image:: inverted-pendulum.png 13 | :align: center 14 | 15 | - :math:`M`: mass of the cart 16 | - :math:`m`: mass of the load on the top of the rod 17 | - :math:`l`: length of the rod 18 | - :math:`u`: force applied to the cart 19 | - :math:`x`: cart position coordinate 20 | - :math:`\theta`: pendulum angle from vertical 21 | 22 | Using Lagrange's equations: 23 | 24 | .. math:: 25 | & (M + m)\ddot{x} - ml\ddot{\theta}cos{\theta} + ml\dot{\theta^2}\sin{\theta} = u \\ 26 | & l\ddot{\theta} - g\sin{\theta} = \ddot{x}\cos{\theta} 27 | 28 | See this `link `__ for more details. 29 | 30 | So 31 | 32 | .. math:: 33 | & \ddot{x} = \frac{m(gcos{\theta} - \dot{\theta}^2l)sin{\theta} + u}{M + m - mcos^2{\theta}} \\ 34 | & \ddot{\theta} = \frac{g(M + m)sin{\theta} - \dot{\theta}^2lmsin{\theta}cos{\theta} + ucos{\theta}}{l(M + m - mcos^2{\theta})} 35 | 36 | 37 | Linearized model when :math:`\theta` small, :math:`cos{\theta} \approx 1`, :math:`sin{\theta} \approx \theta`, :math:`\dot{\theta}^2 \approx 0`. 38 | 39 | .. math:: 40 | & \ddot{x} = \frac{gm}{M}\theta + \frac{1}{M}u\\ 41 | & \ddot{\theta} = \frac{g(M + m)}{Ml}\theta + \frac{1}{Ml}u 42 | 43 | State space: 44 | 45 | .. math:: 46 | & \dot{x} = Ax + Bu \\ 47 | & y = Cx + Du 48 | 49 | where 50 | 51 | .. math:: 52 | & x = [x, \dot{x}, \theta,\dot{\theta}]\\ 53 | & A = \begin{bmatrix} 0 & 1 & 0 & 0\\0 & 0 & \frac{gm}{M} & 0\\0 & 0 & 0 & 1\\0 & 0 & \frac{g(M + m)}{Ml} & 0 \end{bmatrix}\\ 54 | & B = \begin{bmatrix} 0 \\ \frac{1}{M} \\ 0 \\ \frac{1}{Ml} \end{bmatrix} 55 | 56 | If control only \theta 57 | 58 | .. math:: 59 | & C = \begin{bmatrix} 0 & 0 & 1 & 0 \end{bmatrix}\\ 60 | & D = [0] 61 | 62 | If control x and \theta 63 | 64 | .. math:: 65 | & C = \begin{bmatrix} 1 & 0 & 0 & 0\\0 & 0 & 1 & 0 \end{bmatrix}\\ 66 | & D = \begin{bmatrix} 0 \\ 0 \end{bmatrix} 67 | 68 | LQR control 69 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | 71 | The LQR controller minimize this cost function defined as: 72 | 73 | .. math:: J = x^T Q x + u^T R u 74 | 75 | the feedback control law that minimizes the value of the cost is: 76 | 77 | .. math:: u = -K x 78 | 79 | where: 80 | 81 | .. math:: K = (B^T P B + R)^{-1} B^T P A 82 | 83 | and :math:`P` is the unique positive definite solution to the discrete time 84 | `algebraic Riccati equation `__ (DARE): 85 | 86 | .. math:: P = A^T P A - A^T P B ( R + B^T P B )^{-1} B^T P A + Q 87 | 88 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Control/InvertedPendulumCart/animation_lqr.gif 89 | 90 | MPC control 91 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 | The MPC controller minimize this cost function defined as: 93 | 94 | .. math:: J = x^T Q x + u^T R u 95 | 96 | subject to: 97 | 98 | - Linearized Inverted Pendulum model 99 | - Initial state 100 | 101 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Control/InvertedPendulumCart/animation.gif 102 | -------------------------------------------------------------------------------- /docs/modules/introduction_main.rst: -------------------------------------------------------------------------------- 1 | 2 | Introduction 3 | ============ 4 | 5 | TBD 6 | 7 | Definition Of Robotics 8 | ---------------------- 9 | 10 | TBD 11 | 12 | History Of Robotics 13 | ---------------------- 14 | 15 | TBD 16 | 17 | Application Of Robotics 18 | ------------------------ 19 | 20 | TBD 21 | 22 | Software for Robotics 23 | ---------------------- 24 | 25 | TBD 26 | 27 | Software for Robotics 28 | ---------------------- 29 | 30 | TBD 31 | 32 | Python for Robotics 33 | ---------------------- 34 | 35 | TBD 36 | 37 | Learning Robotics Algorithms 38 | ---------------------------- 39 | 40 | TBD 41 | 42 | 43 | -------------------------------------------------------------------------------- /docs/modules/localization/ensamble_kalman_filter_localization_files/ensamble_kalman_filter_localization_main.rst: -------------------------------------------------------------------------------- 1 | Ensamble Kalman Filter Localization 2 | ----------------------------------- 3 | 4 | .. figure:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Localization/ensamble_kalman_filter/animation.gif 5 | 6 | This is a sensor fusion localization with Ensamble Kalman Filter(EnKF). 7 | 8 | -------------------------------------------------------------------------------- /docs/modules/localization/extended_kalman_filter_localization_files/extended_kalman_filter_localization_1_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/localization/extended_kalman_filter_localization_files/extended_kalman_filter_localization_1_0.png -------------------------------------------------------------------------------- /docs/modules/localization/histogram_filter_localization/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/localization/histogram_filter_localization/1.png -------------------------------------------------------------------------------- /docs/modules/localization/histogram_filter_localization/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/localization/histogram_filter_localization/2.png -------------------------------------------------------------------------------- /docs/modules/localization/histogram_filter_localization/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/localization/histogram_filter_localization/3.png -------------------------------------------------------------------------------- /docs/modules/localization/histogram_filter_localization/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/localization/histogram_filter_localization/4.png -------------------------------------------------------------------------------- /docs/modules/localization/localization_main.rst: -------------------------------------------------------------------------------- 1 | .. _localization: 2 | 3 | Localization 4 | ============ 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | extended_kalman_filter_localization_files/extended_kalman_filter_localization 11 | ensamble_kalman_filter_localization_files/ensamble_kalman_filter_localization 12 | unscented_kalman_filter_localization/unscented_kalman_filter_localization 13 | histogram_filter_localization/histogram_filter_localization 14 | particle_filter_localization/particle_filter_localization 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/modules/localization/particle_filter_localization/particle_filter_localization_main.rst: -------------------------------------------------------------------------------- 1 | Particle filter localization 2 | ---------------------------- 3 | 4 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Localization/particle_filter/animation.gif 5 | 6 | This is a sensor fusion localization with Particle Filter(PF). 7 | 8 | The blue line is true trajectory, the black line is dead reckoning 9 | trajectory, 10 | 11 | and the red line is estimated trajectory with PF. 12 | 13 | It is assumed that the robot can measure a distance from landmarks 14 | (RFID). 15 | 16 | This measurements are used for PF localization. 17 | 18 | How to calculate covariance matrix from particles 19 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 | 21 | The covariance matrix :math:`\Xi` from particle information is calculated by the following equation: 22 | 23 | .. math:: \Xi_{j,k}=\frac{1}{1-\sum^N_{i=1}(w^i)^2}\sum^N_{i=1}w^i(x^i_j-\mu_j)(x^i_k-\mu_k) 24 | 25 | - :math:`\Xi_{j,k}` is covariance matrix element at row :math:`i` and column :math:`k`. 26 | 27 | - :math:`w^i` is the weight of the :math:`i` th particle. 28 | 29 | - :math:`x^i_j` is the :math:`j` th state of the :math:`i` th particle. 30 | 31 | - :math:`\mu_j` is the :math:`j` th mean state of particles. 32 | 33 | References: 34 | ~~~~~~~~~~~ 35 | 36 | - `_PROBABILISTIC ROBOTICS: `_ 37 | - `Improving the particle filter in high dimensions using conjugate artificial process noise `_ 38 | -------------------------------------------------------------------------------- /docs/modules/localization/unscented_kalman_filter_localization/unscented_kalman_filter_localization_main.rst: -------------------------------------------------------------------------------- 1 | Unscented Kalman Filter localization 2 | ------------------------------------ 3 | 4 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Localization/unscented_kalman_filter/animation.gif 5 | 6 | This is a sensor fusion localization with Unscented Kalman Filter(UKF). 7 | 8 | The lines and points are same meaning of the EKF simulation. 9 | 10 | References: 11 | ~~~~~~~~~~~ 12 | 13 | - `Discriminatively Trained Unscented Kalman Filter for Mobile Robot Localization `_ 14 | -------------------------------------------------------------------------------- /docs/modules/mapping/circle_fitting/circle_fitting_main.rst: -------------------------------------------------------------------------------- 1 | Object shape recognition using circle fitting 2 | --------------------------------------------- 3 | 4 | This is an object shape recognition using circle fitting. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Mapping/circle_fitting/animation.gif 7 | 8 | The blue circle is the true object shape. 9 | 10 | The red crosses are observations from a ranging sensor. 11 | 12 | The red circle is the estimated object shape using circle fitting. 13 | 14 | -------------------------------------------------------------------------------- /docs/modules/mapping/gaussian_grid_map/gaussian_grid_map_main.rst: -------------------------------------------------------------------------------- 1 | .. _gaussian_grid_map: 2 | 3 | Gaussian grid map 4 | ----------------- 5 | 6 | This is a 2D Gaussian grid mapping example. 7 | 8 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Mapping/gaussian_grid_map/animation.gif 9 | -------------------------------------------------------------------------------- /docs/modules/mapping/k_means_object_clustering/k_means_object_clustering_main.rst: -------------------------------------------------------------------------------- 1 | k-means object clustering 2 | ------------------------- 3 | 4 | This is a 2D object clustering with k-means algorithm. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Mapping/kmeans_clustering/animation.gif 7 | -------------------------------------------------------------------------------- /docs/modules/mapping/lidar_to_grid_map_tutorial/grid_map_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/mapping/lidar_to_grid_map_tutorial/grid_map_example.png -------------------------------------------------------------------------------- /docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_12_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_12_0.png -------------------------------------------------------------------------------- /docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_14_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_14_1.png -------------------------------------------------------------------------------- /docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_5_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_5_0.png -------------------------------------------------------------------------------- /docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_7_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_7_0.png -------------------------------------------------------------------------------- /docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_8_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/mapping/lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial_8_0.png -------------------------------------------------------------------------------- /docs/modules/mapping/mapping_main.rst: -------------------------------------------------------------------------------- 1 | .. _mapping: 2 | 3 | Mapping 4 | ======= 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: Contents 8 | 9 | gaussian_grid_map/gaussian_grid_map 10 | ray_casting_grid_map/ray_casting_grid_map 11 | lidar_to_grid_map_tutorial/lidar_to_grid_map_tutorial 12 | k_means_object_clustering/k_means_object_clustering 13 | circle_fitting/circle_fitting 14 | rectangle_fitting/rectangle_fitting 15 | 16 | -------------------------------------------------------------------------------- /docs/modules/mapping/ray_casting_grid_map/ray_casting_grid_map_main.rst: -------------------------------------------------------------------------------- 1 | Ray casting grid map 2 | -------------------- 3 | 4 | This is a 2D ray casting grid mapping example. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Mapping/raycasting_grid_map/animation.gif -------------------------------------------------------------------------------- /docs/modules/mapping/rectangle_fitting/rectangle_fitting_main.rst: -------------------------------------------------------------------------------- 1 | Object shape recognition using rectangle fitting 2 | ------------------------------------------------ 3 | 4 | This is an object shape recognition using rectangle fitting. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/Mapping/rectangle_fitting/animation.gif 7 | 8 | -------------------------------------------------------------------------------- /docs/modules/path_planning/bezier_path/Figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bezier_path/Figure_1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bezier_path/Figure_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bezier_path/Figure_2.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bezier_path/bezier_path_main.rst: -------------------------------------------------------------------------------- 1 | Bezier path planning 2 | -------------------- 3 | 4 | A sample code of Bezier path planning. 5 | 6 | It is based on 4 control points Beizer path. 7 | 8 | .. image:: Figure_1.png 9 | 10 | If you change the offset distance from start and end point, 11 | 12 | You can get different Beizer course: 13 | 14 | .. image:: Figure_2.png 15 | 16 | Ref: 17 | 18 | - `Continuous Curvature Path Generation Based on Bezier Curves for 19 | Autonomous 20 | Vehicles `__ 21 | -------------------------------------------------------------------------------- /docs/modules/path_planning/bspline_path/approx_and_curvature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bspline_path/approx_and_curvature.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bspline_path/approximation1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bspline_path/approximation1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bspline_path/basis_functions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bspline_path/basis_functions.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bspline_path/bspline_path_planning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bspline_path/bspline_path_planning.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bspline_path/interp_and_curvature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bspline_path/interp_and_curvature.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bspline_path/interpolation1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/bspline_path/interpolation1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/bugplanner/bugplanner_main.rst: -------------------------------------------------------------------------------- 1 | Bug planner 2 | ----------- 3 | 4 | This is a 2D planning with Bug algorithm. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/BugPlanner/animation.gif 7 | 8 | - `ECE452 Bug Algorithms `_ 9 | -------------------------------------------------------------------------------- /docs/modules/path_planning/closed_loop_rrt_star_car/Figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/closed_loop_rrt_star_car/Figure_1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/closed_loop_rrt_star_car/Figure_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/closed_loop_rrt_star_car/Figure_3.png -------------------------------------------------------------------------------- /docs/modules/path_planning/closed_loop_rrt_star_car/Figure_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/closed_loop_rrt_star_car/Figure_4.png -------------------------------------------------------------------------------- /docs/modules/path_planning/closed_loop_rrt_star_car/Figure_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/closed_loop_rrt_star_car/Figure_5.png -------------------------------------------------------------------------------- /docs/modules/path_planning/clothoid_path/clothoid_path_main.rst: -------------------------------------------------------------------------------- 1 | .. _clothoid-path-planning: 2 | 3 | Clothoid path planning 4 | -------------------------- 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ClothoidPath/animation1.gif 7 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ClothoidPath/animation2.gif 8 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ClothoidPath/animation3.gif 9 | 10 | This is a clothoid path planning sample code. 11 | 12 | This can interpolate two 2D pose (x, y, yaw) with a clothoid path, 13 | which its curvature is linearly continuous. 14 | In other words, this is G1 Hermite interpolation with a single clothoid segment. 15 | 16 | This path planning algorithm as follows: 17 | 18 | Step1: Solve g function 19 | ~~~~~~~~~~~~~~~~~~~~~~~ 20 | 21 | Solve the g(A) function with a nonlinear optimization solver. 22 | 23 | .. math:: 24 | 25 | g(A):=Y(2A, \delta-A, \phi_{s}) 26 | 27 | Where 28 | 29 | * :math:`\delta`: the orientation difference between start and goal pose. 30 | * :math:`\phi_{s}`: the orientation of the start pose. 31 | * :math:`Y`: :math:`Y(a, b, c)=\int_{0}^{1} \sin \left(\frac{a}{2} \tau^{2}+b \tau+c\right) d \tau` 32 | 33 | 34 | Step2: Calculate path parameters 35 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 | 37 | We can calculate these path parameters using :math:`A`, 38 | 39 | :math:`L`: path length 40 | 41 | .. math:: 42 | 43 | L=\frac{R}{X\left(2 A, \delta-A, \phi_{s}\right)} 44 | 45 | where 46 | 47 | * :math:`R`: the distance between start and goal pose 48 | * :math:`X`: :math:`X(a, b, c)=\int_{0}^{1} \cos \left(\frac{a}{2} \tau^{2}+b \tau+c\right) d \tau` 49 | 50 | 51 | - :math:`\kappa`: curvature 52 | 53 | .. math:: 54 | 55 | \kappa=(\delta-A) / L 56 | 57 | 58 | - :math:`\kappa'`: curvature rate 59 | 60 | .. math:: 61 | 62 | \kappa^{\prime}=2 A / L^{2} 63 | 64 | 65 | Step3: Construct a path with Fresnel integral 66 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 67 | 68 | The final clothoid path can be calculated with the path parameters and Fresnel integrals. 69 | 70 | .. math:: 71 | \begin{aligned} 72 | &x(s)=x_{0}+\int_{0}^{s} \cos \left(\frac{1}{2} \kappa^{\prime} \tau^{2}+\kappa \tau+\vartheta_{0}\right) \mathrm{d} \tau \\ 73 | &y(s)=y_{0}+\int_{0}^{s} \sin \left(\frac{1}{2} \kappa^{\prime} \tau^{2}+\kappa \tau+\vartheta_{0}\right) \mathrm{d} \tau 74 | \end{aligned} 75 | 76 | 77 | References 78 | ~~~~~~~~~~ 79 | 80 | - `Fast and accurate G1 fitting of clothoid curves `__ 81 | -------------------------------------------------------------------------------- /docs/modules/path_planning/coverage_path/coverage_path_main.rst: -------------------------------------------------------------------------------- 1 | Coverage path planner 2 | --------------------- 3 | 4 | Grid based sweep 5 | ~~~~~~~~~~~~~~~~ 6 | 7 | This is a 2D grid based sweep coverage path planner simulation: 8 | 9 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/GridBasedSweepCPP/animation.gif 10 | 11 | Spiral Spanning Tree 12 | ~~~~~~~~~~~~~~~~~~~~ 13 | 14 | This is a 2D grid based spiral spanning tree coverage path planner simulation: 15 | 16 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/SpiralSpanningTreeCPP/animation1.gif 17 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/SpiralSpanningTreeCPP/animation2.gif 18 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/SpiralSpanningTreeCPP/animation3.gif 19 | 20 | - `Spiral-STC: An On-Line Coverage Algorithm of Grid Environments by a Mobile Robot `_ 21 | 22 | 23 | Wavefront path 24 | ~~~~~~~~~~~~~~ 25 | 26 | This is a 2D grid based wavefront coverage path planner simulation: 27 | 28 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/WavefrontCPP/animation1.gif 29 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/WavefrontCPP/animation2.gif 30 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/WavefrontCPP/animation3.gif 31 | 32 | - `Planning paths of complete coverage of an unstructured environment by a mobile robot `_ 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/modules/path_planning/cubic_spline/cubic_spline_1d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/cubic_spline/cubic_spline_1d.png -------------------------------------------------------------------------------- /docs/modules/path_planning/cubic_spline/cubic_spline_2d_curvature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/cubic_spline/cubic_spline_2d_curvature.png -------------------------------------------------------------------------------- /docs/modules/path_planning/cubic_spline/cubic_spline_2d_path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/cubic_spline/cubic_spline_2d_path.png -------------------------------------------------------------------------------- /docs/modules/path_planning/cubic_spline/cubic_spline_2d_yaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/cubic_spline/cubic_spline_2d_yaw.png -------------------------------------------------------------------------------- /docs/modules/path_planning/cubic_spline/spline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/cubic_spline/spline.png -------------------------------------------------------------------------------- /docs/modules/path_planning/cubic_spline/spline_continuity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/cubic_spline/spline_continuity.png -------------------------------------------------------------------------------- /docs/modules/path_planning/dubins_path/RLR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/dubins_path/RLR.jpg -------------------------------------------------------------------------------- /docs/modules/path_planning/dubins_path/RSR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/dubins_path/RSR.jpg -------------------------------------------------------------------------------- /docs/modules/path_planning/dubins_path/dubins_path.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/dubins_path/dubins_path.jpg -------------------------------------------------------------------------------- /docs/modules/path_planning/dubins_path/dubins_path_main.rst: -------------------------------------------------------------------------------- 1 | Dubins path planning 2 | -------------------- 3 | 4 | A sample code for Dubins path planning. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/DubinsPath/animation.gif?raw=True 7 | 8 | Dubins path 9 | ~~~~~~~~~~~~ 10 | Dubins path is a analytical path planning algorithm for a simple car model. 11 | 12 | It can generates a shortest path between two 2D poses (x, y, yaw) with maximum curvature constraint and tangent(yaw angle) constraint. 13 | 14 | Generated paths consist of 3 segments of maximum curvature curves or a straight line segment. 15 | 16 | Each segment type can is categorized by 3 type: 'Right turn (R)' , 'Left turn (L)', and 'Straight (S).' 17 | 18 | Possible path will be at least one of these six types: RSR, RSL, LSR, LSL, RLR, LRL. 19 | 20 | Dubins path planner can output each segment type and distance of each course segment. 21 | 22 | For example, a RSR Dubins path is: 23 | 24 | .. image:: RSR.jpg 25 | :width: 400px 26 | 27 | Each segment distance can be calculated by: 28 | 29 | :math:`\alpha = mod(-\theta)` 30 | 31 | :math:`\beta = mod(x_{e, yaw} - \theta)` 32 | 33 | :math:`p^2 = 2 + d ^ 2 - 2\cos(\alpha-\beta) + 2d(\sin\alpha - \sin\beta)` 34 | 35 | :math:`t = atan2(\cos\beta - \cos\alpha, d + \sin\alpha - \sin\beta)` 36 | 37 | :math:`d_1 = mod(-\alpha + t)` 38 | 39 | :math:`d_2 = p` 40 | 41 | :math:`d_3 = mod(\beta - t)` 42 | 43 | where :math:`\theta` is tangent and d is distance from :math:`x_s` to :math:`x_e` 44 | 45 | A RLR Dubins path is: 46 | 47 | .. image:: RLR.jpg 48 | :width: 200px 49 | 50 | Each segment distance can be calculated by: 51 | 52 | :math:`t = (6.0 - d^2 + 2\cos(\alpha-\beta) + 2d(\sin\alpha - \sin\beta)) / 8.0` 53 | 54 | :math:`d_2 = mod(2\pi - acos(t))` 55 | 56 | :math:`d_1 = mod(\alpha - atan2(\cos\beta - \cos\alpha, d + \sin\alpha - \sin\beta) + d_2 / 2.0)` 57 | 58 | :math:`d_3 = mod(\alpha - \beta - d_1 + d_2)` 59 | 60 | You can generate a path from these information and the maximum curvature information. 61 | 62 | A path type which has minimum course length among 6 types is selected, 63 | and then a path is constructed based on the selected type and its distances. 64 | 65 | API 66 | ~~~~~~~~~~~~~~~~~~~~ 67 | 68 | .. autofunction:: PathPlanning.DubinsPath.dubins_path_planner.plan_dubins_path 69 | 70 | 71 | Reference 72 | ~~~~~~~~~~~~~~~~~~~~ 73 | - `On Curves of Minimal Length with a Constraint on Average Curvature, and with Prescribed Initial and Terminal Positions and Tangents `__ 74 | - `Dubins path - Wikipedia `__ 75 | - `15.3.1 Dubins Curves `__ 76 | - `A Comprehensive, Step-by-Step Tutorial to Computing Dubin’s Paths `__ 77 | -------------------------------------------------------------------------------- /docs/modules/path_planning/dynamic_window_approach/dynamic_window_approach_main.rst: -------------------------------------------------------------------------------- 1 | .. _dynamic_window_approach: 2 | 3 | Dynamic Window Approach 4 | ----------------------- 5 | 6 | This is a 2D navigation sample code with Dynamic Window Approach. 7 | 8 | - `The Dynamic Window Approach to Collision 9 | Avoidance `__ 10 | 11 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/DynamicWindowApproach/animation.gif 12 | -------------------------------------------------------------------------------- /docs/modules/path_planning/eta3_spline/eta3_spline_main.rst: -------------------------------------------------------------------------------- 1 | .. _eta^3-spline-path-planning: 2 | 3 | Eta^3 Spline path planning 4 | -------------------------- 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/Eta3SplinePath/animation.gif 7 | 8 | This is a path planning with Eta^3 spline. 9 | 10 | Ref: 11 | 12 | - `\\eta^3-Splines for the Smooth Path Generation of Wheeled Mobile 13 | Robots `__ 14 | -------------------------------------------------------------------------------- /docs/modules/path_planning/frenet_frame_path/frenet_frame_path_main.rst: -------------------------------------------------------------------------------- 1 | Optimal Trajectory in a Frenet Frame 2 | ------------------------------------ 3 | 4 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/FrenetOptimalTrajectory/animation.gif 5 | 6 | This is optimal trajectory generation in a Frenet Frame. 7 | 8 | The cyan line is the target course and black crosses are obstacles. 9 | 10 | The red line is predicted path. 11 | 12 | Ref: 13 | 14 | - `Optimal Trajectory Generation for Dynamic Street Scenarios in a 15 | Frenet 16 | Frame `__ 17 | 18 | - `Optimal trajectory generation for dynamic street scenarios in a 19 | Frenet Frame `__ 20 | 21 | -------------------------------------------------------------------------------- /docs/modules/path_planning/grid_base_search/grid_base_search_main.rst: -------------------------------------------------------------------------------- 1 | Grid based search 2 | ----------------- 3 | 4 | Breadth First Search 5 | ~~~~~~~~~~~~~~~~~~~~ 6 | 7 | This is a 2D grid based path planning with Breadth first search algorithm. 8 | 9 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/BreadthFirstSearch/animation.gif 10 | 11 | In the animation, cyan points are searched nodes. 12 | 13 | Depth First Search 14 | ~~~~~~~~~~~~~~~~~~~~ 15 | 16 | This is a 2D grid based path planning with Depth first search algorithm. 17 | 18 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/DepthFirstSearch/animation.gif 19 | 20 | In the animation, cyan points are searched nodes. 21 | 22 | .. _dijkstra: 23 | 24 | Dijkstra algorithm 25 | ~~~~~~~~~~~~~~~~~~ 26 | 27 | This is a 2D grid based shortest path planning with Dijkstra's algorithm. 28 | 29 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/Dijkstra/animation.gif 30 | 31 | In the animation, cyan points are searched nodes. 32 | 33 | .. _a*-algorithm: 34 | 35 | A\* algorithm 36 | ~~~~~~~~~~~~~ 37 | 38 | This is a 2D grid based shortest path planning with A star algorithm. 39 | 40 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/AStar/animation.gif 41 | 42 | In the animation, cyan points are searched nodes. 43 | 44 | Its heuristic is 2D Euclid distance. 45 | 46 | Bidirectional A\* algorithm 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | 49 | This is a 2D grid based shortest path planning with bidirectional A star algorithm. 50 | 51 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/BidirectionalAStar/animation.gif 52 | 53 | In the animation, cyan points are searched nodes. 54 | 55 | .. _D*-algorithm: 56 | 57 | D\* algorithm 58 | ~~~~~~~~~~~~~ 59 | 60 | This is a 2D grid based shortest path planning with D star algorithm. 61 | 62 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/DStar/animation.gif 63 | 64 | The animation shows a robot finding its path avoiding an obstacle using the D* search algorithm. 65 | 66 | Ref: 67 | 68 | - `D* search Wikipedia `__ 69 | 70 | D\* lite algorithm 71 | ~~~~~~~~~~~~~~~~~~ 72 | 73 | This is a 2D grid based path planning and replanning with D star lite algorithm. 74 | 75 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/DStarLite/animation.gif 76 | 77 | Ref: 78 | 79 | - `Improved Fast Replanning for Robot Navigation in Unknown Terrain `_ 80 | 81 | 82 | Potential Field algorithm 83 | ~~~~~~~~~~~~~~~~~~~~~~~~~ 84 | 85 | This is a 2D grid based path planning with Potential Field algorithm. 86 | 87 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/PotentialFieldPlanning/animation.gif 88 | 89 | In the animation, the blue heat map shows potential value on each grid. 90 | 91 | Ref: 92 | 93 | - `Robotic Motion Planning:Potential 94 | Functions `__ 95 | 96 | -------------------------------------------------------------------------------- /docs/modules/path_planning/hybridastar/hybridastar_main.rst: -------------------------------------------------------------------------------- 1 | Hybrid a star 2 | --------------------- 3 | 4 | This is a simple vehicle model based hybrid A\* path planner. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/HybridAStar/animation.gif 7 | -------------------------------------------------------------------------------- /docs/modules/path_planning/lqr_path/lqr_path_main.rst: -------------------------------------------------------------------------------- 1 | LQR based path planning 2 | ----------------------- 3 | 4 | A sample code using LQR based path planning for double integrator model. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/LQRPlanner/animation.gif?raw=true 7 | -------------------------------------------------------------------------------- /docs/modules/path_planning/model_predictive_trajectory_generator/lookup_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/model_predictive_trajectory_generator/lookup_table.png -------------------------------------------------------------------------------- /docs/modules/path_planning/model_predictive_trajectory_generator/model_predictive_trajectory_generator_main.rst: -------------------------------------------------------------------------------- 1 | Model Predictive Trajectory Generator 2 | ------------------------------------- 3 | 4 | This is a path optimization sample on model predictive trajectory 5 | generator. 6 | 7 | This algorithm is used for state lattice planner. 8 | 9 | Path optimization sample 10 | ~~~~~~~~~~~~~~~~~~~~~~~~ 11 | 12 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ModelPredictiveTrajectoryGenerator/kn05animation.gif 13 | 14 | Lookup table generation sample 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | 17 | .. image:: lookup_table.png 18 | 19 | Ref: 20 | 21 | - `Optimal rough terrain trajectory generation for wheeled mobile 22 | robots `__ 23 | -------------------------------------------------------------------------------- /docs/modules/path_planning/path_planning_main.rst: -------------------------------------------------------------------------------- 1 | .. _path_planning: 2 | 3 | Path Planning 4 | ============= 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | dynamic_window_approach/dynamic_window_approach 11 | bugplanner/bugplanner 12 | grid_base_search/grid_base_search 13 | model_predictive_trajectory_generator/model_predictive_trajectory_generator 14 | state_lattice_planner/state_lattice_planner 15 | prm_planner/prm_planner 16 | visibility_road_map_planner/visibility_road_map_planner 17 | vrm_planner/vrm_planner 18 | rrt/rrt 19 | cubic_spline/cubic_spline 20 | bspline_path/bspline_path 21 | clothoid_path/clothoid_path 22 | eta3_spline/eta3_spline 23 | bezier_path/bezier_path 24 | quintic_polynomials_planner/quintic_polynomials_planner 25 | dubins_path/dubins_path 26 | reeds_shepp_path/reeds_shepp_path 27 | lqr_path/lqr_path 28 | hybridastar/hybridastar 29 | frenet_frame_path/frenet_frame_path 30 | coverage_path/coverage_path 31 | -------------------------------------------------------------------------------- /docs/modules/path_planning/prm_planner/prm_planner_main.rst: -------------------------------------------------------------------------------- 1 | .. _probabilistic-road-map-(prm)-planning: 2 | 3 | Probabilistic Road-Map (PRM) planning 4 | ------------------------------------- 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ProbabilisticRoadMap/animation.gif 7 | 8 | This PRM planner uses Dijkstra method for graph search. 9 | 10 | In the animation, blue points are sampled points, 11 | 12 | Cyan crosses means searched points with Dijkstra method, 13 | 14 | The red line is the final path of PRM. 15 | 16 | Ref: 17 | 18 | - `Probabilistic roadmap - 19 | Wikipedia `__ 20 | -------------------------------------------------------------------------------- /docs/modules/path_planning/reeds_shepp_path/reeds_shepp_path_main.rst: -------------------------------------------------------------------------------- 1 | Reeds Shepp planning 2 | -------------------- 3 | 4 | A sample code with Reeds Shepp path planning. 5 | 6 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ReedsSheppPath/animation.gif?raw=true 7 | 8 | Ref: 9 | 10 | - `15.3.2 Reeds-Shepp 11 | Curves `__ 12 | 13 | - `optimal paths for a car that goes both forwards and 14 | backwards `__ 15 | 16 | - `ghliu/pyReedsShepp: Implementation of Reeds Shepp 17 | curve. `__ 18 | -------------------------------------------------------------------------------- /docs/modules/path_planning/rrt/figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/rrt/figure_1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/rrt/rrt_main.rst: -------------------------------------------------------------------------------- 1 | .. _rapidly-exploring-random-trees-(rrt): 2 | 3 | Rapidly-Exploring Random Trees (RRT) 4 | ------------------------------------ 5 | 6 | Basic RRT 7 | ~~~~~~~~~ 8 | 9 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/RRT/animation.gif 10 | 11 | This is a simple path planning code with Rapidly-Exploring Random Trees 12 | (RRT) 13 | 14 | Black circles are obstacles, green line is a searched tree, red crosses 15 | are start and goal positions. 16 | 17 | .. include:: rrt_star.rst 18 | 19 | 20 | RRT with dubins path 21 | ~~~~~~~~~~~~~~~~~~~~ 22 | 23 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/RRTDubins/animation.gif 24 | 25 | Path planning for a car robot with RRT and dubins path planner. 26 | 27 | .. _rrt*-with-dubins-path: 28 | 29 | RRT\* with dubins path 30 | ~~~~~~~~~~~~~~~~~~~~~~ 31 | 32 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/RRTStarDubins/animation.gif 33 | 34 | Path planning for a car robot with RRT\* and dubins path planner. 35 | 36 | .. _rrt*-with-reeds-sheep-path: 37 | 38 | RRT\* with reeds-sheep path 39 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 40 | 41 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/RRTStarReedsShepp/animation.gif 42 | 43 | Path planning for a car robot with RRT\* and reeds sheep path planner. 44 | 45 | .. _informed-rrt*: 46 | 47 | Informed RRT\* 48 | ~~~~~~~~~~~~~~ 49 | 50 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/InformedRRTStar/animation.gif 51 | 52 | This is a path planning code with Informed RRT*. 53 | 54 | The cyan ellipse is the heuristic sampling domain of Informed RRT*. 55 | 56 | Ref: 57 | 58 | - `Informed RRT\*: Optimal Sampling-based Path Planning Focused via 59 | Direct Sampling of an Admissible Ellipsoidal 60 | Heuristic `__ 61 | 62 | .. _batch-informed-rrt*: 63 | 64 | Batch Informed RRT\* 65 | ~~~~~~~~~~~~~~~~~~~~ 66 | 67 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/BatchInformedRRTStar/animation.gif 68 | 69 | This is a path planning code with Batch Informed RRT*. 70 | 71 | Ref: 72 | 73 | - `Batch Informed Trees (BIT*): Sampling-based Optimal Planning via the 74 | Heuristically Guided Search of Implicit Random Geometric 75 | Graphs `__ 76 | 77 | .. _closed-loop-rrt*: 78 | 79 | Closed Loop RRT\* 80 | ~~~~~~~~~~~~~~~~~ 81 | 82 | A vehicle model based path planning with closed loop RRT*. 83 | 84 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/ClosedLoopRRTStar/animation.gif 85 | 86 | In this code, pure-pursuit algorithm is used for steering control, 87 | 88 | PID is used for speed control. 89 | 90 | Ref: 91 | 92 | - `Motion Planning in Complex Environments using Closed-loop 93 | Prediction `__ 94 | 95 | - `Real-time Motion Planning with Applications to Autonomous Urban 96 | Driving `__ 97 | 98 | - `[1601.06326] Sampling-based Algorithms for Optimal Motion Planning 99 | Using Closed-loop Prediction `__ 100 | 101 | .. _lqr-rrt*: 102 | 103 | LQR-RRT\* 104 | ~~~~~~~~~ 105 | 106 | This is a path planning simulation with LQR-RRT*. 107 | 108 | A double integrator motion model is used for LQR local planner. 109 | 110 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/LQRRRTStar/animation.gif 111 | 112 | Ref: 113 | 114 | - `LQR-RRT\*: Optimal Sampling-Based Motion Planning with Automatically 115 | Derived Extension 116 | Heuristics `__ 117 | 118 | - `MahanFathi/LQR-RRTstar: LQR-RRT\* method is used for random motion planning of a simple pendulum in its phase plot `__ -------------------------------------------------------------------------------- /docs/modules/path_planning/rrt/rrt_star.rst: -------------------------------------------------------------------------------- 1 | RRT\* 2 | ~~~~~ 3 | 4 | .. figure:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/RRTstar/animation.gif 5 | 6 | This is a path planning code with RRT\* 7 | 8 | Black circles are obstacles, green line is a searched tree, red crosses are start and goal positions. 9 | 10 | Simulation 11 | ^^^^^^^^^^ 12 | 13 | .. image:: rrt_star/rrt_star_1_0.png 14 | :width: 600px 15 | 16 | 17 | Ref 18 | ^^^ 19 | - `Sampling-based Algorithms for Optimal Motion Planning `__ 20 | - `Incremental Sampling-based Algorithms for Optimal Motion Planning `__ 21 | 22 | -------------------------------------------------------------------------------- /docs/modules/path_planning/rrt/rrt_star/rrt_star_1_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/rrt/rrt_star/rrt_star_1_0.png -------------------------------------------------------------------------------- /docs/modules/path_planning/rrt/rrt_star_reeds_shepp/figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/rrt/rrt_star_reeds_shepp/figure_1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/Figure_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/state_lattice_planner/Figure_1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/Figure_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/state_lattice_planner/Figure_2.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/Figure_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/state_lattice_planner/Figure_3.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/Figure_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/state_lattice_planner/Figure_4.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/Figure_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/state_lattice_planner/Figure_5.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/Figure_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/state_lattice_planner/Figure_6.png -------------------------------------------------------------------------------- /docs/modules/path_planning/state_lattice_planner/state_lattice_planner_main.rst: -------------------------------------------------------------------------------- 1 | State Lattice Planning 2 | ---------------------- 3 | 4 | This script is a path planning code with state lattice planning. 5 | 6 | This code uses the model predictive trajectory generator to solve 7 | boundary problem. 8 | 9 | 10 | Uniform polar sampling 11 | ~~~~~~~~~~~~~~~~~~~~~~ 12 | 13 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/StateLatticePlanner/UniformPolarSampling.gif 14 | 15 | Biased polar sampling 16 | ~~~~~~~~~~~~~~~~~~~~~ 17 | 18 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/StateLatticePlanner/BiasedPolarSampling.gif 19 | 20 | Lane sampling 21 | ~~~~~~~~~~~~~ 22 | 23 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/StateLatticePlanner/LaneSampling.gif 24 | 25 | Ref: 26 | 27 | - `Optimal rough terrain trajectory generation for wheeled mobile 28 | robots `__ 29 | 30 | - `State Space Sampling of Feasible Motions for High-Performance Mobile 31 | Robot Navigation in Complex 32 | Environments `__ 33 | 34 | -------------------------------------------------------------------------------- /docs/modules/path_planning/visibility_road_map_planner/step0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/visibility_road_map_planner/step0.png -------------------------------------------------------------------------------- /docs/modules/path_planning/visibility_road_map_planner/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/visibility_road_map_planner/step1.png -------------------------------------------------------------------------------- /docs/modules/path_planning/visibility_road_map_planner/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/visibility_road_map_planner/step2.png -------------------------------------------------------------------------------- /docs/modules/path_planning/visibility_road_map_planner/step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_planning/visibility_road_map_planner/step3.png -------------------------------------------------------------------------------- /docs/modules/path_planning/visibility_road_map_planner/visibility_road_map_planner_main.rst: -------------------------------------------------------------------------------- 1 | Visibility Road-Map planner 2 | --------------------------- 3 | 4 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/VisibilityRoadMap/animation.gif 5 | 6 | `[Code] `_ 7 | 8 | This visibility road-map planner uses Dijkstra method for graph search. 9 | 10 | In the animation, the black lines are polygon obstacles, 11 | 12 | red crosses are visibility nodes, and blue lines area collision free visibility graphs. 13 | 14 | The red line is the final path searched by dijkstra algorithm frm the visibility graphs. 15 | 16 | Algorithms 17 | ~~~~~~~~~~ 18 | 19 | In this chapter, how does the visibility road map planner search a path. 20 | 21 | We assume this planner can be provided these information in the below figure. 22 | 23 | - 1. Start point (Red point) 24 | - 2. Goal point (Blue point) 25 | - 3. Obstacle polygons (Black lines) 26 | 27 | .. image:: step0.png 28 | :width: 400px 29 | 30 | 31 | Step1: Generate visibility nodes based on polygon obstacles 32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 33 | 34 | The nodes are generated by expanded these polygons vertexes like the below figure: 35 | 36 | .. image:: step1.png 37 | :width: 400px 38 | 39 | Each polygon vertex is expanded outward from the vector of adjacent vertices. 40 | 41 | The start and goal point are included as nodes as well. 42 | 43 | Step2: Generate visibility graphs connecting the nodes. 44 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 45 | 46 | When connecting the nodes, the arc between two nodes is checked to collided or not to each obstacles. 47 | 48 | If the arc is collided, the graph is removed. 49 | 50 | The blue lines are generated visibility graphs in the figure: 51 | 52 | .. image:: step2.png 53 | :width: 400px 54 | 55 | 56 | Step3: Search the shortest path in the graphs using Dijkstra algorithm 57 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | 59 | The red line is searched path in the figure: 60 | 61 | .. image:: step3.png 62 | :width: 400px 63 | 64 | You can find the details of Dijkstra algorithm in :ref:`dijkstra`. 65 | 66 | References 67 | ^^^^^^^^^^ 68 | 69 | - `Visibility graph - Wikipedia `_ 70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/modules/path_planning/vrm_planner/vrm_planner_main.rst: -------------------------------------------------------------------------------- 1 | Voronoi Road-Map planning 2 | ------------------------- 3 | 4 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathPlanning/VoronoiRoadMap/animation.gif 5 | 6 | This Voronoi road-map planner uses Dijkstra method for graph search. 7 | 8 | In the animation, blue points are Voronoi points, 9 | 10 | Cyan crosses mean searched points with Dijkstra method, 11 | 12 | The red line is the final path of Vornoi Road-Map. 13 | 14 | Ref: 15 | 16 | - `Robotic Motion Planning `__ 17 | 18 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_1_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_1_0.png -------------------------------------------------------------------------------- /docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_2_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_2_0.png -------------------------------------------------------------------------------- /docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_3_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_3_0.png -------------------------------------------------------------------------------- /docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_4_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_4_0.png -------------------------------------------------------------------------------- /docs/modules/path_tracking/cgmres_nmpc/cgmres_nmpc_main.rst: -------------------------------------------------------------------------------- 1 | 2 | Nonlinear Model Predictive Control with C-GMRES 3 | ----------------------------------------------- 4 | 5 | .. image:: cgmres_nmpc_1_0.png 6 | :width: 600px 7 | 8 | .. image:: cgmres_nmpc_2_0.png 9 | :width: 600px 10 | 11 | .. image:: cgmres_nmpc_3_0.png 12 | :width: 600px 13 | 14 | .. image:: cgmres_nmpc_4_0.png 15 | :width: 600px 16 | 17 | .. figure:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathTracking/cgmres_nmpc/animation.gif 18 | :alt: gif 19 | 20 | Mathematical Formulation 21 | ~~~~~~~~~~~~~~~~~~~~~~~~ 22 | 23 | Motion model is 24 | 25 | .. math:: \dot{x}=vcos\theta 26 | 27 | .. math:: \dot{y}=vsin\theta 28 | 29 | .. math:: \dot{\theta}=\frac{v}{WB}sin(u_{\delta}) 30 | 31 | \ (tan is not good for optimization) 32 | 33 | .. math:: \dot{v}=u_a 34 | 35 | Cost function is 36 | 37 | .. math:: J=\frac{1}{2}(u_a^2+u_{\delta}^2)-\phi_a d_a-\phi_\delta d_\delta 38 | 39 | Input constraints are 40 | 41 | .. math:: |u_a| \leq u_{a,max} 42 | 43 | .. math:: |u_\delta| \leq u_{\delta,max} 44 | 45 | So, Hamiltonian is 46 | 47 | .. math:: 48 | 49 | J=\frac{1}{2}(u_a^2+u_{\delta}^2)-\phi_a d_a-\phi_\delta d_\delta\\ +\lambda_1vcos\theta+\lambda_2vsin\theta+\lambda_3\frac{v}{WB}sin(u_{\delta})+\lambda_4u_a\\ 50 | +\rho_1(u_a^2+d_a^2+u_{a,max}^2)+\rho_2(u_\delta^2+d_\delta^2+u_{\delta,max}^2) 51 | 52 | Partial differential equations of the Hamiltonian are: 53 | 54 | :math:`\begin{equation*} \frac{\partial H}{\partial \bf{x}}=\\ \begin{bmatrix} \frac{\partial H}{\partial x}= 0&\\ \frac{\partial H}{\partial y}= 0&\\ \frac{\partial H}{\partial \theta}= -\lambda_1vsin\theta+\lambda_2vcos\theta&\\ \frac{\partial H}{\partial v}=-\lambda_1cos\theta+\lambda_2sin\theta+\lambda_3\frac{1}{WB}sin(u_{\delta})&\\ \end{bmatrix} \\ \end{equation*}` 55 | 56 | :math:`\begin{equation*} \frac{\partial H}{\partial \bf{u}}=\\ \begin{bmatrix} \frac{\partial H}{\partial u_a}= u_a+\lambda_4+2\rho_1u_a&\\ \frac{\partial H}{\partial u_\delta}= u_\delta+\lambda_3\frac{v}{WB}cos(u_{\delta})+2\rho_2u_\delta&\\ \frac{\partial H}{\partial d_a}= -\phi_a+2\rho_1d_a&\\ \frac{\partial H}{\partial d_\delta}=-\phi_\delta+2\rho_2d_\delta&\\ \end{bmatrix} \\ \end{equation*}` 57 | 58 | Ref 59 | ~~~ 60 | 61 | - `Shunichi09/nonlinear_control: Implementing the nonlinear model 62 | predictive control, sliding mode 63 | control `__ 64 | 65 | - `非線形モデル予測制御におけるCGMRES法をpythonで実装する - 66 | Qiita `__ 67 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/lqr_speed_and_steering_control/lqr_speed_and_steering_control_main.rst: -------------------------------------------------------------------------------- 1 | .. _linearquadratic-regulator-(lqr)-speed-and-steering-control: 2 | 3 | Linear–quadratic regulator (LQR) speed and steering control 4 | ----------------------------------------------------------- 5 | 6 | Path tracking simulation with LQR speed and steering control. 7 | 8 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathTracking/lqr_speed_steer_control/animation.gif 9 | 10 | References: 11 | ~~~~~~~~~~~ 12 | 13 | - `Towards fully autonomous driving: Systems and algorithms `__ 14 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/lqr_steering_control/lqr_steering_control_main.rst: -------------------------------------------------------------------------------- 1 | .. _linearquadratic-regulator-(lqr)-steering-control: 2 | 3 | Linear–quadratic regulator (LQR) steering control 4 | ------------------------------------------------- 5 | 6 | Path tracking simulation with LQR steering control and PID speed 7 | control. 8 | 9 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathTracking/lqr_steer_control/animation.gif 10 | 11 | References: 12 | ~~~~~~~~~~~ 13 | - `ApolloAuto/apollo: An open autonomous driving platform `_ 14 | 15 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/path_tracking_main.rst: -------------------------------------------------------------------------------- 1 | .. _path_tracking: 2 | 3 | Path Tracking 4 | ============= 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | :caption: Contents 9 | 10 | pure_pursuit_tracking/pure_pursuit_tracking 11 | stanley_control/stanley_control 12 | rear_wheel_feedback_control/rear_wheel_feedback_control 13 | lqr_steering_control/lqr_steering_control 14 | lqr_speed_and_steering_control/lqr_speed_and_steering_control 15 | model_predictive_speed_and_steering_control/model_predictive_speed_and_steering_control 16 | cgmres_nmpc/cgmres_nmpc 17 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/pure_pursuit_tracking/pure_pursuit_tracking_main.rst: -------------------------------------------------------------------------------- 1 | Pure pursuit tracking 2 | --------------------- 3 | 4 | Path tracking simulation with pure pursuit steering control and PID 5 | speed control. 6 | 7 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathTracking/pure_pursuit/animation.gif 8 | 9 | The red line is a target course, the green cross means the target point 10 | for pure pursuit control, the blue line is the tracking. 11 | 12 | References: 13 | ~~~~~~~~~~~ 14 | 15 | - `A Survey of Motion Planning and Control Techniques for Self-driving 16 | Urban Vehicles `_ 17 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/rear_wheel_feedback_control/rear_wheel_feedback_control_main.rst: -------------------------------------------------------------------------------- 1 | Rear wheel feedback control 2 | --------------------------- 3 | 4 | Path tracking simulation with rear wheel feedback steering control and 5 | PID speed control. 6 | 7 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathTracking/rear_wheel_feedback/animation.gif 8 | 9 | References: 10 | ~~~~~~~~~~~ 11 | - `A Survey of Motion Planning and Control Techniques for Self-driving 12 | Urban Vehicles `__ 13 | -------------------------------------------------------------------------------- /docs/modules/path_tracking/stanley_control/stanley_control_main.rst: -------------------------------------------------------------------------------- 1 | Stanley control 2 | --------------- 3 | 4 | Path tracking simulation with Stanley steering control and PID speed 5 | control. 6 | 7 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/PathTracking/stanley_controller/animation.gif 8 | 9 | References: 10 | ~~~~~~~~~~~ 11 | 12 | - `Stanley: The robot that won the DARPA grand 13 | challenge `_ 14 | 15 | - `Automatic Steering Methods for Autonomous Automobile Path 16 | Tracking `_ 17 | -------------------------------------------------------------------------------- /docs/modules/slam/FastSLAM1/FastSLAM1_12_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/FastSLAM1/FastSLAM1_12_0.png -------------------------------------------------------------------------------- /docs/modules/slam/FastSLAM1/FastSLAM1_12_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/FastSLAM1/FastSLAM1_12_1.png -------------------------------------------------------------------------------- /docs/modules/slam/FastSLAM1/FastSLAM1_1_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/FastSLAM1/FastSLAM1_1_0.png -------------------------------------------------------------------------------- /docs/modules/slam/FastSLAM2/FastSLAM2_main.rst: -------------------------------------------------------------------------------- 1 | FastSLAM 2.0 2 | ------------ 3 | 4 | This is a feature based SLAM example using FastSLAM 2.0. 5 | 6 | The animation has the same meanings as one of FastSLAM 1.0. 7 | 8 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/SLAM/FastSLAM2/animation.gif 9 | 10 | References 11 | ~~~~~~~~~~ 12 | 13 | - `PROBABILISTIC ROBOTICS `_ 14 | 15 | - `SLAM simulations by Tim Bailey `_ 16 | 17 | -------------------------------------------------------------------------------- /docs/modules/slam/ekf_slam/ekf_slam_1_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/ekf_slam/ekf_slam_1_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/Graph_SLAM_optimization.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/Graph_SLAM_optimization.gif -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_13_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_13_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_15_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_15_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_16_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_16_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_4_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_4_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_8_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_8_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_9_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_SE2_example_files/graphSLAM_SE2_example_9_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_11_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_11_1.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_11_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_11_2.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_2_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_2_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_2_2.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_4_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_4_0.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_9_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/slam/graph_slam/graphSLAM_doc_files/graphSLAM_doc_9_1.png -------------------------------------------------------------------------------- /docs/modules/slam/graph_slam/graph_slam_main.rst: -------------------------------------------------------------------------------- 1 | Graph based SLAM 2 | ---------------- 3 | 4 | This is a graph based SLAM example. 5 | 6 | The blue line is ground truth. 7 | 8 | The black line is dead reckoning. 9 | 10 | The red line is the estimated trajectory with Graph based SLAM. 11 | 12 | The black stars are landmarks for graph edge generation. 13 | 14 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/SLAM/GraphBasedSLAM/animation.gif 15 | 16 | .. include:: graphSLAM_doc.rst 17 | .. include:: graphSLAM_formulation.rst 18 | .. include:: graphSLAM_SE2_example.rst 19 | 20 | References: 21 | ~~~~~~~~~~~ 22 | 23 | - `A Tutorial on Graph-Based SLAM `_ 24 | 25 | -------------------------------------------------------------------------------- /docs/modules/slam/iterative_closest_point_matching/iterative_closest_point_matching_main.rst: -------------------------------------------------------------------------------- 1 | .. _iterative-closest-point-(icp)-matching: 2 | 3 | Iterative Closest Point (ICP) Matching 4 | -------------------------------------- 5 | 6 | This is a 2D ICP matching example with singular value decomposition. 7 | 8 | It can calculate a rotation matrix and a translation vector between 9 | points to points. 10 | 11 | .. image:: https://github.com/AtsushiSakai/PythonRoboticsGifs/raw/master/SLAM/iterative_closest_point/animation.gif 12 | 13 | References 14 | ~~~~~~~~~~ 15 | 16 | - `Introduction to Mobile Robotics: Iterative Closest Point Algorithm `_ 17 | -------------------------------------------------------------------------------- /docs/modules/slam/slam_main.rst: -------------------------------------------------------------------------------- 1 | .. _slam: 2 | 3 | SLAM 4 | ==== 5 | 6 | Simultaneous Localization and Mapping(SLAM) examples 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | :caption: Contents 11 | 12 | iterative_closest_point_matching/iterative_closest_point_matching 13 | ekf_slam/ekf_slam 14 | FastSLAM1/FastSLAM1 15 | FastSLAM2/FastSLAM2 16 | graph_slam/graph_slam 17 | -------------------------------------------------------------------------------- /docs/modules/utils/plot/curvature_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/docs/modules/utils/plot/curvature_plot.png -------------------------------------------------------------------------------- /docs/modules/utils/plot/plot_main.rst: -------------------------------------------------------------------------------- 1 | .. _plot_utils: 2 | 3 | Plotting Utilities 4 | ------------------- 5 | 6 | This module contains a number of utility functions for plotting data. 7 | 8 | .. _plot_curvature: 9 | 10 | plot_curvature 11 | ~~~~~~~~~~~~~~~ 12 | 13 | .. autofunction:: utils.plot.plot_curvature 14 | 15 | .. image:: curvature_plot.png 16 | 17 | -------------------------------------------------------------------------------- /docs/modules/utils/utils_main.rst: -------------------------------------------------------------------------------- 1 | .. _utils: 2 | 3 | Utilities 4 | ========== 5 | 6 | Common utilities for PythonRobotics. 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | :caption: Contents 11 | 12 | plot/plot 13 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/icon.png -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | ignore_missing_imports = True -------------------------------------------------------------------------------- /requirements/environment.yml: -------------------------------------------------------------------------------- 1 | name: python_robotics 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - python=3.10 6 | - pip 7 | - scipy 8 | - numpy 9 | - cvxpy 10 | - matplotlib 11 | -------------------------------------------------------------------------------- /requirements/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy == 1.23.5 2 | scipy == 1.9.3 3 | matplotlib == 3.6.2 4 | cvxpy == 1.2.2 5 | pytest == 7.2.0 # For unit test 6 | pytest-xdist == 3.1.0 # For unit test 7 | mypy == 0.991 # For unit test 8 | flake8 == 5.0.4 # For unit test 9 | -------------------------------------------------------------------------------- /runtests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Run test suites! " 3 | 4 | # === pytest based test runner === 5 | # -Werror: warning as error 6 | # --durations=0: show ranking of test durations 7 | # -l (--showlocals); show local variables when test failed 8 | pytest -n auto tests -l -Werror --durations=0 9 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | """Path hack to make tests work.""" 2 | import sys 3 | import os 4 | import pytest 5 | 6 | TEST_DIR = os.path.dirname(os.path.abspath(__file__)) 7 | sys.path.append(TEST_DIR) # to import this file from test code. 8 | ROOT_DIR = os.path.dirname(TEST_DIR) 9 | sys.path.append(ROOT_DIR) 10 | 11 | 12 | def run_this_test(file): 13 | pytest.main([os.path.abspath(file)]) 14 | -------------------------------------------------------------------------------- /tests/test_LQR_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.LQRPlanner import lqr_planner as m 3 | 4 | 5 | def test_1(): 6 | m.SHOW_ANIMATION = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_a_star.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.AStar import a_star as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_a_star_searching_two_side.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.AStar import a_star_searching_from_two_side as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main(800) 8 | 9 | 10 | def test2(): 11 | m.show_animation = False 12 | m.main(5000) # increase obstacle number, block path 13 | 14 | 15 | if __name__ == '__main__': 16 | conftest.run_this_test(__file__) 17 | -------------------------------------------------------------------------------- /tests/test_a_star_variants.py: -------------------------------------------------------------------------------- 1 | import PathPlanning.AStar.a_star_variants as a_star 2 | import conftest 3 | 4 | 5 | def test_1(): 6 | # A* with beam search 7 | a_star.show_animation = False 8 | 9 | a_star.use_beam_search = True 10 | a_star.main() 11 | reset_all() 12 | 13 | # A* with iterative deepening 14 | a_star.use_iterative_deepening = True 15 | a_star.main() 16 | reset_all() 17 | 18 | # A* with dynamic weighting 19 | a_star.use_dynamic_weighting = True 20 | a_star.main() 21 | reset_all() 22 | 23 | # theta* 24 | a_star.use_theta_star = True 25 | a_star.main() 26 | reset_all() 27 | 28 | # A* with jump point 29 | a_star.use_jump_point = True 30 | a_star.main() 31 | reset_all() 32 | 33 | 34 | def reset_all(): 35 | a_star.show_animation = False 36 | a_star.use_beam_search = False 37 | a_star.use_iterative_deepening = False 38 | a_star.use_dynamic_weighting = False 39 | a_star.use_theta_star = False 40 | a_star.use_jump_point = False 41 | 42 | 43 | if __name__ == '__main__': 44 | conftest.run_this_test(__file__) 45 | -------------------------------------------------------------------------------- /tests/test_batch_informed_rrt_star.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | import conftest 4 | from PathPlanning.BatchInformedRRTStar import batch_informed_rrtstar as m 5 | 6 | 7 | def test_1(): 8 | m.show_animation = False 9 | random.seed(12345) 10 | m.main(maxIter=10) 11 | 12 | 13 | if __name__ == '__main__': 14 | conftest.run_this_test(__file__) 15 | -------------------------------------------------------------------------------- /tests/test_bezier_path.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.BezierPath import bezier_path as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | def test_2(): 11 | m.show_animation = False 12 | m.main2() 13 | 14 | 15 | if __name__ == '__main__': 16 | conftest.run_this_test(__file__) 17 | -------------------------------------------------------------------------------- /tests/test_bipedal_planner.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Bipedal.bipedal_planner import bipedal_planner as m 3 | 4 | 5 | def test_1(): 6 | bipedal_planner = m.BipedalPlanner() 7 | 8 | footsteps = [[0.0, 0.2, 0.0], 9 | [0.3, 0.2, 0.0], 10 | [0.3, 0.2, 0.2], 11 | [0.3, 0.2, 0.2], 12 | [0.0, 0.2, 0.2]] 13 | bipedal_planner.set_ref_footsteps(footsteps) 14 | bipedal_planner.walk(plot=False) 15 | 16 | 17 | if __name__ == '__main__': 18 | conftest.run_this_test(__file__) 19 | -------------------------------------------------------------------------------- /tests/test_breadth_first_search.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.BreadthFirstSearch import breadth_first_search as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_bspline_path.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | import numpy as np 3 | import pytest 4 | from PathPlanning.BSplinePath import bspline_path 5 | 6 | 7 | def test_list_input(): 8 | way_point_x = [-1.0, 3.0, 4.0, 2.0, 1.0] 9 | way_point_y = [0.0, -3.0, 1.0, 1.0, 3.0] 10 | n_course_point = 50 # sampling number 11 | 12 | rax, ray, heading, curvature = bspline_path.approximate_b_spline_path( 13 | way_point_x, way_point_y, n_course_point, s=0.5) 14 | 15 | assert len(rax) == len(ray) == len(heading) == len(curvature) 16 | 17 | rix, riy, heading, curvature = bspline_path.interpolate_b_spline_path( 18 | way_point_x, way_point_y, n_course_point) 19 | 20 | assert len(rix) == len(riy) == len(heading) == len(curvature) 21 | 22 | 23 | def test_array_input(): 24 | way_point_x = np.array([-1.0, 3.0, 4.0, 2.0, 1.0]) 25 | way_point_y = np.array([0.0, -3.0, 1.0, 1.0, 3.0]) 26 | n_course_point = 50 # sampling number 27 | 28 | rax, ray, heading, curvature = bspline_path.approximate_b_spline_path( 29 | way_point_x, way_point_y, n_course_point, s=0.5) 30 | 31 | assert len(rax) == len(ray) == len(heading) == len(curvature) 32 | 33 | rix, riy, heading, curvature = bspline_path.interpolate_b_spline_path( 34 | way_point_x, way_point_y, n_course_point) 35 | 36 | assert len(rix) == len(riy) == len(heading) == len(curvature) 37 | 38 | 39 | def test_degree_change(): 40 | way_point_x = np.array([-1.0, 3.0, 4.0, 2.0, 1.0]) 41 | way_point_y = np.array([0.0, -3.0, 1.0, 1.0, 3.0]) 42 | n_course_point = 50 # sampling number 43 | 44 | rax, ray, heading, curvature = bspline_path.approximate_b_spline_path( 45 | way_point_x, way_point_y, n_course_point, s=0.5, degree=4) 46 | 47 | assert len(rax) == len(ray) == len(heading) == len(curvature) 48 | 49 | rix, riy, heading, curvature = bspline_path.interpolate_b_spline_path( 50 | way_point_x, way_point_y, n_course_point, degree=4) 51 | 52 | assert len(rix) == len(riy) == len(heading) == len(curvature) 53 | 54 | rax, ray, heading, curvature = bspline_path.approximate_b_spline_path( 55 | way_point_x, way_point_y, n_course_point, s=0.5, degree=2) 56 | 57 | assert len(rax) == len(ray) == len(heading) == len(curvature) 58 | 59 | rix, riy, heading, curvature = bspline_path.interpolate_b_spline_path( 60 | way_point_x, way_point_y, n_course_point, degree=2) 61 | 62 | assert len(rix) == len(riy) == len(heading) == len(curvature) 63 | 64 | with pytest.raises(ValueError): 65 | bspline_path.approximate_b_spline_path( 66 | way_point_x, way_point_y, n_course_point, s=0.5, degree=1) 67 | 68 | with pytest.raises(ValueError): 69 | bspline_path.interpolate_b_spline_path( 70 | way_point_x, way_point_y, n_course_point, degree=1) 71 | 72 | 73 | if __name__ == '__main__': 74 | conftest.run_this_test(__file__) 75 | -------------------------------------------------------------------------------- /tests/test_bug.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.BugPlanning import bug as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main(bug_0=True, bug_1=True, bug_2=True) 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_cgmres_nmpc.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathTracking.cgmres_nmpc import cgmres_nmpc as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_circle_fitting.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Mapping.circle_fitting import circle_fitting as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_closed_loop_rrt_star_car.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.ClosedLoopRRTStar import closed_loop_rrt_star_car as m 3 | import random 4 | 5 | 6 | def test_1(): 7 | random.seed(12345) 8 | m.show_animation = False 9 | m.main(gx=1.0, gy=0.0, gyaw=0.0, max_iter=5) 10 | 11 | 12 | if __name__ == '__main__': 13 | conftest.run_this_test(__file__) 14 | -------------------------------------------------------------------------------- /tests/test_clothoidal_paths.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.ClothoidPath import clothoid_path_planner as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_cubature_kalman_filter.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Localization.cubature_kalman_filter import cubature_kalman_filter as m 3 | 4 | 5 | def test1(): 6 | m.show_final = False 7 | m.show_animation = False 8 | m.show_ellipse = False 9 | m.main() 10 | 11 | 12 | if __name__ == '__main__': 13 | conftest.run_this_test(__file__) 14 | -------------------------------------------------------------------------------- /tests/test_d_star_lite.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.DStarLite import d_star_lite as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_depth_first_search.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.DepthFirstSearch import depth_first_search as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_dijkstra.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.Dijkstra import dijkstra as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_drone_3d_trajectory_following.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from AerialNavigation.drone_3d_trajectory_following \ 3 | import drone_3d_trajectory_following as m 4 | 5 | 6 | def test1(): 7 | m.show_animation = False 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_dstar.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.DStar import dstar as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_dubins_path_planning.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import conftest 4 | from PathPlanning.DubinsPath import dubins_path_planner 5 | 6 | np.random.seed(12345) 7 | 8 | 9 | def check_edge_condition(px, py, pyaw, start_x, start_y, start_yaw, end_x, 10 | end_y, end_yaw): 11 | assert (abs(px[0] - start_x) <= 0.01) 12 | assert (abs(py[0] - start_y) <= 0.01) 13 | assert (abs(pyaw[0] - start_yaw) <= 0.01) 14 | assert (abs(px[-1] - end_x) <= 0.01) 15 | assert (abs(py[-1] - end_y) <= 0.01) 16 | assert (abs(pyaw[-1] - end_yaw) <= 0.01) 17 | 18 | 19 | def check_path_length(px, py, lengths): 20 | path_len = sum( 21 | [np.hypot(dx, dy) for (dx, dy) in zip(np.diff(px), np.diff(py))]) 22 | assert (abs(path_len - sum(lengths)) <= 0.1) 23 | 24 | 25 | def test_1(): 26 | start_x = 1.0 # [m] 27 | start_y = 1.0 # [m] 28 | start_yaw = np.deg2rad(45.0) # [rad] 29 | 30 | end_x = -3.0 # [m] 31 | end_y = -3.0 # [m] 32 | end_yaw = np.deg2rad(-45.0) # [rad] 33 | 34 | curvature = 1.0 35 | 36 | px, py, pyaw, mode, lengths = dubins_path_planner.plan_dubins_path( 37 | start_x, start_y, start_yaw, end_x, end_y, end_yaw, curvature) 38 | 39 | check_edge_condition(px, py, pyaw, start_x, start_y, start_yaw, end_x, 40 | end_y, end_yaw) 41 | check_path_length(px, py, lengths) 42 | 43 | 44 | def test_2(): 45 | dubins_path_planner.show_animation = False 46 | dubins_path_planner.main() 47 | 48 | 49 | def test_3(): 50 | N_TEST = 10 51 | 52 | for i in range(N_TEST): 53 | start_x = (np.random.rand() - 0.5) * 10.0 # [m] 54 | start_y = (np.random.rand() - 0.5) * 10.0 # [m] 55 | start_yaw = np.deg2rad((np.random.rand() - 0.5) * 180.0) # [rad] 56 | 57 | end_x = (np.random.rand() - 0.5) * 10.0 # [m] 58 | end_y = (np.random.rand() - 0.5) * 10.0 # [m] 59 | end_yaw = np.deg2rad((np.random.rand() - 0.5) * 180.0) # [rad] 60 | 61 | curvature = 1.0 / (np.random.rand() * 5.0) 62 | 63 | px, py, pyaw, mode, lengths = \ 64 | dubins_path_planner.plan_dubins_path( 65 | start_x, start_y, start_yaw, end_x, end_y, end_yaw, curvature) 66 | 67 | check_edge_condition(px, py, pyaw, start_x, start_y, start_yaw, end_x, 68 | end_y, end_yaw) 69 | check_path_length(px, py, lengths) 70 | 71 | 72 | def test_path_plannings_types(): 73 | dubins_path_planner.show_animation = False 74 | start_x = 1.0 # [m] 75 | start_y = 1.0 # [m] 76 | start_yaw = np.deg2rad(45.0) # [rad] 77 | 78 | end_x = -3.0 # [m] 79 | end_y = -3.0 # [m] 80 | end_yaw = np.deg2rad(-45.0) # [rad] 81 | 82 | curvature = 1.0 83 | 84 | _, _, _, mode, _ = dubins_path_planner.plan_dubins_path( 85 | start_x, start_y, start_yaw, end_x, end_y, end_yaw, curvature, 86 | selected_types=["RSL"]) 87 | 88 | assert mode == ["R", "S", "L"] 89 | 90 | 91 | if __name__ == '__main__': 92 | conftest.run_this_test(__file__) 93 | -------------------------------------------------------------------------------- /tests/test_dynamic_movement_primitives.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | import numpy as np 3 | from PathPlanning.DynamicMovementPrimitives import \ 4 | dynamic_movement_primitives 5 | 6 | 7 | def test_1(): 8 | # test that trajectory can be learned from user-passed data 9 | T = 5 10 | t = np.arange(0, T, 0.01) 11 | sin_t = np.sin(t) 12 | train_data = np.array([t, sin_t]).T 13 | 14 | DMP_controller = dynamic_movement_primitives.DMP(train_data, T) 15 | DMP_controller.recreate_trajectory(train_data[0], train_data[-1], 4) 16 | 17 | 18 | def test_2(): 19 | # test that length of trajectory is equal to desired number of timesteps 20 | T = 5 21 | t = np.arange(0, T, 0.01) 22 | sin_t = np.sin(t) 23 | train_data = np.array([t, sin_t]).T 24 | 25 | DMP_controller = dynamic_movement_primitives.DMP(train_data, T) 26 | t, path = DMP_controller.recreate_trajectory(train_data[0], 27 | train_data[-1], 4) 28 | 29 | assert(path.shape[0] == DMP_controller.timesteps) 30 | 31 | 32 | def test_3(): 33 | # check that learned trajectory is close to initial 34 | T = 3*np.pi/2 35 | A_noise = 0.02 36 | t = np.arange(0, T, 0.01) 37 | noisy_sin_t = np.sin(t) + A_noise*np.random.rand(len(t)) 38 | train_data = np.array([t, noisy_sin_t]).T 39 | 40 | DMP_controller = dynamic_movement_primitives.DMP(train_data, T) 41 | t, pos = DMP_controller.recreate_trajectory(train_data[0], 42 | train_data[-1], T) 43 | 44 | diff = abs(pos[:, 1] - noisy_sin_t) 45 | assert(max(diff) < 5*A_noise) 46 | 47 | 48 | if __name__ == '__main__': 49 | conftest.run_this_test(__file__) 50 | -------------------------------------------------------------------------------- /tests/test_dynamic_window_approach.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | import numpy as np 3 | 4 | from PathPlanning.DynamicWindowApproach import dynamic_window_approach as m 5 | 6 | 7 | def test_main1(): 8 | m.show_animation = False 9 | m.main(gx=1.0, gy=1.0) 10 | 11 | 12 | def test_main2(): 13 | m.show_animation = False 14 | m.main(gx=1.0, gy=1.0, robot_type=m.RobotType.rectangle) 15 | 16 | 17 | def test_stuck_main(): 18 | m.show_animation = False 19 | # adjust cost 20 | m.config.to_goal_cost_gain = 0.2 21 | m.config.obstacle_cost_gain = 2.0 22 | # obstacles and goals for stuck condition 23 | m.config.ob = -1 * np.array([[-1.0, -1.0], 24 | [0.0, 2.0], 25 | [2.0, 6.0], 26 | [2.0, 8.0], 27 | [3.0, 9.27], 28 | [3.79, 9.39], 29 | [7.25, 8.97], 30 | [7.0, 2.0], 31 | [3.0, 4.0], 32 | [6.0, 5.0], 33 | [3.5, 5.8], 34 | [6.0, 9.0], 35 | [8.8, 9.0], 36 | [5.0, 9.0], 37 | [7.5, 3.0], 38 | [9.0, 8.0], 39 | [5.8, 4.4], 40 | [12.0, 12.0], 41 | [3.0, 2.0], 42 | [13.0, 13.0] 43 | ]) 44 | m.main(gx=-5.0, gy=-7.0) 45 | 46 | 47 | if __name__ == '__main__': 48 | conftest.run_this_test(__file__) 49 | -------------------------------------------------------------------------------- /tests/test_ekf_slam.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from SLAM.EKFSLAM import ekf_slam as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_eta3_spline_path.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.Eta3SplinePath import eta3_spline_path as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_extended_kalman_filter.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Localization.extended_kalman_filter import extended_kalman_filter as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_fast_slam1.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from SLAM.FastSLAM1 import fast_slam1 as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.SIM_TIME = 3.0 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_fast_slam2.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from SLAM.FastSLAM2 import fast_slam2 as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.SIM_TIME = 3.0 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_flow_field.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | import PathPlanning.FlowField.flowfield as flow_field 3 | 4 | 5 | def test(): 6 | flow_field.show_animation = False 7 | flow_field.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_frenet_optimal_trajectory.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.FrenetOptimalTrajectory import frenet_optimal_trajectory as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.SIM_LOOP = 5 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_gaussian_grid_map.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Mapping.gaussian_grid_map import gaussian_grid_map as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_graph_based_slam.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from SLAM.GraphBasedSLAM import graph_based_slam as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.SIM_TIME = 20.0 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_greedy_best_first_search.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.GreedyBestFirstSearch import greedy_best_first_search as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_grid_based_sweep_coverage_path_planner.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.GridBasedSweepCPP \ 3 | import grid_based_sweep_coverage_path_planner 4 | 5 | grid_based_sweep_coverage_path_planner.do_animation = False 6 | RIGHT = grid_based_sweep_coverage_path_planner. \ 7 | SweepSearcher.MovingDirection.RIGHT 8 | LEFT = grid_based_sweep_coverage_path_planner. \ 9 | SweepSearcher.MovingDirection.LEFT 10 | UP = grid_based_sweep_coverage_path_planner. \ 11 | SweepSearcher.SweepDirection.UP 12 | DOWN = grid_based_sweep_coverage_path_planner. \ 13 | SweepSearcher.SweepDirection.DOWN 14 | 15 | 16 | def test_planning1(): 17 | ox = [0.0, 20.0, 50.0, 100.0, 130.0, 40.0, 0.0] 18 | oy = [0.0, -20.0, 0.0, 30.0, 60.0, 80.0, 0.0] 19 | resolution = 5.0 20 | 21 | px, py = grid_based_sweep_coverage_path_planner.planning( 22 | ox, oy, resolution, 23 | moving_direction=RIGHT, 24 | sweeping_direction=DOWN, 25 | ) 26 | assert len(px) >= 5 27 | 28 | px, py = grid_based_sweep_coverage_path_planner.planning( 29 | ox, oy, resolution, 30 | moving_direction=LEFT, 31 | sweeping_direction=DOWN, 32 | ) 33 | assert len(px) >= 5 34 | 35 | px, py = grid_based_sweep_coverage_path_planner.planning( 36 | ox, oy, resolution, 37 | moving_direction=RIGHT, 38 | sweeping_direction=UP, 39 | ) 40 | assert len(px) >= 5 41 | 42 | px, py = grid_based_sweep_coverage_path_planner.planning( 43 | ox, oy, resolution, 44 | moving_direction=RIGHT, 45 | sweeping_direction=UP, 46 | ) 47 | assert len(px) >= 5 48 | 49 | 50 | def test_planning2(): 51 | ox = [0.0, 50.0, 50.0, 0.0, 0.0] 52 | oy = [0.0, 0.0, 30.0, 30.0, 0.0] 53 | resolution = 1.3 54 | 55 | px, py = grid_based_sweep_coverage_path_planner.planning( 56 | ox, oy, resolution, 57 | moving_direction=RIGHT, 58 | sweeping_direction=DOWN, 59 | ) 60 | assert len(px) >= 5 61 | 62 | px, py = grid_based_sweep_coverage_path_planner.planning( 63 | ox, oy, resolution, 64 | moving_direction=LEFT, 65 | sweeping_direction=DOWN, 66 | ) 67 | assert len(px) >= 5 68 | 69 | px, py = grid_based_sweep_coverage_path_planner.planning( 70 | ox, oy, resolution, 71 | moving_direction=RIGHT, 72 | sweeping_direction=UP, 73 | ) 74 | assert len(px) >= 5 75 | 76 | px, py = grid_based_sweep_coverage_path_planner.planning( 77 | ox, oy, resolution, 78 | moving_direction=RIGHT, 79 | sweeping_direction=DOWN, 80 | ) 81 | assert len(px) >= 5 82 | 83 | 84 | def test_planning3(): 85 | ox = [0.0, 20.0, 50.0, 200.0, 130.0, 40.0, 0.0] 86 | oy = [0.0, -80.0, 0.0, 30.0, 60.0, 80.0, 0.0] 87 | resolution = 5.1 88 | px, py = grid_based_sweep_coverage_path_planner.planning( 89 | ox, oy, resolution, 90 | moving_direction=RIGHT, 91 | sweeping_direction=DOWN, 92 | ) 93 | assert len(px) >= 5 94 | 95 | px, py = grid_based_sweep_coverage_path_planner.planning( 96 | ox, oy, resolution, 97 | moving_direction=LEFT, 98 | sweeping_direction=DOWN, 99 | ) 100 | assert len(px) >= 5 101 | 102 | px, py = grid_based_sweep_coverage_path_planner.planning( 103 | ox, oy, resolution, 104 | moving_direction=RIGHT, 105 | sweeping_direction=UP, 106 | ) 107 | assert len(px) >= 5 108 | 109 | px, py = grid_based_sweep_coverage_path_planner.planning( 110 | ox, oy, resolution, 111 | moving_direction=RIGHT, 112 | sweeping_direction=DOWN, 113 | ) 114 | assert len(px) >= 5 115 | 116 | 117 | if __name__ == '__main__': 118 | conftest.run_this_test(__file__) 119 | -------------------------------------------------------------------------------- /tests/test_grid_map_lib.py: -------------------------------------------------------------------------------- 1 | from Mapping.grid_map_lib.grid_map_lib import GridMap 2 | import numpy as np 3 | 4 | 5 | def test_position_set(): 6 | grid_map = GridMap(100, 120, 0.5, 10.0, -0.5) 7 | 8 | grid_map.set_value_from_xy_pos(10.1, -1.1, 1.0) 9 | grid_map.set_value_from_xy_pos(10.1, -0.1, 1.0) 10 | grid_map.set_value_from_xy_pos(10.1, 1.1, 1.0) 11 | grid_map.set_value_from_xy_pos(11.1, 0.1, 1.0) 12 | grid_map.set_value_from_xy_pos(10.1, 0.1, 1.0) 13 | grid_map.set_value_from_xy_pos(9.1, 0.1, 1.0) 14 | 15 | 16 | def test_polygon_set(): 17 | ox = [0.0, 4.35, 20.0, 50.0, 100.0, 130.0, 40.0] 18 | oy = [0.0, -4.15, -20.0, 0.0, 30.0, 60.0, 80.0] 19 | 20 | grid_map = GridMap(600, 290, 0.7, 60.0, 30.5) 21 | 22 | grid_map.set_value_from_polygon(ox, oy, 1.0, inside=False) 23 | grid_map.set_value_from_polygon(np.array(ox), np.array(oy), 24 | 1.0, inside=False) 25 | 26 | 27 | if __name__ == '__main__': 28 | conftest.run_this_test(__file__) 29 | -------------------------------------------------------------------------------- /tests/test_histogram_filter.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Localization.histogram_filter import histogram_filter as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.SIM_TIME = 1.0 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_hybrid_a_star.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.HybridAStar import hybrid_a_star as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_informed_rrt_star.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from PathPlanning.InformedRRTStar import informed_rrt_star as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_inverted_pendulum_lqr_control.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Control.inverted_pendulum import inverted_pendulum_lqr_control as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_inverted_pendulum_mpc_control.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | 3 | from Control.inverted_pendulum import inverted_pendulum_mpc_control as m 4 | 5 | 6 | def test1(): 7 | m.show_animation = False 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_iterative_closest_point.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from SLAM.iterative_closest_point import iterative_closest_point as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | def test_2(): 11 | m.show_animation = False 12 | m.main_3d_points() 13 | 14 | 15 | if __name__ == '__main__': 16 | conftest.run_this_test(__file__) 17 | -------------------------------------------------------------------------------- /tests/test_kmeans_clustering.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | from Mapping.kmeans_clustering import kmeans_clustering as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_lqr_rrt_star.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.LQRRRTStar import lqr_rrt_star as m 3 | import random 4 | 5 | random.seed(12345) 6 | 7 | 8 | def test1(): 9 | m.show_animation = False 10 | m.main(maxIter=5) 11 | 12 | 13 | if __name__ == '__main__': 14 | conftest.run_this_test(__file__) 15 | -------------------------------------------------------------------------------- /tests/test_lqr_speed_steer_control.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathTracking.lqr_speed_steer_control import lqr_speed_steer_control as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_lqr_steer_control.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathTracking.lqr_steer_control import lqr_steer_control as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_model_predictive_speed_and_steer_control.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | 3 | from PathTracking.model_predictive_speed_and_steer_control \ 4 | import model_predictive_speed_and_steer_control as m 5 | 6 | 7 | def test_1(): 8 | m.show_animation = False 9 | m.main() 10 | 11 | 12 | def test_2(): 13 | m.show_animation = False 14 | m.main2() 15 | 16 | 17 | if __name__ == '__main__': 18 | conftest.run_this_test(__file__) 19 | -------------------------------------------------------------------------------- /tests/test_move_to_pose.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from Control.move_to_pose import move_to_pose as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | def test_2(): 11 | """ 12 | This unit test tests the move_to_pose.py program for a MAX_LINEAR_SPEED and 13 | MAX_ANGULAR_SPEED 14 | """ 15 | m.show_animation = False 16 | m.MAX_LINEAR_SPEED = 11 17 | m.MAX_ANGULAR_SPEED = 5 18 | m.main() 19 | 20 | 21 | if __name__ == '__main__': 22 | conftest.run_this_test(__file__) 23 | -------------------------------------------------------------------------------- /tests/test_move_to_pose_robot.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from Control.move_to_pose import move_to_pose as m 3 | 4 | 5 | def test_1(): 6 | """ 7 | This unit test tests the move_to_pose_robot.py program 8 | """ 9 | m.show_animation = False 10 | m.main() 11 | 12 | 13 | if __name__ == '__main__': 14 | conftest.run_this_test(__file__) 15 | -------------------------------------------------------------------------------- /tests/test_mypy_type_check.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | import conftest 5 | 6 | SUBPACKAGE_LIST = [ 7 | "AerialNavigation", 8 | "ArmNavigation", 9 | "Bipedal", 10 | "Control", 11 | "Localization", 12 | "Mapping", 13 | "PathPlanning", 14 | "PathTracking", 15 | "SLAM", 16 | ] 17 | 18 | 19 | def run_mypy(dir_name, project_path, config_path): 20 | res = subprocess.run( 21 | ['mypy', 22 | '--config-file', 23 | config_path, 24 | '-p', 25 | dir_name], 26 | cwd=project_path, 27 | stdout=subprocess.PIPE, 28 | encoding='utf-8') 29 | return res.returncode, res.stdout 30 | 31 | 32 | def test(): 33 | project_dir_path = os.path.dirname( 34 | os.path.dirname(os.path.abspath(__file__))) 35 | print(f"{project_dir_path=}") 36 | 37 | config_path = os.path.join(project_dir_path, "mypy.ini") 38 | print(f"{config_path=}") 39 | 40 | for sub_package_name in SUBPACKAGE_LIST: 41 | rc, errors = run_mypy(sub_package_name, project_dir_path, config_path) 42 | if errors: 43 | print(errors) 44 | else: 45 | print("No lint errors found.") 46 | assert rc == 0 47 | 48 | 49 | if __name__ == '__main__': 50 | conftest.run_this_test(__file__) 51 | -------------------------------------------------------------------------------- /tests/test_n_joint_arm_to_point_control.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from ArmNavigation.n_joint_arm_to_point_control\ 3 | import n_joint_arm_to_point_control as m 4 | import random 5 | 6 | random.seed(12345) 7 | 8 | 9 | def test1(): 10 | m.show_animation = False 11 | m.animation() 12 | 13 | 14 | if __name__ == '__main__': 15 | conftest.run_this_test(__file__) 16 | -------------------------------------------------------------------------------- /tests/test_particle_filter.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from Localization.particle_filter import particle_filter as m 3 | 4 | 5 | def test_1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_potential_field_planning.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.PotentialFieldPlanning import potential_field_planning as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_probabilistic_road_map.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | import numpy as np 3 | from PathPlanning.ProbabilisticRoadMap import probabilistic_road_map 4 | 5 | 6 | def test1(): 7 | probabilistic_road_map.show_animation = False 8 | probabilistic_road_map.main(rng=np.random.default_rng(1233)) 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_pure_pursuit.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathTracking.pure_pursuit import pure_pursuit as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_quintic_polynomials_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.QuinticPolynomialsPlanner import quintic_polynomials_planner as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_raycasting_grid_map.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from Mapping.raycasting_grid_map import raycasting_grid_map as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_rear_wheel_feedback.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathTracking.rear_wheel_feedback import rear_wheel_feedback as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_rectangle_fitting.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from Mapping.rectangle_fitting import rectangle_fitting as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_reeds_shepp_path_planning.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import conftest # Add root path to sys.path 4 | from PathPlanning.ReedsSheppPath import reeds_shepp_path_planning as m 5 | 6 | 7 | def check_edge_condition(px, py, pyaw, start_x, start_y, start_yaw, end_x, 8 | end_y, end_yaw): 9 | assert (abs(px[0] - start_x) <= 0.01) 10 | assert (abs(py[0] - start_y) <= 0.01) 11 | assert (abs(pyaw[0] - start_yaw) <= 0.01) 12 | assert (abs(px[-1] - end_x) <= 0.01) 13 | assert (abs(py[-1] - end_y) <= 0.01) 14 | assert (abs(pyaw[-1] - end_yaw) <= 0.01) 15 | 16 | 17 | def check_path_length(px, py, lengths): 18 | sum_len = sum(abs(length) for length in lengths) 19 | dpx = np.diff(px) 20 | dpy = np.diff(py) 21 | actual_len = sum( 22 | np.hypot(dx, dy) for (dx, dy) in zip(dpx, dpy)) 23 | diff_len = sum_len - actual_len 24 | assert (diff_len <= 0.01) 25 | 26 | 27 | def test1(): 28 | m.show_animation = False 29 | m.main() 30 | 31 | 32 | def test2(): 33 | N_TEST = 10 34 | np.random.seed(1234) 35 | 36 | for i in range(N_TEST): 37 | start_x = (np.random.rand() - 0.5) * 10.0 # [m] 38 | start_y = (np.random.rand() - 0.5) * 10.0 # [m] 39 | start_yaw = np.deg2rad((np.random.rand() - 0.5) * 180.0) # [rad] 40 | 41 | end_x = (np.random.rand() - 0.5) * 10.0 # [m] 42 | end_y = (np.random.rand() - 0.5) * 10.0 # [m] 43 | end_yaw = np.deg2rad((np.random.rand() - 0.5) * 180.0) # [rad] 44 | 45 | curvature = 1.0 / (np.random.rand() * 5.0) 46 | 47 | px, py, pyaw, mode, lengths = m.reeds_shepp_path_planning( 48 | start_x, start_y, start_yaw, 49 | end_x, end_y, end_yaw, curvature) 50 | 51 | check_edge_condition(px, py, pyaw, start_x, start_y, start_yaw, end_x, 52 | end_y, end_yaw) 53 | check_path_length(px, py, lengths) 54 | 55 | 56 | if __name__ == '__main__': 57 | conftest.run_this_test(__file__) 58 | -------------------------------------------------------------------------------- /tests/test_rocket_powered_landing.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | import numpy as np 3 | from numpy.testing import suppress_warnings 4 | 5 | from AerialNavigation.rocket_powered_landing import rocket_powered_landing as m 6 | 7 | 8 | def test1(): 9 | m.show_animation = False 10 | with suppress_warnings() as sup: 11 | sup.filter(UserWarning, 12 | "You are solving a parameterized problem that is not DPP" 13 | ) 14 | sup.filter(UserWarning, 15 | "Solution may be inaccurate") 16 | m.main(rng=np.random.default_rng(1234)) 17 | 18 | 19 | if __name__ == '__main__': 20 | conftest.run_this_test(__file__) 21 | -------------------------------------------------------------------------------- /tests/test_rrt.py: -------------------------------------------------------------------------------- 1 | import conftest 2 | import random 3 | 4 | from PathPlanning.RRT import rrt as m 5 | from PathPlanning.RRT import rrt_with_pathsmoothing as m1 6 | 7 | random.seed(12345) 8 | 9 | 10 | def test1(): 11 | m.show_animation = False 12 | m.main(gx=1.0, gy=1.0) 13 | 14 | 15 | def test2(): 16 | m1.show_animation = False 17 | m1.main() 18 | 19 | 20 | if __name__ == '__main__': 21 | conftest.run_this_test(__file__) 22 | -------------------------------------------------------------------------------- /tests/test_rrt_dubins.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.RRTDubins import rrt_dubins as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_rrt_star.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.RRTStar import rrt_star as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | def test_no_obstacle(): 11 | obstacle_list = [] 12 | 13 | # Set Initial parameters 14 | rrt_star = m.RRTStar(start=[0, 0], 15 | goal=[6, 10], 16 | rand_area=[-2, 15], 17 | obstacle_list=obstacle_list) 18 | path = rrt_star.planning(animation=False) 19 | assert path is not None 20 | 21 | 22 | def test_no_obstacle_and_robot_radius(): 23 | obstacle_list = [] 24 | 25 | # Set Initial parameters 26 | rrt_star = m.RRTStar(start=[0, 0], 27 | goal=[6, 10], 28 | rand_area=[-2, 15], 29 | obstacle_list=obstacle_list, 30 | robot_radius=0.8) 31 | path = rrt_star.planning(animation=False) 32 | assert path is not None 33 | 34 | 35 | if __name__ == '__main__': 36 | conftest.run_this_test(__file__) 37 | -------------------------------------------------------------------------------- /tests/test_rrt_star_dubins.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.RRTStarDubins import rrt_star_dubins as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_rrt_star_reeds_shepp.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.RRTStarReedsShepp import rrt_star_reeds_shepp as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main(max_iter=5) 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_rrt_star_seven_joint_arm.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from ArmNavigation.rrt_star_seven_joint_arm_control \ 3 | import rrt_star_seven_joint_arm_control as m 4 | 5 | 6 | def test1(): 7 | m.show_animation = False 8 | m.main() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_rrt_with_sobol_sampler.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.RRT import rrt_with_sobol_sampler as m 3 | import random 4 | 5 | random.seed(12345) 6 | 7 | 8 | def test1(): 9 | m.show_animation = False 10 | m.main(gx=1.0, gy=1.0) 11 | 12 | 13 | if __name__ == '__main__': 14 | conftest.run_this_test(__file__) 15 | -------------------------------------------------------------------------------- /tests/test_spiral_spanning_tree_coverage_path_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | import os 3 | import matplotlib.pyplot as plt 4 | from PathPlanning.SpiralSpanningTreeCPP \ 5 | import spiral_spanning_tree_coverage_path_planner 6 | 7 | spiral_spanning_tree_coverage_path_planner.do_animation = True 8 | 9 | 10 | def spiral_stc_cpp(img, start): 11 | num_free = 0 12 | for i in range(img.shape[0]): 13 | for j in range(img.shape[1]): 14 | num_free += img[i][j] 15 | 16 | STC_planner = spiral_spanning_tree_coverage_path_planner.\ 17 | SpiralSpanningTreeCoveragePlanner(img) 18 | 19 | edge, route, path = STC_planner.plan(start) 20 | 21 | covered_nodes = set() 22 | for p, q in edge: 23 | covered_nodes.add(p) 24 | covered_nodes.add(q) 25 | 26 | # assert complete coverage 27 | assert len(covered_nodes) == num_free / 4 28 | 29 | 30 | def test_spiral_stc_cpp_1(): 31 | img_dir = os.path.dirname( 32 | os.path.abspath(__file__)) + \ 33 | "/../PathPlanning/SpiralSpanningTreeCPP" 34 | img = plt.imread(os.path.join(img_dir, 'map', 'test.png')) 35 | start = (0, 0) 36 | spiral_stc_cpp(img, start) 37 | 38 | 39 | def test_spiral_stc_cpp_2(): 40 | img_dir = os.path.dirname( 41 | os.path.abspath(__file__)) + \ 42 | "/../PathPlanning/SpiralSpanningTreeCPP" 43 | img = plt.imread(os.path.join(img_dir, 'map', 'test_2.png')) 44 | start = (10, 0) 45 | spiral_stc_cpp(img, start) 46 | 47 | 48 | def test_spiral_stc_cpp_3(): 49 | img_dir = os.path.dirname( 50 | os.path.abspath(__file__)) + \ 51 | "/../PathPlanning/SpiralSpanningTreeCPP" 52 | img = plt.imread(os.path.join(img_dir, 'map', 'test_3.png')) 53 | start = (0, 0) 54 | spiral_stc_cpp(img, start) 55 | 56 | 57 | if __name__ == '__main__': 58 | conftest.run_this_test(__file__) 59 | -------------------------------------------------------------------------------- /tests/test_stanley_controller.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathTracking.stanley_controller import stanley_controller as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_state_lattice_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.StateLatticePlanner import state_lattice_planner as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_two_joint_arm_to_point_control.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from ArmNavigation.two_joint_arm_to_point_control \ 3 | import two_joint_arm_to_point_control as m 4 | 5 | 6 | def test1(): 7 | m.show_animation = False 8 | m.animation() 9 | 10 | 11 | if __name__ == '__main__': 12 | conftest.run_this_test(__file__) 13 | -------------------------------------------------------------------------------- /tests/test_unscented_kalman_filter.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from Localization.unscented_kalman_filter import unscented_kalman_filter as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from utils import angle 3 | from numpy.testing import assert_allclose 4 | import numpy as np 5 | 6 | 7 | def test_rot_mat_2d(): 8 | assert_allclose(angle.rot_mat_2d(0.0), 9 | np.array([[1., 0.], 10 | [0., 1.]])) 11 | 12 | 13 | def test_angle_mod(): 14 | assert_allclose(angle.angle_mod(-4.0), 2.28318531) 15 | assert(isinstance(angle.angle_mod(-4.0), float)) 16 | assert_allclose(angle.angle_mod([-4.0]), [2.28318531]) 17 | assert(isinstance(angle.angle_mod([-4.0]), np.ndarray)) 18 | 19 | assert_allclose(angle.angle_mod([-150.0, 190.0, 350], degree=True), 20 | [-150., -170., -10.]) 21 | 22 | assert_allclose(angle.angle_mod(-60.0, zero_2_2pi=True, degree=True), 23 | [300.]) 24 | 25 | 26 | if __name__ == '__main__': 27 | conftest.run_this_test(__file__) 28 | -------------------------------------------------------------------------------- /tests/test_visibility_road_map_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.VoronoiRoadMap import voronoi_road_map as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_voronoi_road_map_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | from PathPlanning.VisibilityRoadMap import visibility_road_map as m 3 | 4 | 5 | def test1(): 6 | m.show_animation = False 7 | m.main() 8 | 9 | 10 | if __name__ == '__main__': 11 | conftest.run_this_test(__file__) 12 | -------------------------------------------------------------------------------- /tests/test_wavefront_coverage_path_planner.py: -------------------------------------------------------------------------------- 1 | import conftest # Add root path to sys.path 2 | import os 3 | import matplotlib.pyplot as plt 4 | from PathPlanning.WavefrontCPP import wavefront_coverage_path_planner 5 | 6 | wavefront_coverage_path_planner.do_animation = False 7 | 8 | 9 | def wavefront_cpp(img, start, goal): 10 | num_free = 0 11 | for i in range(img.shape[0]): 12 | for j in range(img.shape[1]): 13 | num_free += 1 - img[i][j] 14 | 15 | DT = wavefront_coverage_path_planner.transform( 16 | img, goal, transform_type='distance') 17 | DT_path = wavefront_coverage_path_planner.wavefront(DT, start, goal) 18 | assert len(DT_path) == num_free # assert complete coverage 19 | 20 | PT = wavefront_coverage_path_planner.transform( 21 | img, goal, transform_type='path', alpha=0.01) 22 | PT_path = wavefront_coverage_path_planner.wavefront(PT, start, goal) 23 | assert len(PT_path) == num_free # assert complete coverage 24 | 25 | 26 | def test_wavefront_CPP_1(): 27 | img_dir = os.path.dirname( 28 | os.path.abspath(__file__)) + "/../PathPlanning/WavefrontCPP" 29 | img = plt.imread(os.path.join(img_dir, 'map', 'test.png')) 30 | img = 1 - img 31 | 32 | start = (43, 0) 33 | goal = (0, 0) 34 | 35 | wavefront_cpp(img, start, goal) 36 | 37 | 38 | def test_wavefront_CPP_2(): 39 | img_dir = os.path.dirname( 40 | os.path.abspath(__file__)) + "/../PathPlanning/WavefrontCPP" 41 | img = plt.imread(os.path.join(img_dir, 'map', 'test_2.png')) 42 | img = 1 - img 43 | 44 | start = (10, 0) 45 | goal = (10, 40) 46 | 47 | wavefront_cpp(img, start, goal) 48 | 49 | 50 | def test_wavefront_CPP_3(): 51 | img_dir = os.path.dirname( 52 | os.path.abspath(__file__)) + "/../PathPlanning/WavefrontCPP" 53 | img = plt.imread(os.path.join(img_dir, 'map', 'test_3.png')) 54 | img = 1 - img 55 | 56 | start = (0, 0) 57 | goal = (30, 30) 58 | 59 | wavefront_cpp(img, start, goal) 60 | 61 | 62 | if __name__ == '__main__': 63 | conftest.run_this_test(__file__) 64 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Alexbeast-CN/PythonRobotics/6653ed1fd16dc19c02bcbc9225533dc71106697d/utils/__init__.py -------------------------------------------------------------------------------- /utils/angle.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.spatial.transform import Rotation as Rot 3 | 4 | 5 | def rot_mat_2d(angle): 6 | """ 7 | Create 2D rotation matrix from an angle 8 | 9 | Parameters 10 | ---------- 11 | angle : 12 | 13 | Returns 14 | ------- 15 | A 2D rotation matrix 16 | 17 | Examples 18 | -------- 19 | >>> angle_mod(-4.0) 20 | 21 | 22 | """ 23 | return Rot.from_euler('z', angle).as_matrix()[0:2, 0:2] 24 | 25 | 26 | def angle_mod(x, zero_2_2pi=False, degree=False): 27 | """ 28 | Angle modulo operation 29 | Default angle modulo range is [-pi, pi) 30 | 31 | Parameters 32 | ---------- 33 | x : float or array_like 34 | A angle or an array of angles. This array is flattened for 35 | the calculation. When an angle is provided, a float angle is returned. 36 | zero_2_2pi : bool, optional 37 | Change angle modulo range to [0, 2pi) 38 | Default is False. 39 | degree : bool, optional 40 | If True, then the given angles are assumed to be in degrees. 41 | Default is False. 42 | 43 | Returns 44 | ------- 45 | ret : float or ndarray 46 | an angle or an array of modulated angle. 47 | 48 | Examples 49 | -------- 50 | >>> angle_mod(-4.0) 51 | 2.28318531 52 | 53 | >>> angle_mod([-4.0]) 54 | np.array(2.28318531) 55 | 56 | >>> angle_mod([-150.0, 190.0, 350], degree=True) 57 | array([-150., -170., -10.]) 58 | 59 | >>> angle_mod(-60.0, zero_2_2pi=True, degree=True) 60 | array([300.]) 61 | 62 | """ 63 | if isinstance(x, float): 64 | is_float = True 65 | else: 66 | is_float = False 67 | 68 | x = np.asarray(x).flatten() 69 | if degree: 70 | x = np.deg2rad(x) 71 | 72 | if zero_2_2pi: 73 | mod_angle = x % (2 * np.pi) 74 | else: 75 | mod_angle = (x + np.pi) % (2 * np.pi) - np.pi 76 | 77 | if degree: 78 | mod_angle = np.rad2deg(mod_angle) 79 | 80 | if is_float: 81 | return mod_angle.item() 82 | else: 83 | return mod_angle 84 | -------------------------------------------------------------------------------- /utils/plot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Matplotlib based plotting utilities 3 | """ 4 | import math 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | 8 | 9 | def plot_arrow(x, y, yaw, arrow_length=1.0, 10 | origin_point_plot_style="xr", 11 | head_width=0.1, fc="r", ec="k", **kwargs): 12 | """ 13 | Plot an arrow or arrows based on 2D state (x, y, yaw) 14 | 15 | All optional settings of matplotlib.pyplot.arrow can be used. 16 | - matplotlib.pyplot.arrow: 17 | https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.arrow.html 18 | 19 | Parameters 20 | ---------- 21 | x : a float or array_like 22 | a value or a list of arrow origin x position. 23 | y : a float or array_like 24 | a value or a list of arrow origin y position. 25 | yaw : a float or array_like 26 | a value or a list of arrow yaw angle (orientation). 27 | arrow_length : a float (optional) 28 | arrow length. default is 1.0 29 | origin_point_plot_style : str (optional) 30 | origin point plot style. If None, not plotting. 31 | head_width : a float (optional) 32 | arrow head width. default is 0.1 33 | fc : string (optional) 34 | face color 35 | ec : string (optional) 36 | edge color 37 | """ 38 | if not isinstance(x, float): 39 | for (i_x, i_y, i_yaw) in zip(x, y, yaw): 40 | plot_arrow(i_x, i_y, i_yaw, head_width=head_width, 41 | fc=fc, ec=ec, **kwargs) 42 | else: 43 | plt.arrow(x, y, 44 | arrow_length * math.cos(yaw), 45 | arrow_length * math.sin(yaw), 46 | head_width=head_width, 47 | fc=fc, ec=ec, 48 | **kwargs) 49 | if origin_point_plot_style is not None: 50 | plt.plot(x, y, origin_point_plot_style) 51 | 52 | 53 | def plot_curvature(x_list, y_list, heading_list, curvature, 54 | k=0.01, c="-c", label="Curvature"): 55 | """ 56 | Plot curvature on 2D path. This plot is a line from the original path, 57 | the lateral distance from the original path shows curvature magnitude. 58 | Left turning shows right side plot, right turning shows left side plot. 59 | For straight path, the curvature plot will be on the path, because 60 | curvature is 0 on the straight path. 61 | 62 | Parameters 63 | ---------- 64 | x_list : array_like 65 | x position list of the path 66 | y_list : array_like 67 | y position list of the path 68 | heading_list : array_like 69 | heading list of the path 70 | curvature : array_like 71 | curvature list of the path 72 | k : float 73 | curvature scale factor to calculate distance from the original path 74 | c : string 75 | color of the plot 76 | label : string 77 | label of the plot 78 | """ 79 | cx = [x + d * k * np.cos(yaw - np.pi / 2.0) for x, y, yaw, d in 80 | zip(x_list, y_list, heading_list, curvature)] 81 | cy = [y + d * k * np.sin(yaw - np.pi / 2.0) for x, y, yaw, d in 82 | zip(x_list, y_list, heading_list, curvature)] 83 | 84 | plt.plot(cx, cy, c, label=label) 85 | for ix, iy, icx, icy in zip(x_list, y_list, cx, cy): 86 | plt.plot([ix, icx], [iy, icy], c) 87 | --------------------------------------------------------------------------------