@@ -18,6 +18,7 @@ class SOFA_CONSTRAINTGEOMETRY_API ConstraintUnilateral : public TBaseConstraint<
1818 SOFA_CLASS (ConstraintUnilateral , SOFA_TEMPLATE2 (TBaseConstraint,collisionalgorithm::BaseProximity,collisionalgorithm::BaseProximity) );
1919
2020 Data<double > d_friction;
21+ Data<double > d_contactDistance;
2122 Data<double > d_maxforce0;
2223 Data<double > d_maxforce1;
2324 Data<double > d_maxforce2;
@@ -26,11 +27,23 @@ class SOFA_CONSTRAINTGEOMETRY_API ConstraintUnilateral : public TBaseConstraint<
2627
2728 ConstraintUnilateral ()
2829 : d_friction(initData(&d_friction, 0.0 , " mu" , " Friction" ))
30+ , d_contactDistance(initData(&d_contactDistance, 0.0 , " contactDistance" , " Standoff distance kept between the proximities in contact" ))
2931 , d_maxforce0(initData(&d_maxforce0, std::numeric_limits<double >::max(), " maxForce0" , " Max force applied on the first axis" ))
3032 , d_maxforce1(initData(&d_maxforce1, std::numeric_limits<double >::max(), " maxForce1" , " Max force applied on the second axis" ))
3133 , d_maxforce2(initData(&d_maxforce2, std::numeric_limits<double >::max(), " maxForce2" , " Max force applied on the third axis" ))
3234 , l_directions(initLink(" directions" , " link to the default direction" )) {}
3335
36+ void getConstraintViolation (const core::ConstraintParams* p,
37+ sofa::linearalgebra::BaseVector* v, unsigned cid) override
38+ {
39+ TBaseConstraint<collisionalgorithm::BaseProximity,collisionalgorithm::BaseProximity>::getConstraintViolation (p, v, cid);
40+ // Shift violation by -contactDistance so that the constraint is maintained at a distance.
41+ // ic->id() is the normal row.
42+ const double cd = d_contactDistance.getValue ();
43+ for (const auto & ic : d_container.getValue ())
44+ v->add (ic->id (), -cd);
45+ }
46+
3447 ConstraintNormal createConstraintNormal (const BaseProximity::SPtr & first, const BaseProximity::SPtr & second) const override {
3548 if (l_directions==NULL ) return ConstraintNormal ();
3649
0 commit comments