Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into tmp-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
quimortiz committed Nov 8, 2023
2 parents 2982993 + 4fc68b3 commit a58153d
Show file tree
Hide file tree
Showing 10 changed files with 745 additions and 57 deletions.
18 changes: 11 additions & 7 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
submodules: recursive

- name: Install system dependencies
run: sudo apt update && sudo apt install libboost-all-dev libfcl-dev cmake libeigen3-dev libyaml-cpp-dev liblz4-dev python3-pip texlive latexmk texlive-latex-extra texlive-science -y
run: sudo apt update && sudo apt install libboost-all-dev libfcl-dev cmake libeigen3-dev libyaml-cpp-dev liblz4-dev python3-pip texlive latexmk texlive-latex-extra texlive-science coinor-libipopt-dev -y

- name: install crocoddyl
run: |
Expand All @@ -38,9 +38,13 @@ jobs:
- name: Install latest ompl
run: |
# sudo apt install libompl-dev -y
cd
mkdir __local
git clone https://github.com/ompl/ompl
cd ompl && mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=~/__local && make install -j8
cd ompl
git checkout e2994e5
mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=~/__local && make install -j4
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
Expand All @@ -52,7 +56,7 @@ jobs:
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
continue-on-error: true
# continue-on-error: true
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
Expand All @@ -62,7 +66,7 @@ jobs:
- name: Check pip
run: pip3 install numpy matplotlib scipy pyyaml pandas

