Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
33 changes: 16 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,23 +73,22 @@ Configuration lives in `pyrightconfig.json` (`pythonVersion` 3.9,

## Conventions

- **Preserve prior solver behaviour.** The wrapper's historical defaults are
the behavioural contract. In particular:
- `Configuration.enableRegularisation` defaults to `BT_FALSE`
(qpOASES' own default is `BT_TRUE`) — do not "fix" it to `BT_TRUE` without
re-validating the semi-definite / indefinite examples.
- `Configuration.print_level` defaults to `PL_LOW` (qpOASES default is
`PL_MEDIUM`) so the solver is quiet by default.
- `Configuration.enableNZCTests` and `enableFlippingBounds` default to
`BT_FALSE` (qpOASES default is `BT_TRUE`) — the "fast"/MPC preset.
- `Solver` accepts `None` for `A`/`b`/`Aeq`/`beq` and substitutes a single
trivially-satisfied zero row; `Solver.get_active_set()` returns one entry
per combined constraint row (-1 lower / 0 inactive / +1 upper).
- **Style.** Match the existing style: no trailing-whitespace obsession,
docstrings on public API, snake_case for new `Configuration` fields that
map to qpOASES `Options` fields (keep qpOASES-native names where they are
already the established wrapper spelling: `enableFlippingBounds`,
`enableRegularisation`, `enableNZCTests`).
- **Defaults match qpOASES.** `Configuration` defaults mirror qpOASES'
own `Options::setToDefault()` for a double-precision build (see the
defaults table in `README.md`). Do not silently override them here; if a
particular problem needs a non-default option, set it on the
`Configuration` in the *caller* (e.g. `example.py:semidefinite()` sets
`hessian_type = HST_SEMIDEF` because its Hessian is rank-deficient).
Re-validate the `example.py` and `example_kinematics.py` solves after any
change to a default.
- **`Solver` API.** `Solver.solve_quadratic_program()` accepts `None` for
`A`/`b`/`Aeq`/`beq` and substitutes a single trivially-satisfied zero row;
`Solver.get_active_set()` returns one entry per combined constraint row
(-1 lower / 0 inactive / +1 upper).
- **Style.** Match the existing style: docstrings on the public API and
snake_case for every `Configuration` field (including the ones whose
qpOASES `Options` names are camelCase, e.g. `enable_flipping_bounds` for
`Options::enableFlippingBounds`).
- **Doxygen.** C++ types and members are documented with Doxygen
(`/** ... @brief ... @see ... */` blocks). Keep that when adding fields.
- **Annotations.** All public Python API is fully type-annotated and must
Expand Down
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ the solver:
```python
config = qpoases.Configuration()
config.hessian_type = qpoases.HessianType.HST_SEMIDEF # H is rank-deficient
config.enableRegularisation = qpoases.BooleanType.BT_FALSE
config.termination_tolerance = 1.0e-9 # tighter convergence
solver = qpoases.Solver(config)
```
Expand Down Expand Up @@ -111,23 +110,20 @@ The enum types are re-exported for convenience: `qpoases.BooleanType`,
### qpOASES options

These map 1:1 onto qpOASES' `Options` fields. Defaults match qpOASES' own
defaults for a **double-precision** build (see `Options::setToDefault()`), with
two deliberate exceptions noted inline: `enableNZCTests` and
`enableFlippingBounds` default to `BT_FALSE` here (qpOASES' default is
`BT_TRUE`) because those are the recommended "fast"/MPC settings for repeated,
online solves. See the [qpOASES manual](https://www.coin-or.org/qpOASES/doc/3.0/manual.pdf)
for a full description of each option.
defaults for a **double-precision** build (see `Options::setToDefault()`). See
the [qpOASES manual](https://www.coin-or.org/qpOASES/doc/3.0/manual.pdf) for a
full description of each option.

**Booleans** (`BooleanType`: `BT_FALSE` / `BT_TRUE`)

| Option | Default | Description |
|---|---|---|
| `enable_ramping` | `BT_TRUE` | Enables the ramping strategy. |
| `enable_far_bounds` | `BT_TRUE` | Enables the far bounds strategy. |
| `enableFlippingBounds` | `BT_FALSE` | Allows flipping active bounds between lower and upper values. *(differs from qpOASES default)* |
| `enableRegularisation` | `BT_FALSE` | Regularises `H` when (semi-)definiteness is detected. |
| `enable_flipping_bounds` | `BT_TRUE` | Allows flipping active bounds between lower and upper values. |
| `enable_regularisation` | `BT_FALSE` | Regularises `H` when (semi-)definiteness is detected. |
| `enable_full_li_tests` | `BT_FALSE` | Uses the condition-hardened linear-independence (LI) test. |
| `enableNZCTests` | `BT_FALSE` | Enables the nonzero-curvature test. *(differs from qpOASES default)* |
| `enable_nzc_tests` | `BT_TRUE` | Enables the nonzero-curvature test. |
| `enable_equalities` | `BT_FALSE` | Treats equality constraints as always active. |
| `enable_inertia_correction` | `BT_TRUE` | Repairs the working set when negative curvature is found during a hotstart. |
| `enable_drop_infeasibles` | `BT_FALSE` | Whether infeasible constraints may be dropped. |
Expand Down Expand Up @@ -170,7 +166,7 @@ for a full description of each option.

| Option | Default | Type | Description |
|---|---|---|---|
| `print_level` | `PL_LOW` | `PrintLevel` | Verbosity of qpOASES output (`PL_NONE`, `PL_LOW`, `PL_MEDIUM`, `PL_HIGH`, `PL_TABULAR`, `PL_DEBUG_ITER`). Defaults to `PL_LOW` so the solver stays quiet (qpOASES' own default is `PL_MEDIUM`). |
| `print_level` | `PL_MEDIUM` | `PrintLevel` | Verbosity of qpOASES output (`PL_NONE`, `PL_LOW`, `PL_MEDIUM`, `PL_HIGH`, `PL_TABULAR`, `PL_DEBUG_ITER`). |
| `initial_status_bounds` | `ST_LOWER` | `SubjectToStatus` | Status assumed for all bounds at the first iteration. |

### Print levels (`PrintLevel`)
Expand Down
29 changes: 7 additions & 22 deletions include/qpOASES_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,9 @@ class qpOASES_Solver
/**
* @brief Holds all user-configurable solver options.
*
* Every qpOASES `Options` field is exposed here. Defaults are chosen
* to match qpOASES' own defaults for a double-precision build (see
* `Options::setToDefault()`), with three deliberate exceptions:
*
* - enableNZCTests defaults to BT_FALSE (qpOASES default is
* BT_TRUE) and enableFlippingBounds defaults to BT_FALSE
* (qpOASES default is BT_TRUE). These are the settings used by
* qpOASES' "fast"/MPC preset and are the recommended settings
* for online, embedded use.
* - print_level defaults to PL_LOW (qpOASES default is PL_MEDIUM)
* so the wrapper stays quiet by default.
* Every qpOASES `Options` field is exposed here. Defaults match
* qpOASES' own defaults for a double-precision build (see
* `Options::setToDefault()`).
*
* @note qpOASES applies `Options::ensureConsistency()` when it sets
* its options, which will silently adjust any value that falls
Expand Down Expand Up @@ -85,12 +77,9 @@ class qpOASES_Solver

/**
* @brief Verbose-ness of qpOASES output.
*
* Defaults to PL_LOW so the solver stays quiet, matching this
* wrapper's historical behaviour.
* @see `Options::printLevel`
*/
PrintLevel print_level = PL_LOW;
PrintLevel print_level = PL_MEDIUM;

/**
* @brief Whether the ramping strategy shall be used.
Expand All @@ -109,18 +98,14 @@ class qpOASES_Solver
* values.
* @see `Options::enableFlippingBounds`. Page 22 of the manual.
*/
BooleanType enableFlippingBounds = BT_FALSE;
BooleanType enable_flipping_bounds = BT_TRUE;

/**
* @brief Whether the Hessian shall be regularised in case
* (semi-)definiteness is detected.
*
* Defaults to BT_FALSE to match both qpOASES' own default and the
* effective default of this wrapper prior to this option being
* passed through.
* @see `Options::enableRegularisation`. Page 26 of the manual.
*/
BooleanType enableRegularisation = BT_FALSE;
BooleanType enable_regularisation = BT_FALSE;

/**
* @brief Whether the condition-hardened linear independence
Expand All @@ -133,7 +118,7 @@ class qpOASES_Solver
* @brief Whether nonzero curvature tests shall be used.
* @see `Options::enableNZCTests`. Page 22 of the manual.
*/
BooleanType enableNZCTests = BT_FALSE;
BooleanType enable_nzc_tests = BT_TRUE;

/**
* @brief Frequency of drift corrections (0 = off).
Expand Down
6 changes: 3 additions & 3 deletions marinholab/solvers/qpoases/_core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ class qpOASES_Solver:
#: Enables the far bounds strategy.
enable_far_bounds: BooleanType
#: Enables flipping of active bounds between lower and upper values.
enableFlippingBounds: BooleanType
enable_flipping_bounds: BooleanType
#: Regularises the Hessian in case (semi-)definiteness is detected.
enableRegularisation: BooleanType
enable_regularisation: BooleanType
#: Uses the condition-hardened linear independence test.
enable_full_li_tests: BooleanType
#: Enables the nonzero curvature test.
enableNZCTests: BooleanType
enable_nzc_tests: BooleanType
#: Frequency of drift corrections (0 = off).
enable_drift_correction: int
#: Frequency of full Cholesky refactorisation of the projected Hessian (0 = updates only).
Expand Down
6 changes: 3 additions & 3 deletions marinholab/solvers/qpoases/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ def positivedefinite() -> None:
print(u_both)

def semidefinite() -> None:
# The Hessian here is positive semi-definite (rank deficient), so the
# Hessian type must be set to HST_SEMIDEF; everything else stays at the
# defaults.
config = qpoases.Configuration()
config.hessian_type = qpoases.HessianType.HST_SEMIDEF
config.enableRegularisation = qpoases.BooleanType.BT_FALSE
#config.enableNZCTests = qpOASES_Solver.BooleanType.BT_TRUE
#config.enableFlippingBounds = qpOASES_Solver.BooleanType.BT_TRUE
solver = qpoases.Solver(config)

x = np.array([1.0, 0.0, 0.0, 0.0])
Expand Down
5 changes: 2 additions & 3 deletions marinholab/solvers/qpoases/example_kinematics.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,10 @@ def main():
# qpOASES is an active-set solver and its Hessian must instead be flagged
# according to its definiteness. Level 1's H1 = Jt.T @ Jt is only
# positive semi-definite (rank <= 3 out of 7 joints), so we flag it as
# such and disable qpOASES' automatic regularisation, matching the
# `semidefinite()` pattern in `example.py`.
# such; everything else stays at the defaults (in particular
# `enable_regularisation` is already BT_FALSE).
config_1 = qpoases.Configuration()
config_1.hessian_type = qpoases.HessianType.HST_SEMIDEF
config_1.enableRegularisation = qpoases.BooleanType.BT_FALSE

# Level 2's H2 = I is positive definite, so the default configuration
# (HST_POSDEF) is adequate.
Expand Down
8 changes: 4 additions & 4 deletions src/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ PYBIND11_MODULE(_core, m) {
qpoases_configuration.def_readwrite("maximum_working_set_recalculations", &qpOASES_Solver::Configuration::maximum_working_set_recalculations, "Maximum number of working set recalculations during the initial homotopy.");
qpoases_configuration.def_readwrite("use_hotstart", &qpOASES_Solver::Configuration::use_hotstart, "Whether subsequent solves are warm-started instead of re-initialised.");
// qpOASES `Options` fields
qpoases_configuration.def_readwrite("print_level", &qpOASES_Solver::Configuration::print_level, "qpOASES print level (default PL_LOW, quiet).");
qpoases_configuration.def_readwrite("print_level", &qpOASES_Solver::Configuration::print_level, "qpOASES print level (default PL_MEDIUM).");
qpoases_configuration.def_readwrite("enable_ramping", &qpOASES_Solver::Configuration::enable_ramping, "Enables the ramping strategy.");
qpoases_configuration.def_readwrite("enable_far_bounds", &qpOASES_Solver::Configuration::enable_far_bounds, "Enables the far bounds strategy.");
qpoases_configuration.def_readwrite("enableFlippingBounds", &qpOASES_Solver::Configuration::enableFlippingBounds, "Enables flipping of active bounds between lower and upper values.");
qpoases_configuration.def_readwrite("enableRegularisation", &qpOASES_Solver::Configuration::enableRegularisation, "Regularises the Hessian in case (semi-)definiteness is detected.");
qpoases_configuration.def_readwrite("enable_flipping_bounds", &qpOASES_Solver::Configuration::enable_flipping_bounds, "Enables flipping of active bounds between lower and upper values.");
qpoases_configuration.def_readwrite("enable_regularisation", &qpOASES_Solver::Configuration::enable_regularisation, "Regularises the Hessian in case (semi-)definiteness is detected.");
qpoases_configuration.def_readwrite("enable_full_li_tests", &qpOASES_Solver::Configuration::enable_full_li_tests, "Uses the condition-hardened linear independence test.");
qpoases_configuration.def_readwrite("enableNZCTests", &qpOASES_Solver::Configuration::enableNZCTests, "Enables the nonzero curvature test.");
qpoases_configuration.def_readwrite("enable_nzc_tests", &qpOASES_Solver::Configuration::enable_nzc_tests, "Enables the nonzero curvature test.");
qpoases_configuration.def_readwrite("enable_drift_correction", &qpOASES_Solver::Configuration::enable_drift_correction, "Frequency of drift corrections (0 = off).");
qpoases_configuration.def_readwrite("enable_cholesky_refactorisation", &qpOASES_Solver::Configuration::enable_cholesky_refactorisation, "Frequency of full Cholesky refactorisation of the projected Hessian (0 = updates only).");
qpoases_configuration.def_readwrite("enable_equalities", &qpOASES_Solver::Configuration::enable_equalities, "Treats equality constraints as always active.");
Expand Down
6 changes: 3 additions & 3 deletions src/core_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ Options qpOASES_Solver::_to_qpoases_options() const
options.printLevel = configuration_.print_level;
options.enableRamping = configuration_.enable_ramping;
options.enableFarBounds = configuration_.enable_far_bounds;
options.enableFlippingBounds = configuration_.enableFlippingBounds;
options.enableRegularisation = configuration_.enableRegularisation;
options.enableFlippingBounds = configuration_.enable_flipping_bounds;
options.enableRegularisation = configuration_.enable_regularisation;
options.enableFullLITests = configuration_.enable_full_li_tests;
options.enableNZCTests = configuration_.enableNZCTests;
options.enableNZCTests = configuration_.enable_nzc_tests;
options.enableDriftCorrection = configuration_.enable_drift_correction;
options.enableCholeskyRefactorisation = configuration_.enable_cholesky_refactorisation;
options.enableEqualities = configuration_.enable_equalities;
Expand Down
Loading