示例#1
0
        public override void ConstraintsBiLoad_C(double factor = 1, double recovery_clamp = 0.1, bool do_clamp = false)
        {
            int cnt = 0;

            for (int i = 0; i < mask.nconstr; i++)
            {
                if (mask.Constr_N(i).IsActive())
                {
                    if (do_clamp)
                    {
                        if (mask.Constr_N(i).IsUnilateral())
                        {
                            mask.Constr_N(i).Set_b_i(mask.Constr_N(i).Get_b_i() +
                                                     ChMaths.ChMax(factor * C.matrix.ElementN(cnt), -recovery_clamp));
                        }
                        else
                        {
                            mask.Constr_N(i).Set_b_i(mask.Constr_N(i).Get_b_i() +
                                                     ChMaths.ChMin(ChMaths.ChMax(factor * C.matrix.ElementN(cnt), -recovery_clamp), recovery_clamp));
                        }
                    }
                    else
                    {
                        mask.Constr_N(i).Set_b_i(mask.Constr_N(i).Get_b_i() + factor * C.matrix.ElementN(cnt));
                    }

                    cnt++;
                }
            }
        }
示例#2
0
        public override void IntLoadConstraint_C(int off_L,
                                                 ref ChVectorDynamic <double> Qc,
                                                 double c,
                                                 bool do_clamp,
                                                 double recovery_clamp)
        {
            int cnt = 0;

            for (int i = 0; i < mask.nconstr; i++)
            {
                if (mask.Constr_N(i).IsActive())
                {
                    if (do_clamp)
                    {
                        if (mask.Constr_N(i).IsUnilateral())
                        {
                            Qc.matrix[off_L + cnt] += ChMaths.ChMax(c * C.matrix.ElementN(cnt), -recovery_clamp);
                        }
                        else
                        {
                            Qc.matrix[off_L + cnt] += ChMaths.ChMin(ChMaths.ChMax(c * C.matrix.ElementN(cnt), -recovery_clamp), recovery_clamp);
                        }
                    }
                    else
                    {
                        Qc.matrix[off_L + cnt] += c * C.matrix.ElementN(cnt);
                    }
                    cnt++;
                }
            }
        }
示例#3
0
        public override void IntLoadConstraint_C(int off_L,
                                                 ref ChVectorDynamic <double> Qc,
                                                 double c,
                                                 bool do_clamp,
                                                 double recovery_clamp)
        {
            int cnt = 0;

            for (int i = 0; i < mask.nconstr; i++)
            {
                if (mask.Constr_N(i).IsActive())
                {
                    if (do_clamp)
                    {
                        if (mask.Constr_N(i).IsUnilateral())
                        {
                            Qc.matrix[off_L + cnt] += ChMaths.ChMax(c * C.matrix.ElementN(cnt), -recovery_clamp);
                        }
                        else
                        {
                            Qc.matrix[off_L + cnt] += ChMaths.ChMin(ChMaths.ChMax(c * C.matrix.ElementN(cnt), -recovery_clamp), recovery_clamp);
                        }
                    }
                    else
                    {
                        Qc.matrix[off_L + cnt] += c * C.matrix.ElementN(cnt);
                    }
                    cnt++;     // The Gremlin in the works was here!   I had accidently locked this variable in the above else, causing joint jittering
                }
            }
        }
示例#4
0
        public override void ConstraintsBiLoad_C(double factor = 1, double recovery_clamp = 0.1, bool do_clamp = false)
        {
            if (!IsActive())
            {
                return;
            }

            if (do_clamp)
            {
                Cx.Set_b_i(Cx.Get_b_i() + ChMaths.ChMin(ChMaths.ChMax(factor * (curr_dist - distance), -recovery_clamp), recovery_clamp));
            }
            else
            {
                Cx.Set_b_i(Cx.Get_b_i() + factor * (curr_dist - distance));
            }
        }