- name: Python
working-directory: ${{github.workspace}}/build
run: |
python3 ../benchmark/test.py
# - name: Python
# working-directory: ${{github.workspace}}/build
# run: |
# python3 ../benchmark/test.py
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "dynobench"]
path = dynobench
url = git@github.com:quimortiz/dynobench
url = git@github.com:quimortiz/dynobench
[submodule "deps/nigh"]
path = deps/nigh
url = https://github.com/UNC-Robotics/nigh.git
Expand Down
23 changes: 21 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ project(
# find_package(pinocchio REQUIRED)
find_package(Boost REQUIRED COMPONENTS program_options serialization
stacktrace_basic)
find_package(ompl 1.6 REQUIRED)
find_package(ompl REQUIRED)

include(FindThreads)

Expand Down Expand Up @@ -57,6 +57,8 @@ add_executable(from_boost_to_msgpack

add_executable(main_sst ./src/ompl/main_sst.cpp)
add_executable(main_optimization ./src/optimization/main_optimization.cpp)
add_executable(main_multirobot_optimization
./src/optimization/main_multirobot_optimization.cpp)

add_executable(main_dbastar ./src/dbastar/main_dbastar.cpp)
add_executable(main_idbastar ./src/idbastar/main_idbastar.cpp)
Expand Down Expand Up @@ -103,6 +105,12 @@ target_include_directories(
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)

target_include_directories(
main_multirobot_optimization
PUBLIC $<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)

target_include_directories(
sst
PUBLIC $<INSTALL_INTERFACE:include> ${OMPL_INCLUDE_DIRS}
Expand Down Expand Up @@ -224,7 +232,7 @@ target_link_libraries(
optimization
PUBLIC Eigen3::Eigen dynobench::dynobench
PRIVATE ${CROCODDYL_LIBRARIES} fcl yaml-cpp Boost::program_options
Boost::serialization)
Boost::serialization libipopt.so)

target_link_libraries(
main_optimization
Expand All @@ -237,5 +245,16 @@ target_link_libraries(
Boost::program_options
Boost::serialization)

target_link_libraries(
main_multirobot_optimization
PRIVATE ${CROCODDYL_LIBRARIES}
optimization
Eigen3::Eigen
dynobench::dynobench
fcl
yaml-cpp
Boost::program_options
Boost::serialization)

enable_testing()
add_subdirectory(test)
42 changes: 19 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
# Dynoplan 🦖

<!---
<p align="center">
<img src="https://github.com/quimortiz/dynoplan/assets/32126190/87259a14-cbe4-4f9f-9cbb-47053cde594f">
</p >
-->
<p>
<p align="center">
<img src="https://github.com/quimortiz/dynoplan/assets/32126190/b14905b7-8a8b-435e-be6e-11dfc49f909a">
</p >

Dynoplan is a small library for solving kinodynamic motion planning problems, as defined in [Dynobench](https://github.com/quimortiz/dynobench) :t-rex:. It implements 3 different algorithms: Trajectory Optimization with geometric initial guess (RRT*-TO), Sample based Motion Planning (SST*), and Iterative Search and Optimization (iDb-A*).

<p align="center">
<img src="assets/example1.png" width=60% height=auto>
</p >





The first version [kinodynamic-motion-planning-benchmark](https://github.com/imrCLab/kinodynamic-motion-planning-benchmark) is now deprecated.

## Robots and Problem Description
Expand Down Expand Up @@ -98,48 +105,37 @@ https://drive.google.com/file/d/1OLuw5XICTueoZuleXOuD6vNh3PCWfHif/view?usp=drive

## How to generate motion primitives for new systems

We will show how to generate motion primitives for the `integrator1_2d_v0`

Step one: Implement the Dynamics in Dynobench, Following the tutorial for the `Integrator2_2d` in the `README`
* Step one: Implement the Dynamics in Dynobench, following the tutorial for the `Integrator2_2d` in the `README` (in this case `integrator1_2d_v0` is already implemented)

* Step two: Solve Optimization Problems with Random Start and Goals
```
```

Step two: Solve Optimization Problems with Random Start and Goals

```
./main_primitives --mode_gen_id 0 --dynamics integrator1_2d_v0 --models_base_path ../dynobench/models/ --max_num_primitives 200 --out_file /tmp/my_motions.bin
```
Primitives will be store in `/tmp/my_motions.bin` and `/tmp/my_motions.bin.yaml`

Primitives will be store in `/tmp/my_motions.bin` and `/tmp/my_motions.bin.yaml`. You can pass options to the solver for trajectory optimization.

Step Three: Improve the quality of the primitives
* Step Three: Improve the cost of the primitives

```
./main_primitives --mode_gen_id 1 --dynamics integrator1_2d_v0 --models_base_path ../dynobench/models/ --max_num_primitives 200 --in_file /tmp/my_motions.bin --solver_id 1
```

By default, primitives are stored in `/tmp/my_motions.bin.im.bin` and `/tmp/my_motions.bin.im.bin.yaml`
By default, primitives are stored in `/tmp/my_motions.bin.im.bin` and `/tmp/my_motions.bin.im.bin.yaml`. You can pass options to the solver for trajectory optimization.


Step Fours: Randomnly cut primitives
* Step Fours: Randomnly cut primitives

```
m4 main_primitives && ./main_primitives --mode_gen_id 2 --in_file /tmp/my_motions.bin.im.bin --max_num_primitives -1 --max_splits 1 --max_length_cut 50 --min_length_cut 5 --dynamics integrator1_2d_v0 --models_base_path ../dynobench/models/
./main_primitives --mode_gen_id 2 --in_file /tmp/my_motions.bin.im.bin --max_num_primitives -1 --max_splits 1 --max_length_cut 50 --min_length_cut 5 --dynamics integrator1_2d_v0 --models_base_path ../dynobench/models/
```

By default, primitives will be stored in `/tmp/my_motions.bin.im.bin.sp.bin` and `/tmp/my_motions.bin.im.bin.sp.bin.yaml`



Done!

`main_primitives` provide more utils, such as conversion between formats, computing statistics, generating primitives with random rollouts, sorting primitives and resampling of primitives
Additionally, `main_primitives` provide more useful functionality, such as conversion between formats, computing statistics, generating primitives with random rollouts, sorting primitives and resampling of primitives.


## Benchmark
Expand Down
2 changes: 1 addition & 1 deletion dynobench
Submodule dynobench updated 59 files
+6 −8 .github/workflows/build_test.yml
+14 −0 .github/workflows/pre-commit.yml
+1 −0 .gitignore
+18 −23 .pre-commit-config.yaml
+13 −5 CMakeLists.txt
+2 −2 README.md
+50 −0 envs/multirobot/example/gen_p10_n2_6_hetero.yaml
+11 −0 envs/multirobot/example/swap2_trailer.yaml
+11 −0 envs/multirobot/example/swap2_unicycle2.yaml
+23 −0 envs/multirobot/example/swap4_unicycle.yaml
+132 −0 envs/multirobot/guess_indiv_straight.yaml
+230 −0 envs/multirobot/results/swap2_trailer_db.yaml
+293 −0 envs/multirobot/results/swap2_trailer_solution.yaml
+266 −0 envs/multirobot/results/swap2_unicycle2_db.yaml
+399 −0 envs/multirobot/results/swap2_unicycle2_solution.yaml
+434 −0 envs/multirobot/results/swap4_unicycle_db.yaml
+637 −0 envs/multirobot/results/swap4_unicycle_solution.yaml
+11 −0 envs/multirobot/straight.yaml
+8 −0 envs/multirobot/swap1_trailer.yaml
+97 −0 envs/multirobot/swap1_trailer_db.yaml
+8 −0 envs/multirobot/swap1_trailer_initguess.yaml
+2 −2 envs/quad2d_v0/quad2d_recovery_obs.yaml
+2 −2 envs/quad2dpole_v0/window_hard.yaml
+7 −0 include/dynobench/acrobot.hpp
+5 −1 include/dynobench/car.hpp
+6 −0 include/dynobench/car2.hpp
+15 −4 include/dynobench/integrator1_2d.hpp
+8 −1 include/dynobench/integrator2_2d.hpp
+69 −0 include/dynobench/joint_robot.hpp
+11 −1 include/dynobench/motions.hpp
+177 −0 include/dynobench/multirobot_trajectory.hpp
+7 −0 include/dynobench/planar_rotor.hpp
+7 −0 include/dynobench/planar_rotor_pole.hpp
+7 −0 include/dynobench/quadrotor.hpp
+5 −0 include/dynobench/robot_models.hpp
+12 −0 include/dynobench/robot_models_base.hpp
+5 −0 include/dynobench/unicycle1.hpp
+7 −0 include/dynobench/unicycle2.hpp
+14 −0 models/car_first_order_with_1_trailers_0.yaml
+3 −0 models/double_integrator_0.yaml
+9 −0 models/unicycle_first_order_0.yaml
+10 −0 models/unicycle_first_order_0_sphere.yaml
+11 −0 models/unicycle_second_order_0.yaml
+12 −0 src/car.cpp
+94 −0 src/check_trajectory_multirobot.cpp
+13 −10 src/integrator1_2d.cpp
+5 −1 src/integrator2_2d.cpp
+300 −0 src/joint_robot.cpp
+10 −12 src/motions.cpp
+17 −1 src/robot_models.cpp
+17 −0 src/robot_models_base.cpp
+16 −0 src/unicycle1.cpp
+1 −1 src/unicycle2.cpp
+347 −2 test/test_models.cpp
+1 −1 utils/viewer/integrator1_2d_viewer.py
+1 −1 utils/viewer/quad2dpole_viewer.py
+18 −30 utils/viewer/view_motions.py
+2 −1 utils/viewer/viewer_test.py
+40 −9 utils/viewer/viewer_utils.py
35 changes: 35 additions & 0 deletions src/optimization/generate_ocp.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@


#include "dynoplan/optimization/generate_ocp.hpp"
#include "dynobench/joint_robot.hpp"

namespace dynoplan {

Expand Down Expand Up @@ -100,6 +101,40 @@ generate_problem(const Generate_params &gen_args,

std::vector<ptr<Cost>> feats_run;

if (gen_args.model_robot->name == "joint_robot") {

auto ptr_derived = std::dynamic_pointer_cast<dynobench::Joint_robot>(
gen_args.model_robot);

std::vector<int> goal_times = ptr_derived->goal_times;

print_vec(goal_times.data(), goal_times.size());
CSTR_(gen_args.N);


if (goal_times.size()) {
Eigen::VectorXd weights = Eigen::VectorXd::Zero(nx);
for (size_t j = 0; j < goal_times.size(); j++) {
if (goal_times.at(j) <= t + 1) {
size_t start_index = std::accumulate(
ptr_derived->nxs.begin(), ptr_derived->nxs.begin() + j, 0);
size_t nx = ptr_derived->nxs.at(j);
weights.segment(start_index, nx).setOnes();
}
}

if (weights.sum() > 1e-12) {
std::cout << "warning, adding special goal cost" << std::endl;
ptr<Cost> state_feature = mk<State_cost_model>(
gen_args.model_robot, nx, nu,
gen_args.penalty * options_trajopt.weight_goal * weights,
gen_args.goal);

feats_run.emplace_back(state_feature);
}
}
}

if (control_mode == Control_Mode::free_time_linear) {
if (t > 0)
feats_run.emplace_back(mk<Time_linear_reg>(nx, nu));
Expand Down
139 changes: 139 additions & 0 deletions src/optimization/main_multirobot_optimization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include <algorithm>
#include <boost/program_options.hpp>
#include <chrono>
#include <fstream>
#include <iostream>
#include <iterator>
#include <yaml-cpp/yaml.h>
#include "dynobench/multirobot_trajectory.hpp"

// OMPL headers

#include <dynoplan/optimization/ocp.hpp>


bool execute_optimizationMultiRobot(const std::string &env_file,
const std::string &initial_guess_file,
const std::string &output_file,
const std::string &dynobench_base,
bool sum_robots_cost) {

using namespace dynoplan;
using namespace dynobench;

Options_trajopt options_trajopt;
Problem problem(env_file);

MultiRobotTrajectory init_guess_multi_robot;
init_guess_multi_robot.read_from_yaml(initial_guess_file.c_str());



std::vector<int> goal_times(init_guess_multi_robot.trajectories.size());

std::transform(init_guess_multi_robot.trajectories.begin(),
init_guess_multi_robot.trajectories.end(), goal_times.begin(),
[](const Trajectory &traj) { return traj.states.size(); });

Trajectory init_guess;

std::cout << "goal times are " << std::endl;

for (auto &t : goal_times) {
std::cout << t << std::endl;
}

if (sum_robots_cost) {
std::cout
<< "warning: new approach where each robot tries to reach the goal fast"
<< std::endl;
problem.goal_times = goal_times;
}

else {
std::cout
<< "warning: old apprach, robots will reach the goals at the same time "
<< std::endl;
}

options_trajopt.solver_id = 1; // static_cast<int>(SOLVER::traj_opt);
options_trajopt.control_bounds = 1;
options_trajopt.use_warmstart = 1;
options_trajopt.weight_goal = 100;
options_trajopt.max_iter = 50;
problem.models_base_path = dynobench_base + std::string("models/");

Result_opti result;
Trajectory sol;

dynobench::Trajectory init_guess_joint =
init_guess_multi_robot.transform_to_joint_trajectory();
init_guess.to_yaml_format("/tmp/check2.yaml");

trajectory_optimization(problem, init_guess_joint, options_trajopt, sol,
result);
if (!result.feasible) {
std::cout << "optimization infeasible" << std::endl;
return false;
}

std::cout << "optimization done! " << std::endl;
std::vector<int> index_time_goals;

if (problem.goal_times.size()) {
index_time_goals = sol.multi_robot_index_goal;
} else {
size_t num_robots = init_guess_multi_robot.get_num_robots();
index_time_goals = std::vector<int>(num_robots, sol.states.size());
}

MultiRobotTrajectory multi_out = from_joint_to_indiv_trajectory(
sol, init_guess_multi_robot.get_nxs(), init_guess_multi_robot.get_nus(),
index_time_goals);

multi_out.to_yaml_format("/tmp/check5.yaml");
multi_out.to_yaml_format(output_file.c_str());


return true;

}


int main(int argc, char *argv[]) {

namespace po = boost::program_options;
po::options_description desc("Allowed options");
std::string envFile;
std::string initFile;
std::string outFile;
std::string dynobench_base;
bool sum_robots_cost = true;
desc.add_options()("help", "produce help message")(
"env,e", po::value<std::string>(&envFile)->required())(
"init,i", po::value<std::string>(&initFile)->required())(
"out,o", po::value<std::string>(&outFile)->required())
(
"base,b", po::value<std::string>(&dynobench_base)->required())

(
"sum,s", po::value<bool>(&sum_robots_cost)->required());

try {
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);

if (vm.count("help") != 0u) {
std::cout << desc << "\n";
return 0;
}
} catch (po::error &e) {
std::cerr << e.what() << std::endl << std::endl;
std::cerr << desc << std::endl;
return 1;
}

execute_optimizationMultiRobot(envFile, initFile, outFile,
dynobench_base, sum_robots_cost);
}
Loading

0 comments on commit a58153d

Please sign in to comment.