RussTedrake/manipulation

differential_ik_optimization.ipynb depends on Snopt specifically for dubious reasons

nimrod-gileadi opened this issue · 12 comments

The following line in exercises/pick/differential_ik_optimization.ipynb (exercise 3.9) fails:

simulator = BuildAndSimulate(DiffIKQP, V_d)

<ipython-input-10-48b45d3b8fa8> in DiffIKQP(J_G, V_G_desired, q_now, v_now, p_now)
      9   prog.AddCost(error.dot(error))
     10   solver = SnoptSolver()
---> 11   result = solver.Solve(prog)
     12 
     13   if not (result.is_success()):

ValueError: The drake::solvers::SnoptSolver is not available in this build

For this particular exercise, replacing the SnoptSolver with just result = Solve(prog), imported at the top of the notebook, works for me.

Were you building from source? The notebooks on colab use the binaries, which come with Snopt inside.

@hjsuh94 -- is there a reason you used Snopt in that exercise? I would actually think it's the wrong solver to use (for a convex QP)? or at very least, it's strange to require it?

There was a very specific reason for this, which was that the default solver (osqp) is not exact w.r.t. constraints (it violates the bounding box constraint with 1e-3), while Snopt is.

More specifically osqp gives different results when you use AddBoundingBoxConstraint vs. le/ge, which is a pain when dealing with the autograder downstream. Here is a small test script that I did back then to reproduce the issue:
https://colab.research.google.com/drive/1QyeAQm68DsN3zAX-Us9_0YF-unYeL8f6?usp=sharing

I recommend using osqp if you're building from source - the autograder might complain here and there, but your solution will still be correct visually.

Thanks @hjsuh94 . That makes sense.

@hongkai-dai -- it seems like OSQP has settings that we haven't exposed in drake yet? https://osqp.org/docs/interfaces/solver_settings.html#solver-settings
Do you think exposing them would help with some of these issues?

Were you building from source? The notebooks on colab use the binaries, which come with Snopt inside.

I wasn't building from source, just running the notebook as linked from exercise 3.9.

I just tried now again and it failed in the import stage (differently from the reported issue):

FileNotFoundError: [Errno 2] No such file or directory: '/opt/drake/share/drake/setup/packages-bionic.txt'

@flederbaysian perhaps the runtime has expired? It might go back to normal if you do factory reset of the runtime.

Thanks @hjsuh94 . That makes sense.

@hongkai-dai -- it seems like OSQP has settings that we haven't exposed in drake yet? https://osqp.org/docs/interfaces/solver_settings.html#solver-settings
Do you think exposing them would help with some of these issues?

I think we can tighten the tolerance. I will send a PR to expose these parameters.

BTW, currently we support a partial list of parameters, as in https://github.com/RobotLocomotion/drake/blob/4ffb523ab25206c47b4211679fe01dd787a47c31/solvers/osqp_solver.cc#L222-L233

Another option is to use IPOPT, which should also solve QP with high precision.

BTW, I also added CLP into Drake. The upstream CLP solver supports QP. I haven't supported solving QP with CLP in Drake yet, but it should be straightforward.

I filed a Drake PR RobotLocomotion/drake#14886 to expose all OSQP parameters.

I added prog.SetSolverOption(OsqpSolver().solver_id(), "eps_abs", 1E-6) before calling Solve in @hjsuh94 's colab notebook, now both the ge version and the bounding box version give the same result.

Awesome. Thanks @hongkai-dai ! I'll leave this open for now, since right now we only get infrequent updates to the drake binaries on colab. But the plan will be to switch back to OSQP after your change lands and the binary is ready.

I tried changing the problem to use

    prog.SetSolverOption(osqp.solver_id(), "eps_abs", 1E-6)
    result = osqp.Solve(prog)

but it would also require a note of the form

NOTE: Use `AddQuadraticCost(... , is_convex=True)` to be robust to small numerical artifacts that result in the error message `OsqpSolver is unable to solve because the quadratic cost ... is non-convex.` 

i think this is too brittle. It also fails the current grader tolerance even with this as a solution. I'll leave it with SnoptSolver for now.

The real fix, of course, would be to not pass numerically non-convex costs!