示例#5
0
        public override void ConstraintsBiLoad_C(double factor = 1, double recovery_clamp = 0.1, bool do_clamp = false)
        {
            if (!this.IsActive())
            {
                return;
            }

            //***TEST***

            /*
             *  GetLog()<< "cload: " ;
             *  if (this.c_x) GetLog()<< " x";
             *  if (this.c_y) GetLog()<< " y";
             *  if (this.c_z) GetLog()<< " z";
             *  if (this.c_rx) GetLog()<< " Rx";
             *  if (this.c_ry) GetLog()<< " Ry";
             *  if (this.c_rz) GetLog()<< " Rz";
             *  GetLog()<< *this.C << "\n";
             */
            int cnt = 0;

            for (int i = 0; i < mask.nconstr; i++)
            {
                if (mask.Constr_N(i).IsActive())
                {
                    if (do_clamp)
                    {
                        if (mask.Constr_N(i).IsUnilateral())
                        {
                            mask.Constr_N(i).Set_b_i(mask.Constr_N(i).Get_b_i() +
                                                     ChMaths.ChMax(factor * C.matrix.ElementN(cnt), -recovery_clamp));
                        }
                        else
                        {
                            mask.Constr_N(i).Set_b_i(mask.Constr_N(i).Get_b_i() +
                                                     ChMaths.ChMin(ChMaths.ChMax(factor * C.matrix.ElementN(cnt), -recovery_clamp), recovery_clamp));
                        }
                    }
                    else
                    {
                        mask.Constr_N(i).Set_b_i(mask.Constr_N(i).Get_b_i() + factor * C.matrix.ElementN(cnt));
                    }

                    cnt++;
                }
            }
        }
示例#6
0
        public override void IntLoadConstraint_C(int off_L,
                                                 ref ChVectorDynamic <double> Qc,
                                                 double c,
                                                 bool do_clamp,
                                                 double recovery_clamp)
        {
            double res = 0;  // no residual anyway! allow drifting...

            double cnstr_violation = c * res;

            if (do_clamp)
            {
                cnstr_violation = ChMaths.ChMin(ChMaths.ChMax(cnstr_violation, -recovery_clamp), recovery_clamp);
            }

            Qc.matrix[off_L] += cnstr_violation;
        }
示例#7
0
        public override void ConstraintsBiLoad_C(double factor = 1, double recovery_clamp = 0.1, bool do_clamp = false)
        {
            if (!IsActive())
            {
                return;
            }

            double cnstr_dist_violation = do_clamp
                                              ? ChMaths.ChMin(ChMaths.ChMax(factor * (m_cur_dist - m_dist), -recovery_clamp), recovery_clamp)
                                              : factor * (m_cur_dist - m_dist);

            double cnstr_dot_violation =
                do_clamp ? ChMaths.ChMin(ChMaths.ChMax(factor * m_cur_dot, -recovery_clamp), recovery_clamp) : factor * m_cur_dot;

            m_cnstr_dist.Set_b_i(m_cnstr_dist.Get_b_i() + cnstr_dist_violation);
            m_cnstr_dot.Set_b_i(m_cnstr_dot.Get_b_i() + cnstr_dot_violation);
        }
示例#8
0
        public override void IntLoadConstraint_C(int off_L,
                                                 ref ChVectorDynamic <double> Qc,
                                                 double c,
                                                 bool do_clamp,
                                                 double recovery_clamp)
        {
            if (!IsActive())
            {
                return;
            }

            if (do_clamp)
            {
                Qc.matrix[off_L] += ChMaths.ChMin(ChMaths.ChMax(c * (curr_dist - distance), -recovery_clamp), recovery_clamp);
            }
            else
            {
                Qc.matrix[off_L] += c * (curr_dist - distance);
            }
        }
示例#9
0
        public override void IntLoadConstraint_C(int off_L,
                                                 ref ChVectorDynamic <double> Qc,
                                                 double c,
                                                 bool do_clamp,
                                                 double recovery_clamp)
        {
            if (!IsActive())
            {
                return;
            }

            double cnstr_dist_violation =
                do_clamp ? ChMaths.ChMin(ChMaths.ChMax(c * (m_cur_dist - m_dist), -recovery_clamp), recovery_clamp) : c * (m_cur_dist - m_dist);

            double cnstr_dot_violation =
                do_clamp ? ChMaths.ChMin(ChMaths.ChMax(c * m_cur_dot, -recovery_clamp), recovery_clamp) : c * m_cur_dot;

            Qc.matrix[off_L + 0] += cnstr_dist_violation;
            Qc.matrix[off_L + 1] += cnstr_dot_violation;
        }
