Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable qpOASES on Windows and fix Windows build #327

Merged
merged 15 commits into from
Jun 18, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ jobs:
with:
path: workspace/src/trajopt

- name: configure-msvc
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64

- name: vcpkg build
uses: johnwason/vcpkg-action@v4
with:
Expand All @@ -36,6 +41,7 @@ jobs:
extra-args: --clean-after-build
token: ${{ github.token }}
cache-key: ci-${{ matrix.os }}
revision: master

- name: install-depends
shell: cmd
Expand All @@ -44,11 +50,6 @@ jobs:
python -m pip install colcon-common-extensions -q
python -m pip install ninja -q

- name: configure-msvc
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64

- name: build-workspace
working-directory: workspace
shell: cmd
Expand Down
2 changes: 1 addition & 1 deletion trajopt/test/simple_collision_unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SimpleCollisionTest : public testing::TestWithParam<const char*>
ResourceLocator::Ptr locator = std::make_shared<TrajOptSupportResourceLocator>();
EXPECT_TRUE(env_->init(urdf_file, srdf_file, locator));

gLogLevel = util::LevelDebug;
// gLogLevel = util::LevelDebug;

// Create plotting tool
// plotter_.reset(new tesseract_ros::ROSBasicPlotting(env_));
Expand Down
51 changes: 51 additions & 0 deletions trajopt_ext/qpoases/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.2.1)
find_package(ros_industrial_cmake_boilerplate REQUIRED)

extract_package_metadata(pkg)
project(qpoases VERSION ${pkg_extracted_version} LANGUAGES CXX)

find_package(qpoases QUIET)
johnwason marked this conversation as resolved.
Show resolved Hide resolved

if(NOT qpOASES_FOUND)
message(WARNING "No valid qpOASES version found. Cloning into build directory")

include(ExternalProject)

ExternalProject_Add(
${PROJECT_NAME}
GIT_REPOSITORY "https://github.com/coin-or/qpOASES.git"
GIT_TAG 0b86dbf00c7fce34420bedc5914f71b176fe79d3
SOURCE_DIR ${CMAKE_BINARY_DIR}-src
BINARY_DIR ${CMAKE_BINARY_DIR}-build
PATCH_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/patch_qpoases.cmake
CMAKE_CACHE_ARGS
-DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE:STRING=Release
-DCMAKE_TOOLCHAIN_FILE:STRING=${CMAKE_TOOLCHAIN_FILE}
-DVCPKG_TARGET_TRIPLET:STRING=${VCPKG_TARGET_TRIPLET}
-DBUILD_SHARED_LIBS:BOOL=ON
-DQPOASES_BUILD_EXAMPLES:BOOL=OFF)

if(TRAJOPT_PACKAGE)
find_package(ros_industrial_cmake_boilerplate REQUIRED)
set(CPACK_BUILD_SOURCE_DIRS "${CMAKE_BINARY_DIR}-src;${CMAKE_BINARY_DIR}-build")
set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_BINARY_DIR}-build;${PROJECT_NAME};ALL;/")
cpack(
VERSION
${pkg_extracted_version}
MAINTAINER
<https://github.com/tesseract-robotics/trajopt>
VENDOR
"ROS-Industrial"
DESCRIPTION
${pkg_extracted_description}
PACKAGE_PREFIX
${TRAJOPT_PACKAGE_PREFIX}
LINUX_DEPENDS
"libeigen3-dev"
WINDOWS_DEPENDS
"Eigen3")
endif()
endif()

install(FILES package.xml DESTINATION share/${PROJECT_NAME})
3 changes: 3 additions & 0 deletions trajopt_ext/qpoases/colcon.pkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"hooks": ["share/qpoases/hook/ament_prefix_path.dsv", "share/qpoases/hook/ros_package_path.dsv"]
}
15 changes: 15 additions & 0 deletions trajopt_ext/qpoases/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<package format="2">
<name>qpoases</name>
<version>3.2.1</version>
<description>Downloads and builds the qpOASES Library</description>
<maintainer email="[email protected]">Levi Armstrong</maintainer>
<license>LGPL</license>

<build_depend>ros_industrial_cmake_boilerplate</build_depend>

<export>
<build_type>cmake</build_type>
</export>

