Skip to content

Basic class based Matlab interface. #13

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

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
164 changes: 163 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,169 @@ if (${BUILD_MATLAB_INTERFACE})
COPY ${MATLAB_INTERFACE_DIR}/${MATLAB_INTERFACE_NAME}.m
DESTINATION ${MATLAB_INTERFACE_DESTINATION}
)


file(
COPY ${MATLAB_INTERFACE_DIR}/${MATLAB_INTERFACE_NAME}_options.m
DESTINATION ${MATLAB_INTERFACE_DESTINATION}
)

# HERE STARTS A HACK
# Copy over new interface .m file
file(
COPY ${MATLAB_INTERFACE_DIR}/@LCQProblem/LCQProblem.m
DESTINATION ${MATLAB_INTERFACE_DESTINATION}/@LCQProblem
)
# Include new matlab interface stuff
# constructProblem
matlab_add_mex(
NAME constructProblem
SRC ${MATLAB_INTERFACE_DIR}/@LCQProblem/constructProblem.cpp
OUTPUT_NAME ${MATLAB_INTERFACE_DESTINATION}/@LCQProblem/constructProblem
LINK_TO "-llcqpow -lqpOASES -losqp -lmwblas -lmwlapack -lmwma57"
)

target_link_directories(
constructProblem
PUBLIC ${CMAKE_BINARY_DIR}/lib
)

target_compile_options(
constructProblem
PUBLIC -D${DEF_SOLVER}
PUBLIC -D__USE_LONG_FINTS__
PUBLIC -D__MATLAB__
PUBLIC -D__NO_COPYRIGHT__
PUBLIC -D__cpluplus
PUBLIC -O
PUBLIC -largeArrayDims
PUBLIC -lmwblas
PUBLIC -lmwlapack
PUBLIC -lmwma57
PUBLIC -llcqpow
PUBLIC -lqpOASES
PUBLIC -losqp
)

target_include_directories(
constructProblem
PRIVATE include
SYSTEM ${osqp_include}
SYSTEM ${qpoases_include}
)

# destructProblem
matlab_add_mex(
NAME destructProblem
SRC ${MATLAB_INTERFACE_DIR}/@LCQProblem/destructProblem.cpp
OUTPUT_NAME ${MATLAB_INTERFACE_DESTINATION}/@LCQProblem/destructProblem
LINK_TO "-llcqpow -lqpOASES -losqp -lmwblas -lmwlapack -lmwma57"
)

target_link_directories(
destructProblem
PUBLIC ${CMAKE_BINARY_DIR}/lib
)

target_compile_options(
destructProblem
PUBLIC -D${DEF_SOLVER}
PUBLIC -D__USE_LONG_FINTS__
PUBLIC -D__MATLAB__
PUBLIC -D__NO_COPYRIGHT__
PUBLIC -D__cpluplus
PUBLIC -O
PUBLIC -largeArrayDims
PUBLIC -lmwblas
PUBLIC -lmwlapack
PUBLIC -lmwma57
PUBLIC -llcqpow
PUBLIC -lqpOASES
PUBLIC -losqp
)

target_include_directories(
destructProblem
PRIVATE include
SYSTEM ${osqp_include}
SYSTEM ${qpoases_include}
)

# loadLCQP
matlab_add_mex(
NAME loadLCQP
SRC ${MATLAB_INTERFACE_DIR}/@LCQProblem/loadLCQP.cpp
OUTPUT_NAME ${MATLAB_INTERFACE_DESTINATION}/@LCQProblem/loadLCQP
LINK_TO "-llcqpow -lqpOASES -losqp -lmwblas -lmwlapack -lmwma57"
)

target_link_directories(
loadLCQP
PUBLIC ${CMAKE_BINARY_DIR}/lib
)

target_compile_options(
loadLCQP
PUBLIC -D${DEF_SOLVER}
PUBLIC -D__USE_LONG_FINTS__
PUBLIC -D__MATLAB__
PUBLIC -D__NO_COPYRIGHT__
PUBLIC -D__cpluplus
PUBLIC -O
PUBLIC -largeArrayDims
PUBLIC -lmwblas
PUBLIC -lmwlapack
PUBLIC -lmwma57
PUBLIC -llcqpow
PUBLIC -lqpOASES
PUBLIC -losqp
PUBLIC -g
)

target_include_directories(
loadLCQP
PRIVATE include
SYSTEM ${osqp_include}
SYSTEM ${qpoases_include}
)

# runProblem
matlab_add_mex(
NAME runProblem
SRC ${MATLAB_INTERFACE_DIR}/@LCQProblem/runProblem.cpp
OUTPUT_NAME ${MATLAB_INTERFACE_DESTINATION}/@LCQProblem/runProblem
LINK_TO "-llcqpow -lqpOASES -losqp -lmwblas -lmwlapack -lmwma57"
)

target_link_directories(
runProblem
PUBLIC ${CMAKE_BINARY_DIR}/lib
)