示例#10
0
        public override void ConstraintsBiLoad_C(double factor = 1, double recovery_clamp = 0.1, bool do_clamp = false)
        {
            double C;

            if (this.avoid_angle_drift)
            {
                C = this.GetMotorRot() - aux_dt - this.rot_offset;
            }
            else
            {
                C = 0.0;
            }

            double res = factor * C;

            if (do_clamp)
            {
                res = ChMaths.ChMin(ChMaths.ChMax(res, -recovery_clamp), recovery_clamp);
            }

            constraint.Set_b_i(constraint.Get_b_i() + res);
        }
示例#11
0
        public override void IntLoadConstraint_C(int off_L, ref ChVectorDynamic <double> Qc, double c, bool do_clamp, double recovery_clamp)
        {
            // Add the time-dependent term in residual C as
            //   C = d_error - d_setpoint - d_offset
            // with d_error = x_pos_A-x_pos_B, and d_setpoint = x(t)
            double C;

            if (this.avoid_angle_drift)
            {
                C = this.GetMotorRot() - aux_dt - this.rot_offset;
            }
            else
            {
                C = 0.0;
            }

            double res = c * C;

            if (do_clamp)
            {
                res = ChMaths.ChMin(ChMaths.ChMax(res, -recovery_clamp), recovery_clamp);
            }
            Qc.matrix[off_L] += res;
        }
示例#12
0
        /// Performs the static analysis,
        /// doing a linear solve.

        public override void StaticAnalysis()
        {
            ChIntegrableIIorder mintegrable = (ChIntegrableIIorder)this.integrable;

            // setup main vectors
            mintegrable.StateSetup(ref X, ref V, ref A);

            ChState                  Xnew = new ChState();
            ChStateDelta             Dx   = new ChStateDelta();
            ChVectorDynamic <double> R    = new ChVectorDynamic <double>();
            ChVectorDynamic <double> Qc   = new ChVectorDynamic <double>();
            double T = 0;

            // setup auxiliary vectors
            Dx.Reset(mintegrable.GetNcoords_v(), GetIntegrable());
            Xnew.Reset(mintegrable.GetNcoords_x(), mintegrable);
            R.Reset(mintegrable.GetNcoords_v());
            Qc.Reset(mintegrable.GetNconstr());
            L.Reset(mintegrable.GetNconstr());

            mintegrable.StateGather(ref X, ref V, ref T);  // state <- system

            // Set speed to zero
            V.matrix.FillElem(0);

            // Extrapolate a prediction as warm start
            Xnew = X;

            // use Newton Raphson iteration to solve implicit Euler for v_new
            //
            // [ - dF/dx    Cq' ] [ Dx  ] = [ f ]
            // [ Cq         0   ] [ L   ] = [ C ]

            for (int i = 0; i < this.GetMaxiters(); ++i)
            {
                mintegrable.StateScatter(Xnew, V, T);  // state -> system
                R.Reset();
                Qc.Reset();
                mintegrable.LoadResidual_F(ref R, 1.0);
                mintegrable.LoadConstraint_C(ref Qc, 1.0);

                double cfactor = ChMaths.ChMin(1.0, ((double)(i + 2) / (double)(incremental_steps + 1)));
                R  *= cfactor;
                Qc *= cfactor;

                //	GetLog()<< "Non-linear statics iteration=" << i << "  |R|=" << R.NormInf() << "  |Qc|=" << Qc.NormInf()
                //<< "\n";
                if ((R.matrix.NormInf() < this.GetTolerance()) && (Qc.matrix.NormInf() < this.GetTolerance()))
                {
                    break;
                }

                mintegrable.StateSolveCorrection(
                    ref Dx, ref L, R, Qc,
                    0,           // factor for  M
                    0,           // factor for  dF/dv
                    -1.0,        // factor for  dF/dx (the stiffness matrix)
                    Xnew, V, T,  // not needed here
                    false,       // do not StateScatter update to Xnew Vnew T+dt before computing correction
                    true         // force a call to the solver's Setup() function
                    );

                Xnew += Dx;
            }

            X = Xnew;

            mintegrable.StateScatter(X, V, T);    // state -> system
            mintegrable.StateScatterReactions(L); // -> system auxiliary data
        }
