OpEn

OpEn

  • Docs
  • Blog
  • Rust API
  • Opengen API
  • Chat
  • Github

›Python

OpEn Guide

  • Introduction
  • Installation

Python

  • Opengen basics
  • Advanced options
  • C/C++ Bindings
  • Direct interface
  • TCP Sockets
  • ROS packages
  • Examples

MATLAB

  • MATLAB
  • Examples

Rust

  • Introduction
  • ALM/PM
  • Features

Docker

  • Docker

Extras

  • Algorithm
  • FAQ
  • Cite OpEn
  • Contributing

Advanced options

Solver options

The user may wish to modify some additional solver parameters.

When using the penalty method to account for general constraints, the most important parameters which determine the speed of convergence are the initial value of the penalty weight and the update factor. These are set using

solver_config.with_penalty_weight_update_factor(8.0)       \
             .with_initial_penalty(20.0)

The number of the initial penalty weights must be equal to $n_c$; the number of constraints. If you need to set all weights to the same value, use

solver_config.with_initial_penalty(100.0)

In embedded applications it is often important that the solver is forced to terminate within a given time period. The user may set the maximum runtime (in microseconds) using

# Maximum duration: 50ms
solver_config.with_max_duration_micros(50000)

Lastly, the maximum number of outer iterations can be set using

solver_config.with_max_outer_iterations(num_out_iters)

The number of outer iterations should be kept reasonably small to avoid too high values of the penalty parameters (which increase exponentially).

Preconditioning: Opengen since version 0.7.0 supports a preconditioning mechanism. If activated, the initial penalty is computed internally. Moreover, appropriate scaling is applied on the cost function, the PM-type constraints, $F_2(u; p) = 0$, and the ALM-type constraints, $F_1(u; p) \in C$, but only if $C=\{0\}$, or if $C$ is a quadrant, e.g., $C = \{x: x\leq 0\}$.

Preconditioning seems to improve the convergence speed and robustness of the solver based on some initial benchmarks, however, for the time being it is not active by default. To activate it, use with_preconditioning(True).

A complete list of solver options is given in the following table

MethodExplanation
with_toleranceTarget $\epsilon$-tolerance
with_delta_toleranceTolerance $\delta$
with_initial_penaltyInitial penalty value, $c_0$
with_max_inner_iterationsMaximum number of outer iterations
with_max_outer_iterationsMaximum number of inner iterations
with_penalty_weight_update_factorUpdate factor of penalty weight, $\rho$
with_initial_toleranceInitial tolerance, $\epsilon_0$
with_sufficient_decrease_coefficientSufficient decrease coeff. (for skipping penalty update)
with_max_duration_microsMaximum duration of execution in micros
with_cbfgs_parametersCBFGS parameters
with_lbfgs_memoryLBFGS memory
with_inner_tolerance_update_factorUpdate factor for the inner tolerance
with_preconditioningWhether preconditioning should be applied

Build options

Build mode

During the design phase, one needs to experiment with the problem formulation and solver parameters. This is way the default build mode is the "debug" mode, which compiles fast, but it suboptimal. Building in "release" mode takes slightly longer to compile, but can lead to a significant speed-up. To do so, use the option

build_config.with_build_mode(
    og.config.BuildConfiguration.DEBUG_MODE)

οr

build_config.with_build_mode(
    og.config.BuildConfiguration.RELEASE_MODE)

Cross-compilation

You can either compile for your own system, or cross-compile for a different target system. For example, to cross-compile for a Raspberry Pi, set the following option

build_config.with_target_system("arm-unknown-linux-gnueabihf")

or

build_config.with_target_system("rpi")  # Raspberry Pi

Note that you need to install the necessary target first.

See setup details To cross-compile for a Raspberry Pi you need to run the following in your terminal

rustup target add arm-unknown-linux-gnueabihf

You also need to install the following dependencies

Linux
MacOS
sudo apt-get update
sudo apt-get install -y gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
# Tap the repository that provides the cross-compiler
brew tap messense/macos-cross-toolchains
# Update brew to ensure the tap is recognized (can sometimes be needed)
brew update
# Install the full toolchain (includes gcc, binutils, sysroot)
# This specific formula provides the entire toolchain.
brew install arm-unknown-linux-gnueabihf

# Verify the compiler is found
which arm-linux-gnueabihf-gcc || (echo "arm-linux-gnueabihf-gcc not found in PATH" && exit 1)


If you need to compile for a target other than arm-linux-gnueabihf-gcc (rpi) some manual configuration may be needed (you may need to install the target and/or a compiler/linker) and you may need to edit the auto-generated .cargo/config.toml files you will find in your auto-generated solvers.

