alphaville / optimization-engine

Nonconvex embedded optimization: code generation for fast real-time optimization + ROS support
https://alphaville.github.io/optimization-engine/
Other
512 stars 53 forks source link

Maximum number of inner iterations is not passed to inner solver #121

Closed alphaville closed 5 years ago

alphaville commented 5 years ago

Describe the bug

The maximum number of inner iterations is not passed from AlmOptimizer to the inner solver in AlmOptimizer:solve_inner_problem (line 716).

To Reproduce

Run the following example (not an MWE, sorry)

import casadi.casadi as cs
import opengen as og
import matplotlib.pyplot as plt
import numpy as np

# Example: Ball and Plate
# ======================================

# System dynamics
# --------------------------------------

mass_ball = 0.8
moment_inertia = 9.99e-6
length_rod = 1
gravity_acceleration = 9.8044
sampling_time = 0.01
nx = 4
nu = 1
N = 30

def dynamics_ct(x, u):
    dx1 = x[1]
    dx2 = (5/7)*(x[0] * x[3] * x[3] - gravity_acceleration * cs.sin(x[2]))
    dx3 = x[3]
    dx4 = (u - mass_ball * gravity_acceleration * x[0] * cs.cos(x[2]) - 2 * mass_ball * x[0] * x[1] * x[3]) \
          / (mass_ball * x[0] * x[0] + moment_inertia)
    return [dx1, dx2, dx3, dx4]

def dynamics_dt(x, u):
    dx = dynamics_ct(x, u)
    return [x[i] + sampling_time * dx[i] for i in range(nx)]

def stage_cost(x, u):
    cost = x[0]**2 + 0.1*x[1]**2 + 1.5*x[2]**2 + x[3]**2 + 2*u**2
    return cost

u_seq = cs.SX.sym("u", nu*N)  # sequence of all u's - decision variable
x0 = cs.SX.sym("x0", nx)      # initial state

x_t = x0
total_cost = 0
for t in range(0, nu*N, nu):
    u_t = u_seq[t:t+nu]
    total_cost += stage_cost(x_t, u_t)
    x_t = dynamics_dt(x_t, u_t)

U = og.constraints.BallInf(None, 0.1)

problem = og.builder.Problem(u_seq, x0, total_cost)  \
            .with_constraints(U)

build_config = og.config.BuildConfiguration()  \
    .with_build_directory("python_build")      \
    .with_build_mode("debug")                  \
    .with_tcp_interface_config()

meta = og.config.OptimizerMeta().with_optimizer_name("ball_and_plate")

solver_config = og.config.SolverConfiguration()\
    .with_tolerance(1e-6)\
    .with_initial_tolerance(1e-6)\
    .with_max_inner_iterations(1000)

builder = og.builder.OpEnOptimizerBuilder(problem, meta,
                                          build_config, solver_config)
builder.build()

mng = og.tcp.OptimizerTcpManager("python_build/ball_and_plate")
mng.start()
x_state_0 = [0, 0.2, 0, 0.01]
solution = mng.call(x_state_0)
print(solution)
mng.kill()

This will return a status Converged, but the maximum number of iterations was reached, which is 100 instead of 1000.

We should increase the maximum number of iterations btw.

Expected behavior

If the maximum number of inner iterations is reached NotConvergedIterations (this works for outer iterations - we need to check the inner status as well!). The maximum number of iterations should have been 1000.

System information:

Ubuntu 16.04, Rust 1.38.0,

Additional context

To be resolved in 0.6.1. Nothing to do in opengen.