示例#13
0
        public override void ContIntLoadConstraint_C(int off_L,
                                                     ref ChVectorDynamic <double> Qc,
                                                     double c,
                                                     bool do_clamp,
                                                     double recovery_clamp
                                                     )
        {
            bool bounced = false;

            // Elastic Restitution model (use simple Newton model with coefficient e=v(+)/v(-))
            // Note that this works only if the two connected items are two ChBody.

            if (this.objA != null && this.objB != null)
            {
                var oA = (ChBody)(object)this.objA;
                var oB = (ChBody)(object)this.objB;
                if (this.restitution != 0)
                {
                    // compute normal rebounce speed
                    ChVector V1_w        = oA.GetContactPointSpeed(this.p1);
                    ChVector V2_w        = oB.GetContactPointSpeed(this.p2);
                    ChVector Vrel_w      = V2_w - V1_w;
                    ChVector Vrel_cplane = this.contact_plane.MatrT_x_Vect(Vrel_w);

                    double h = this.container.GetSystem().GetStep();  // = 1.0 / c;  // not all steppers have c = 1/h

                    double neg_rebounce_speed = Vrel_cplane.x * this.restitution;
                    if (neg_rebounce_speed < -this.container.GetSystem().GetMinBounceSpeed())
                    {
                        if (this.norm_dist + neg_rebounce_speed * h < 0)
                        {
                            // CASE: BOUNCE
                            bounced           = true;
                            Qc.matrix[off_L] += neg_rebounce_speed;
                        }
                    }
                }
            }

            if (!bounced)
            {
                // CASE: SETTLE (most often, and also default if two colliding items are not two ChBody)

                if (this.compliance != 0)
                {
                    double h = 1.0 / c;                        // was: this->container->GetSystem()->GetStep(); note not all steppers have c = 1/h

                    double alpha    = this.dampingf;           // [R]=alpha*[K]
                    double inv_hpa  = 1.0 / (h + alpha);       // 1/(h+a)
                    double inv_hhpa = 1.0 / (h * (h + alpha)); // 1/(h*(h+a))

                    //***TODO*** move to KRMmatricesLoad() the following, and only for !bounced case
                    Nx.Set_cfm_i((inv_hhpa) * this.compliance);
                    Tu.Set_cfm_i((inv_hhpa) * this.complianceT);
                    Tv.Set_cfm_i((inv_hhpa) * this.complianceT);

                    double qc = inv_hpa * this.norm_dist;  //***TODO*** see how to move this in KRMmatricesLoad()

                    // Note: clamping of Qc in case of compliance is questionable: it does not limit only the outbound
                    // speed, but also the reaction, so it might allow longer 'sinking' not related to the real compliance.
                    // I.e. If clamping kicks in (when using large timesteps and low compliance), it acts as a numerical damping.
                    if (do_clamp)
                    {
                        qc = ChMaths.ChMax(qc, -recovery_clamp);
                    }

                    Qc.matrix[off_L] += qc;
                }
                else
                {
                    if (do_clamp)
                    {
                        if (this.Nx.Constraint2TuplesNall.GetCohesion() != 0)
                        {
                            Qc.matrix[off_L] += ChMaths.ChMin(0.0, ChMaths.ChMax(c * this.norm_dist, -recovery_clamp));
                        }
                        else
                        {
                            Qc.matrix[off_L] += ChMaths.ChMax(c * this.norm_dist, -recovery_clamp);
                        }
                    }
                    else
                    {
                        Qc.matrix[off_L] += c * this.norm_dist;
                    }
                }
            }
        }