Non-supported targets The auto-generated .cargo/config.toml files contain entries like

[target.arm-unknown-linux-gnueabihf]
linker="arm-linux-gnueabihf-gcc"

Here you may have to insert manually your own target. Feel free to open an issue on GitHub if you would like us to add support for a particular target (create a feature request); see the contributing guidelines.

When cross-compiling for a Raspberry Pi you may want to configure a TCP server so you can call the optimizer remotely. You can find more information about this below. Once you have cross-compiled, locate the file

{your_optimizer}/tcp_iface_{your_optimizer}/target/arm-unknown-linux-gnueabihf/release/tcp_iface_{your_optimizer}

—where {your_optimizer} is the name of your optimizer—and copy it to your Raspberry Pi. On your Raspberry, change the permissions so you can execute this file

chmod u+x ./tcp_iface_{your_optimizer}

and run it. Your OpEn server is live. Read also the documentation on the TCP sockets protocol of OpEn servers.

Other build options

All build options are shown below

MethodExplanation
with_build_directoryTarget build directory; the default is .
with_build_moderelease or debug; the default option is release, which requires more time to compile, but leads to high performance executables; use debug for faster compilation, at the cost of lower performance (this is useful when experimenting with OpEn)
with_tcp_interface_configEnable TCP server; provide configuration
with_target_systemTarget system (to be used when you need to cross-compile)
with_build_c_bindingsEnalbe generation of C/C++ bindings
with_rebuildWhether to do a clean build
with_open_versionUse a certain version of OpEn (see all versions), e.g., with_open_version("0.6.0"), or a local version of OpEn (this is useful when you want to download the latest version of OpEn from github). You can do so using with_open_version(local_path="/path/to/open/").
with_allocatorAvailable in opengen >= 0.6.6. Compile with a different memory allocator. The available allocators are the entries of RustAllocator. OpEn currently supports Jemalloc and Rpmalloc.

TCP/IP interface

Generation of TCP server

In order to change the IP and port at which the server listens for requests (e.g., for remote connections), you may crate an TcpServerConfiguration object as follows

tcp_config = og.config.TcpServerConfiguration('10.8.0.12', 9555)

and then provide it to the builder configuration using

builder_config.with_tcp_interface_config(tcp_config)

Communicate with TCP server

There are two ways to connect to a generated TCP server and call the auto-generated optimizer:

Connect to a local optimizer by providing the path of the optimizer directory. For that purpose, we need to create an instance of OptimizerTcpManager and specify the path to the auto-generated optimizer.

For example,

mng = og.tcp.OptimizerTcpManager('python_build/the_optimizer')

we can then start the optimizer. The TCP manager known what IP and port to link to, so we can call it directly.

Connect to a local optimizer and customize its IP and port. This is particularly useful if you need to start multiple instances of a TCP server (with different ports).

For example,

ip = '0.0.0.0'
port = 5678
mng = og.tcp.OptimizerTcpManager('python_build/the_optimizer', ip, port)
Connect to a remote optimizer by providing its IP and port. In that case we assume that an optimizer is up an running at some remote address and listens for connections at a certain port. In that case, we cannot start the optimizer remotely using the TCP manager.

For example to connect to a remote TCP server at 10.8.0.7:5678, we can create a TCP manager as follows:

mng = og.tcp.OptimizerTcpManager(ip="10.8.0.7", port=5678)

A list of the methods of OptimizerTcpManager is given below:

MethodExplanation
startStarts the (local) server; throws an exception if the IP is not local. If the server is local, it will start in a separate thread and will remain alive unit kill is invoked.
pingPings the server to check if it is alive
callCalls the TCP server; provides a parameter and the solver responds with either the solution or an error report
killKills the server associated with the TCP manager; works both on local and remote servers.

Metadata

The solver metadata offer important information about the auto-generated solver such as its name

MethodExplanation
with_optimizer_nameOptimizer name (which is also the name of the folder in which the auto-generated solver will be stored). The default optimizer name is open_optimizer
with_authorsProvide list of author names
with_licenceName or URL of license of generated solver; the default licence is the MIT licence
with_versionVersion of auto-generated solver; the default version is 0.0.0
← Opengen basicsC/C++ Bindings →
  • Solver options
  • Build options
    • Build mode
    • Cross-compilation
    • Other build options
  • TCP/IP interface
    • Generation of TCP server
    • Communicate with TCP server
  • Metadata
OpEn
Docs
Getting StartedPython interfaceMATLAB interfaceDocker
Community
User ShowcaseDiscord communityChat on GitterTwitter
More
BlogGitHubOpenhubStar

Tweet
Copyright © 2025 Pantelis Sopasakis and Emil Fresk
Box Icon made by Freepik from www.flaticon.com