</package>
12 changes: 12 additions & 0 deletions trajopt_ext/qpoases/patch_qpoases.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
file(READ CMakeLists.txt ROOT_FILE)
string(
REPLACE "MESSAGE(FATAL_ERROR \"Compiling qpOASES as a shared library in Windows is not supported.\")"
"set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)\ninclude(GNUInstallDirs)"
ROOT_FILE2
${ROOT_FILE})
string(
REPLACE "SET(CMAKE_INSTALL_BINDIR \${CMAKE_INSTALL_LIBDIR})"
""
ROOT_FILE3
${ROOT_FILE2})
file(WRITE CMakeLists.txt ${ROOT_FILE3})
6 changes: 3 additions & 3 deletions trajopt_sco/include/trajopt_sco/solver_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace sco
* @param [in] n_vars the number of variables in expr. It is usually equal
* to `expr.size()`, but it might be larger.
*/
void exprToEigen(const AffExpr& expr, Eigen::SparseVector<double>& sparse_vector, const int& n_vars);
void exprToEigen(const AffExpr& expr, Eigen::SparseVector<double>& sparse_vector, const Eigen::Index& n_vars);

/**
* @brief transform a `QuadExpr` to an `Eigen::SparseMatrix` plus
Expand All @@ -40,7 +40,7 @@ void exprToEigen(const AffExpr& expr, Eigen::SparseVector<double>& sparse_vector
void exprToEigen(const QuadExpr& expr,
Eigen::SparseMatrix<double>& sparse_matrix,
Eigen::VectorXd& vector,
const int& n_vars,
const Eigen::Index& n_vars,
const bool& matrix_is_halved = false,
const bool& force_diagonal = false);

Expand All @@ -64,7 +64,7 @@ void exprToEigen(const QuadExpr& expr,
void exprToEigen(const AffExprVector& expr_vec,
Eigen::SparseMatrix<double>& sparse_matrix,
Eigen::VectorXd& vector,
const int& n_vars = -1);
const Eigen::Index& n_vars = -1);
/**
* @brief Converts triplets to an `Eigen::SparseMatrix`.
* @param [in] rows_i a vector of row indices
Expand Down
1 change: 1 addition & 0 deletions trajopt_sco/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<build_export_depend>eigen</build_export_depend>
<depend>libjsoncpp-dev</depend>
<depend>osqp</depend>
<depend>qpoases</depend>
<depend>trajopt_utils</depend>
<depend>boost</depend>

Expand Down
40 changes: 21 additions & 19 deletions trajopt_sco/src/qpoases_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,35 @@ Cnt qpOASESModel::addIneqCnt(const AffExpr& expr, const std::string& /*name*/)
Cnt qpOASESModel::addIneqCnt(const QuadExpr&, const std::string& /*name*/)
{
assert(0 && "NOT IMPLEMENTED");
return 0;
return {};
}

void qpOASESModel::removeVars(const VarVector& vars)
{
IntVec inds;
vars2inds(vars, inds);
for (unsigned i = 0; i < vars.size(); ++i)
for (size_t i = 0; i < vars.size(); ++i)
vars[i].var_rep->removed = true;
}

void qpOASESModel::removeCnts(const CntVector& cnts)
{
IntVec inds;
cnts2inds(cnts, inds);
for (unsigned i = 0; i < cnts.size(); ++i)
for (size_t i = 0; i < cnts.size(); ++i)
cnts[i].cnt_rep->removed = true;
}

void qpOASESModel::updateObjective()
{
const size_t n = vars_.size();
const Eigen::Index n = Eigen::Index(vars_.size());

Eigen::SparseMatrix<double> sm;
exprToEigen(objective_, sm, g_, n, true, true);
eigenToCSC(sm, H_row_indices_, H_column_pointers_, H_csc_data_);

H_ = SymSparseMat(vars_.size(), vars_.size(), H_row_indices_.data(), H_column_pointers_.data(), H_csc_data_.data());
H_ = SymSparseMat(
(int)vars_.size(), (int)vars_.size(), H_row_indices_.data(), H_column_pointers_.data(), H_csc_data_.data());
H_.createDiagInfo();
}

Expand All @@ -106,16 +107,17 @@ void qpOASESModel::updateConstraints()

Eigen::SparseMatrix<double> sm;
Eigen::VectorXd v;
exprToEigen(cnt_exprs_, sm, v, n);
exprToEigen(cnt_exprs_, sm, v, Eigen::Index(n));

for (int i_cnt = 0; i_cnt < m; ++i_cnt)
for (size_t i_cnt = 0; i_cnt < m; ++i_cnt)
{
lbA_[i_cnt] = (cnt_types_[i_cnt] == INEQ) ? -QPOASES_INFTY : v[i_cnt];
ubA_[i_cnt] = v[i_cnt];
lbA_[i_cnt] = (cnt_types_[i_cnt] == INEQ) ? -QPOASES_INFTY : v[Eigen::Index(i_cnt)];
ubA_[i_cnt] = v[Eigen::Index(i_cnt)];
}