target_compile_options(
runProblem
PUBLIC -D${DEF_SOLVER}
PUBLIC -D__USE_LONG_FINTS__
PUBLIC -D__MATLAB__
PUBLIC -D__NO_COPYRIGHT__
PUBLIC -D__cpluplus
PUBLIC -O
PUBLIC -largeArrayDims
PUBLIC -lmwblas
PUBLIC -lmwlapack
PUBLIC -lmwma57
PUBLIC -llcqpow
PUBLIC -lqpOASES
PUBLIC -losqp
PUBLIC -g
)

target_include_directories(
runProblem
PRIVATE include
SYSTEM ${osqp_include}
SYSTEM ${qpoases_include}
)

endif()

endif()
Expand Down
24 changes: 24 additions & 0 deletions include/LCQProblem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,30 @@ namespace LCQPow {
*/
inline void setOptions( const Options& _options );

/** Get nV
*
* @return Returns nV.
*/
int getNV() const;

/** Get nV
*
* @return Returns nC.
*/
int getNC() const;

/** Get nV
*
* @return Returns nComp.
*/
int getNComp() const;

/** Get (a copy of) Options object
*
* @return Returns deep copy of current Options object.
*/
Options getOptions() const;


/**
* PROTECTED METHODS
Expand Down
3 changes: 2 additions & 1 deletion include/Utilities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ namespace LCQPow {

/** Clear sparse matrix **/
static void ClearSparseMat(csc* M);
static void ClearSparseMatCPP(csc* M);


/** Clear sparse matrix **/
Expand Down Expand Up @@ -368,4 +369,4 @@ namespace LCQPow {
};
}

#endif // LCQPOW_UTILITIES_HPP
#endif // LCQPOW_UTILITIES_HPP
29 changes: 29 additions & 0 deletions interfaces/matlab/@LCQProblem/LCQProblem.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
classdef LCQProblem < handle
properties%(Access=private)
self % ptr to C++ LCQProblem object. On a 64 bit x86
end

methods
% Constuctor
function obj = LCQProblem(nV, nC, nComp)
obj.constructProblem(nV, nC, nComp);
end


%
loadLCQP(obj, Q, g, L, R, lbL, ubL, lbR, ubR, A, lbA, ubA, lb, ub, opts);

%
[varargout] = runSolver(obj);

function delete(obj)
% obj is always scalar, if it isn't we panic :)
obj.destructProblem();
end
end

methods(Access=private)
constructProblem(obj, nV, nC, nComp);
destructProblem(obj);
end
end
85 changes: 85 additions & 0 deletions interfaces/matlab/@LCQProblem/constructProblem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* This file is part of LCQPow.
*
* LCQPow -- A Solver for Quadratic Programs with Commplementarity Constraints.
* Copyright (C) 2020 - 2022 by Jonas Hall et al.
*
* LCQPow is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* LCQPow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with LCQPow; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "mex.hpp"
#include "mexAdapter.hpp"
#include "LCQProblem.hpp"
#include <cstdint>

using namespace matlab::data;
using matlab::mex::ArgumentList;

class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
std::shared_ptr<matlab::engine::MATLABEngine> matlab = getEngine();
matlab::data::ArrayFactory factory;

// Check inputs are valid
checkArguments(outputs, inputs);

// Assume the inputs are integral, this is generally not true but, shrug, it is fine.
int nV = (int) inputs[1][0];
int nC = (int) inputs[2][0];
int nComp = (int) inputs[3][0];

// Use raw pointer because we will have to handle this as an implicit unique pointer stored in matlab.
LCQPow::LCQProblem* problem = new LCQPow::LCQProblem(nV,nC,nComp);

// Reinterpret the pointer to an unsigned integer
std::uintptr_t self = reinterpret_cast<std::uintptr_t>(problem);

// Set the self property the current object
matlab->setProperty(inputs[0], u"self", factory.createScalar(self));
}

void checkArguments(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
std::shared_ptr<matlab::engine::MATLABEngine> matlab = getEngine();
matlab::data::ArrayFactory factory;
if(outputs.size() > 0)
{
matlab->feval(u"error", 0,
std::vector<matlab::data::Array>({ factory.createScalar("no outputs returned") }));

}
if(inputs.size() != 4)
{
matlab->feval(u"error", 0,
std::vector<matlab::data::Array>({ factory.createScalar("Incorrect number of inputs") }));

}
if (inputs[1].getType() != matlab::data::ArrayType::DOUBLE || inputs[1].getNumberOfElements() != 1)
{
matlab->feval(u"error", 0,
std::vector<matlab::data::Array>({ factory.createScalar("nV must be a scalar double") }));
}
if (inputs[2].getType() != matlab::data::ArrayType::DOUBLE || inputs[2].getNumberOfElements() != 1)
{
matlab->feval(u"error", 0,
std::vector<matlab::data::Array>({ factory.createScalar("nC must be a scalar double") }));
}
if (inputs[3].getType() != matlab::data::ArrayType::DOUBLE || inputs[3].getNumberOfElements() != 1)
{
matlab->feval(u"error", 0,
std::vector<matlab::data::Array>({ factory.createScalar("nComp must be a scalar double") }));
}
}
};
Loading