RussTedrake / manipulation

Course notes for MIT manipulation class
BSD 3-Clause "New" or "Revised" License
422 stars 124 forks source link

differential_ik_optimization.ipynb depends on Snopt specifically for dubious reasons #140

Open nimrod-gileadi opened 3 years ago

nimrod-gileadi commented 3 years ago

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
nimrod-gileadi commented 3 years ago

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

RussTedrake commented 3 years ago

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

RussTedrake commented 3 years ago

@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?

hjsuh94 commented 3 years ago

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.

RussTedrake commented 3 years ago

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?

nimrod-gileadi commented 3 years ago

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'
hjsuh94 commented 3 years ago

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

hongkai-dai commented 3 years ago

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

hongkai-dai commented 3 years ago

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.

hongkai-dai commented 3 years ago

I filed a Drake PR https://github.com/RobotLocomotion/drake/pull/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.

RussTedrake commented 3 years ago

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.

RussTedrake commented 1 year ago

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!