eigenToCSC(sm, A_row_indices_, A_column_pointers_, A_csc_data_);
A_ = SparseMatrix(cnts_.size(), vars_.size(), A_row_indices_.data(), A_column_pointers_.data(), A_csc_data_.data());
A_ = SparseMatrix(
(int)cnts_.size(), (int)vars_.size(), A_row_indices_.data(), A_column_pointers_.data(), A_csc_data_.data());
}

bool qpOASESModel::updateSolver()
Expand All @@ -140,8 +142,8 @@ void qpOASESModel::createSolver()
void qpOASESModel::update()
{
{
int inew = 0;
for (unsigned iold = 0; iold < vars_.size(); ++iold)
size_t inew = 0;
for (size_t iold = 0; iold < vars_.size(); ++iold)
{
Var& var = vars_[iold];
if (!var.var_rep->removed)
Expand All @@ -162,10 +164,10 @@ void qpOASESModel::update()
ub_.resize(inew, -QPOASES_INFTY);
}
{
int inew = 0;
for (unsigned iold = 0; iold < cnts_.size(); ++iold)
size_t inew = 0;
for (size_t iold = 0; iold < cnts_.size(); ++iold)
{
const Cnt& cnt = cnts_[iold];
Cnt& cnt = cnts_[iold];
Levi-Armstrong marked this conversation as resolved.
Show resolved Hide resolved
if (!cnt.cnt_rep->removed)
{
cnts_[inew] = cnt;
Expand All @@ -187,19 +189,19 @@ void qpOASESModel::update()

void qpOASESModel::setVarBounds(const VarVector& vars, const DblVec& lower, const DblVec& upper)
{
for (unsigned i = 0; i < vars.size(); ++i)
for (size_t i = 0; i < vars.size(); ++i)
{
const int varind = vars[i].var_rep->index;
const size_t varind = vars[i].var_rep->index;
lb_[varind] = lower[i];
ub_[varind] = upper[i];
}
}
DblVec qpOASESModel::getVarValues(const VarVector& vars) const
{
DblVec out(vars.size());
for (unsigned i = 0; i < vars.size(); ++i)
for (size_t i = 0; i < vars.size(); ++i)
{
const int varind = vars[i].var_rep->index;
const size_t varind = vars[i].var_rep->index;
out[i] = solution_[varind];
}
return out;
Expand Down
6 changes: 3 additions & 3 deletions trajopt_sco/src/solver_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ TRAJOPT_IGNORE_WARNINGS_POP

namespace sco
{
void exprToEigen(const AffExpr& expr, Eigen::SparseVector<double>& sparse_vector, const int& n_vars)
void exprToEigen(const AffExpr& expr, Eigen::SparseVector<double>& sparse_vector, const Eigen::Index& n_vars)
{
sparse_vector.resize(n_vars);
sparse_vector.reserve(static_cast<long int>(expr.size()));
Expand All @@ -31,7 +31,7 @@ void exprToEigen(const AffExpr& expr, Eigen::SparseVector<double>& sparse_vector
void exprToEigen(const QuadExpr& expr,
Eigen::SparseMatrix<double>& sparse_matrix,
Eigen::VectorXd& vector,
const int& n_vars,
const Eigen::Index& n_vars,
const bool& matrix_is_halved,
const bool& force_diagonal)
{
Expand Down Expand Up @@ -85,7 +85,7 @@ void exprToEigen(const QuadExpr& expr,
void exprToEigen(const AffExprVector& expr_vec,
Eigen::SparseMatrix<double>& sparse_matrix,
Eigen::VectorXd& vector,
const int& n_vars)
const Eigen::Index& n_vars)
{
vector.resize(static_cast<long int>(expr_vec.size()));
vector.setZero();
Expand Down
11 changes: 7 additions & 4 deletions trajopt_sco/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ endif()

include(GoogleTest)

set(SCO_TEST_SOURCE
unit.cpp
set(SCO_TEST_SOURCE unit.cpp solver-utils-unit.cpp)
if(HAVE_GUROBI OR HAVE_qpOASES)
list(
APPEND
SCO_TEST_SOURCE
small-problems-unit.cpp
solver-interface-unit.cpp
solver-utils-unit.cpp)
solver-interface-unit.cpp)
endif()

add_executable(${PROJECT_NAME}-test ${SCO_TEST_SOURCE})
target_link_libraries(
Expand Down