3737#include < fmt/ostream.h>
3838
3939#include < cassert>
40+ #include < cmath>
4041
4142#if DART_BUILD_MODE_DEBUG
4243 #include < iomanip>
@@ -149,6 +150,7 @@ void BoxedLcpConstraintSolver::solveConstrainedGroup(ConstrainedGroup& group)
149150 mA .setZero (n, nSkip);
150151#endif
151152 mX .resize (n);
153+ mX .setZero ();
152154 mB .resize (n);
153155 mW .setZero (n); // set w to 0
154156 mLo .resize (n);
@@ -267,9 +269,11 @@ void BoxedLcpConstraintSolver::solveConstrainedGroup(ConstrainedGroup& group)
267269 if (success && mX .hasNaN ())
268270 success = false ;
269271
272+ bool fallbackSuccess = false ;
273+ bool fallbackRan = false ;
270274 if (!success && mSecondaryBoxedLcpSolver ) {
271275 DART_PROFILE_SCOPED_N (" Secondary LCP" );
272- mSecondaryBoxedLcpSolver ->solve (
276+ fallbackSuccess = mSecondaryBoxedLcpSolver ->solve (
273277 n,
274278 mABackup .data (),
275279 mXBackup .data (),
@@ -280,15 +284,40 @@ void BoxedLcpConstraintSolver::solveConstrainedGroup(ConstrainedGroup& group)
280284 mFIndexBackup .data (),
281285 false );
282286 mX = mXBackup ;
287+ fallbackRan = true ;
283288 }
284289
285- if (mX .hasNaN ()) {
286- DART_ERROR (
287- " [BoxedLcpConstraintSolver] The solution of LCP includes NAN values: "
288- " {}. We're setting it zero for safety. Consider using more robust "
289- " solver such as PGS as a secondary solver. If this happens even with "
290- " PGS solver, please report this as a bug." ,
291- fmt::streamed (mX .transpose ()));
290+ const bool hasNaN = mX .hasNaN ();
291+ if (!success && fallbackRan && hasNaN) {
292+ // If the fallback produced NaNs, zero just those entries but still allow
293+ // non-NaN entries to propagate.
294+ for (int i = 0 ; i < mX .size (); ++i) {
295+ if (std::isnan (mX [i]))
296+ mX [i] = 0.0 ;
297+ }
298+ }
299+
300+ // Treat a finite fallback solution as usable even if the solver reported
301+ // failure to avoid discarding potentially valid impulses.
302+ const bool finalSuccess
303+ = success || fallbackSuccess || (fallbackRan && !mX .hasNaN ());
304+
305+ if (!finalSuccess) {
306+ if (hasNaN) {
307+ DART_ERROR (
308+ " [BoxedLcpConstraintSolver] The solution of LCP includes NAN values: "
309+ " {}. We're setting it zero for safety. Consider using more robust "
310+ " solver such as PGS as a secondary solver. If this happens even with "
311+ " PGS solver, please report this as a bug." ,
312+ fmt::streamed (mX .transpose ()));
313+ } else {
314+ DART_ERROR (
315+ " [BoxedLcpConstraintSolver] Primary LCP solver failed to find a "
316+ " solution. The constraint impulses are set to zero for safety. "
317+ " Consider configuring a secondary solver (e.g., PGS) to provide a "
318+ " fallback when Dantzig fails." );
319+ }
320+
292321 mX .setZero ();
293322 }
294323
0 commit comments