示例#14
0
        /// Performs the solution of the problem.
        /// \return  the maximum constraint violation after termination.
        public override double Solve(ref ChSystemDescriptor sysd  //< system description with constraints and variables
                                     )
        {
            List <ChConstraint> mconstraints = sysd.GetConstraintsList();
            List <ChVariables>  mvariables   = sysd.GetVariablesList();

            double maxviolation    = 0.0;
            double maxdeltalambda  = 0.0;
            int    i_friction_comp = 0;

            double[] old_lambda_friction = new double[3];
            int      nConstr             = mconstraints.Count;
            int      nVars = mvariables.Count;

            // 1)  Update auxiliary data in all constraints before starting,
            //     that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
            for (int ic = 0; ic < nConstr; ic++)
            {
                mconstraints[ic].Update_auxiliary();
            }

            // Average all g_i for the triplet of contact constraints n,u,v.
            int j_friction_comp = 0;

            double[] gi_values = new double[3];
            for (int ic = 0; ic < nConstr; ic++)
            {
                if (mconstraints[ic].GetMode() == eChConstraintMode.CONSTRAINT_FRIC)
                {
                    gi_values[j_friction_comp] = mconstraints[ic].Get_g_i();
                    j_friction_comp++;
                    if (j_friction_comp == 3)
                    {
                        double average_g_i = (gi_values[0] + gi_values[1] + gi_values[2]) / 3.0;
                        mconstraints[ic - 2].Set_g_i(average_g_i);
                        mconstraints[ic - 1].Set_g_i(average_g_i);
                        mconstraints[ic - 0].Set_g_i(average_g_i);
                        j_friction_comp = 0;
                    }
                }
            }

            // 2)  Compute, for all items with variables, the initial guess for
            //     still unconstrained system:
            for (int iv = 0; iv < nVars; iv++)
            {
                if (mvariables[iv].IsActive())
                {
                    mvariables[iv].Compute_invMb_v(mvariables[iv].Get_qb().matrix, mvariables[iv].Get_fb().matrix);  // q = [M]'*fb
                }
            }
            // 3)  For all items with variables, add the effect of initial (guessed)
            //     lagrangian reactions of constraints, if a warm start is desired.
            //     Otherwise, if no warm start, simply resets initial lagrangians to zero.
            if (warm_start)
            {
                for (int ic = 0; ic < nConstr; ic++)
                {
                    if (mconstraints[ic].IsActive())
                    {
                        mconstraints[ic].Increment_q(mconstraints[ic].Get_l_i());
                    }
                }
            }
            else
            {
                for (int ic = 0; ic < nConstr; ic++)
                {
                    mconstraints[ic].Set_l_i(0.0);
                }
            }

            // 4)  Perform the iteration loops
            for (int iter = 0; iter < max_iterations;)
            {
                //
                // Forward sweep, for symmetric SOR
                //
                maxviolation    = 0;
                maxdeltalambda  = 0;
                i_friction_comp = 0;
                int dummy = mconstraints.Count;
                for (int ic = 0; ic < dummy; ic++)
                {
                    // skip computations if constraint not active.
                    if (mconstraints[ic].IsActive())
                    {
                        // compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
                        double mresidual = mconstraints[ic].Compute_Cq_q() + mconstraints[ic].Get_b_i() +
                                           mconstraints[ic].Get_cfm_i() * mconstraints[ic].Get_l_i();

                        // true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
                        double candidate_violation = Math.Abs(mconstraints[ic].Violation(mresidual));

                        // compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
                        double deltal = (omega / mconstraints[ic].Get_g_i()) * (-mresidual);

                        if (mconstraints[ic].GetMode() == eChConstraintMode.CONSTRAINT_FRIC)
                        {
                            candidate_violation = 0;
                            // update:   lambda += delta_lambda;
                            old_lambda_friction[i_friction_comp] = mconstraints[ic].Get_l_i();
                            mconstraints[ic].Set_l_i(old_lambda_friction[i_friction_comp] + deltal);
                            i_friction_comp++;

                            if (i_friction_comp == 1)
                            {
                                candidate_violation = Math.Abs(ChMaths.ChMin(0.0, mresidual));
                            }

                            if (i_friction_comp == 3)
                            {
                                mconstraints[ic - 2].Project();  // the N normal component will take care of N,U,V

                                double new_lambda_0 = mconstraints[ic - 2].Get_l_i();
                                double new_lambda_1 = mconstraints[ic - 1].Get_l_i();
                                double new_lambda_2 = mconstraints[ic - 0].Get_l_i();
                                // Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
                                if (this.shlambda != 1.0)
                                {
                                    new_lambda_0 = shlambda * new_lambda_0 + (1.0 - shlambda) * old_lambda_friction[0];
                                    new_lambda_1 = shlambda * new_lambda_1 + (1.0 - shlambda) * old_lambda_friction[1];
                                    new_lambda_2 = shlambda * new_lambda_2 + (1.0 - shlambda) * old_lambda_friction[2];
                                    mconstraints[ic - 2].Set_l_i(new_lambda_0);
                                    mconstraints[ic - 1].Set_l_i(new_lambda_1);
                                    mconstraints[ic - 0].Set_l_i(new_lambda_2);
                                }
                                double true_delta_0 = new_lambda_0 - old_lambda_friction[0];
                                double true_delta_1 = new_lambda_1 - old_lambda_friction[1];
                                double true_delta_2 = new_lambda_2 - old_lambda_friction[2];
                                mconstraints[ic - 2].Increment_q(true_delta_0);
                                mconstraints[ic - 1].Increment_q(true_delta_1);
                                mconstraints[ic - 0].Increment_q(true_delta_2);

                                if (this.record_violation_history)
                                {
                                    maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta_0));
                                    maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta_1));
                                    maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta_2));
                                }
                                i_friction_comp = 0;
                            }
                        }
                        else
                        {
                            // update:   lambda += delta_lambda;
                            double old_lambda = mconstraints[ic].Get_l_i();
                            mconstraints[ic].Set_l_i(old_lambda + deltal);

                            // If new lagrangian multiplier does not satisfy inequalities, project
                            // it into an admissible orthant (or, in general, onto an admissible set)
                            mconstraints[ic].Project();

                            // After projection, the lambda may have changed a bit..
                            double new_lambda = mconstraints[ic].Get_l_i();

                            // Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
                            if (this.shlambda != 1.0)
                            {
                                new_lambda = shlambda * new_lambda + (1.0 - shlambda) * old_lambda;
                                mconstraints[ic].Set_l_i(new_lambda);
                            }

                            double true_delta = new_lambda - old_lambda;

                            // For all items with variables, add the effect of incremented
                            // (and projected) lagrangian reactions:
                            mconstraints[ic].Increment_q(true_delta);

                            if (this.record_violation_history)
                            {
                                maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta));
                            }
                        }

                        maxviolation = ChMaths.ChMax(maxviolation, Math.Abs(candidate_violation));
                    } // end IsActive()
                }     // end constraint loop

                // Terminate the loop if violation in constraints has been successfully limited.
                // if (maxviolation < tolerance)
                //	break;

                // For recording into violation history, if debugging
                if (this.record_violation_history)
                {
                    AtIterationEnd(maxviolation, maxdeltalambda, iter);
                }

                // Increment iter count (each sweep, either forward or backward, is considered
                // as a complete iteration, to be fair when comparing to the non-symmetric SOR :)
                iter++;

                //
                // Backward sweep, for symmetric SOR
                //
                maxviolation    = 0.0;
                maxdeltalambda  = 0.0;
                i_friction_comp = 0;

                for (int ic = (nConstr - 1); ic >= 0; ic--)
                {
                    // skip computations if constraint not active.
                    if (mconstraints[ic].IsActive())
                    {
                        // compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
                        double mresidual = mconstraints[ic].Compute_Cq_q() + mconstraints[ic].Get_b_i() +
                                           mconstraints[ic].Get_cfm_i() * mconstraints[ic].Get_l_i();

                        // true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
                        double candidate_violation = Math.Abs(mconstraints[ic].Violation(mresidual));

                        // compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
                        double deltal = (omega / mconstraints[ic].Get_g_i()) * (-mresidual);

                        if (mconstraints[ic].GetMode() == eChConstraintMode.CONSTRAINT_FRIC)
                        {
                            candidate_violation = 0;
                            // update:   lambda += delta_lambda;
                            old_lambda_friction[i_friction_comp] = mconstraints[ic].Get_l_i();
                            mconstraints[ic].Set_l_i(old_lambda_friction[i_friction_comp] + deltal);
                            i_friction_comp++;
                            if (i_friction_comp == 3)
                            {
                                mconstraints[ic].Project();  // the N normal component will take care of N,U,V

                                double new_lambda_0 = mconstraints[ic + 2].Get_l_i();
                                double new_lambda_1 = mconstraints[ic + 1].Get_l_i();
                                double new_lambda_2 = mconstraints[ic + 0].Get_l_i();
                                // Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
                                if (this.shlambda != 1.0)
                                {
                                    new_lambda_0 = shlambda * new_lambda_0 + (1.0 - shlambda) * old_lambda_friction[0];
                                    new_lambda_1 = shlambda * new_lambda_1 + (1.0 - shlambda) * old_lambda_friction[1];
                                    new_lambda_2 = shlambda * new_lambda_2 + (1.0 - shlambda) * old_lambda_friction[2];
                                    mconstraints[ic + 2].Set_l_i(new_lambda_0);
                                    mconstraints[ic + 1].Set_l_i(new_lambda_1);
                                    mconstraints[ic + 0].Set_l_i(new_lambda_2);
                                }
                                double true_delta_0 = new_lambda_0 - old_lambda_friction[0];
                                double true_delta_1 = new_lambda_1 - old_lambda_friction[1];
                                double true_delta_2 = new_lambda_2 - old_lambda_friction[2];
                                mconstraints[ic + 2].Increment_q(true_delta_0);
                                mconstraints[ic + 1].Increment_q(true_delta_1);
                                mconstraints[ic + 0].Increment_q(true_delta_2);

                                candidate_violation = Math.Abs(ChMaths.ChMin(0.0, mresidual));

                                if (this.record_violation_history)
                                {
                                    maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta_0));
                                    maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta_1));
                                    maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta_2));
                                }
                                i_friction_comp = 0;
                            }
                        }
                        else
                        {
                            // update:   lambda += delta_lambda;
                            double old_lambda = mconstraints[ic].Get_l_i();
                            mconstraints[ic].Set_l_i(old_lambda + deltal);

                            // If new lagrangian multiplier does not satisfy inequalities, project
                            // it into an admissible orthant (or, in general, onto an admissible set)
                            mconstraints[ic].Project();

                            // After projection, the lambda may have changed a bit..
                            double new_lambda = mconstraints[ic].Get_l_i();

                            // Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
                            if (this.shlambda != 1.0)
                            {
                                new_lambda = shlambda * new_lambda + (1.0 - shlambda) * old_lambda;
                                mconstraints[ic].Set_l_i(new_lambda);
                            }

                            double true_delta = new_lambda - old_lambda;

                            // For all items with variables, add the effect of incremented
                            // (and projected) lagrangian reactions:
                            mconstraints[ic].Increment_q(true_delta);

                            if (this.record_violation_history)
                            {
                                maxdeltalambda = ChMaths.ChMax(maxdeltalambda, Math.Abs(true_delta));
                            }
                        }

                        maxviolation = ChMaths.ChMax(maxviolation, Math.Abs(candidate_violation));
                    } // end IsActive()
                }     // end loop on constraints

                // For recording into violation history, if debugging
                if (this.record_violation_history)
                {
                    AtIterationEnd(maxviolation, maxdeltalambda, iter);
                }

                // Terminate the loop if violation in constraints has been successfully limited.
                if (maxviolation < tolerance)
                {
                    break;
                }

                iter++;
            }

            return(maxviolation);
        }
示例#15
0
 /// Set the user modulation of the torque (or brake, if you use it between
 /// a fixed shaft and a free shaft). The modulation must range from
 /// 0 (switched off) to 1 (max torque). Default is 1, when clutch is created.
 /// You can update this during integration loop to simulate the pedal pushing by the driver.
 public void SetModulation(double mm)
 {
     modulation = ChMaths.ChMax(ChMaths.ChMin(mm, 1.0), 0.0);
 }