Exemplo n.º 1
0
        /// Initialize again this constraint.
        public override void Reset(Ta mobjA,                       //< collidable object A
                                   Tb mobjB,                       //< collidable object B
                                   collision.ChCollisionInfo cinfo //< data for the contact pair
                                   )                               //where T1: IntInterface.IBase
        {
            // Inherit base class.
            base.Reset(mobjA, mobjB, cinfo);

            // Note: cinfo.distance is the same as this.norm_dist.
            // Debug.Assert(cinfo.distance < 0);

            ChBody oA = (this.objA as ChBody);
            ChBody oB = (this.objB as ChBody);

            // Calculate composite material properties
            ChMaterialCompositeSMC mat = new ChMaterialCompositeSMC(
                this.container.GetSystem().composition_strategy,
                (ChMaterialSurfaceSMC)(oA.GetMaterialSurfaceBase()),
                (ChMaterialSurfaceSMC)(oB.GetMaterialSurfaceBase()));

            // Check for a user-provided callback to modify the material
            if (this.container.GetAddContactCallback() != null)
            {
                this.container.GetAddContactCallback().OnAddContact(cinfo, mat);
            }

            // Calculate contact force.
            m_force = CalculateForce(-this.norm_dist,                   // overlap (here, always positive)
                                     this.normal,                       // normal contact direction
                                     oA.GetContactPointSpeed(this.p1),  // velocity of contact point on objA
                                     oB.GetContactPointSpeed(this.p2),  // velocity of contact point on objB
                                     mat                                // composite material for contact pair
                                     );

            ChSystemSMC smc = (ChSystemSMC)this.container.GetSystem();

            // Set up and compute Jacobian matrices.
            if (smc.GetStiffContact() == true)
            {
                CreateJacobians();
                CalculateJacobians(mat);
            }
        }
Exemplo n.º 2
0
        /// Calculate contact force, expressed in absolute coordinates.
        public ChVector CalculateForce(
            double delta,              //< overlap in normal direction
            ChVector normal_dir,       //< normal contact direction (expressed in global frame)
            ChVector vel1,             //< velocity of contact point on objA (expressed in global frame)
            ChVector vel2,             //< velocity of contact point on objB (expressed in global frame)
            ChMaterialCompositeSMC mat //< composite material for contact pair
            )
        {
            // Set contact force to zero if no penetration.
            if (delta <= 0)
            {
                return(new ChVector(0, 0, 0));
            }

            // Extract parameters from containing system
            ChSystemSMC sys           = (ChSystemSMC)(this.container.GetSystem());
            double      dT            = sys.GetStep();
            bool        use_mat_props = sys.UsingMaterialProperties();

            ChSystemSMC.ContactForceModel           contact_model  = sys.GetContactForceModel();
            ChSystemSMC.AdhesionForceModel          adhesion_model = sys.GetAdhesionForceModel();
            ChSystemSMC.TangentialDisplacementModel tdispl_model   = sys.GetTangentialDisplacementModel();

            // Relative velocity at contact
            ChVector relvel       = vel2 - vel1;
            double   relvel_n_mag = relvel.Dot(normal_dir);
            ChVector relvel_n     = relvel_n_mag * normal_dir;
            ChVector relvel_t     = relvel - relvel_n;
            double   relvel_t_mag = relvel_t.Length();

            ChBody oA = (this.objA as ChBody);
            ChBody oB = (this.objB as ChBody);

            // Calculate effective mass
            double eff_mass = oA.GetContactableMass() * oB.GetContactableMass() /
                              (oA.GetContactableMass() + oB.GetContactableMass());

            // Calculate stiffness and viscous damping coefficients.
            // All models use the following formulas for normal and tangential forces:
            //     Fn = kn * delta_n - gn * v_n
            //     Ft = kt * delta_t - gt * v_t
            double kn = 0;
            double kt = 0;
            double gn = 0;
            double gt = 0;

            double eps = double.Epsilon;

            switch (contact_model)
            {
            case ChSystemSMC.ContactForceModel.Hooke:
                if (use_mat_props)
                {
                    double tmp_k = (16.0 / 15) * Math.Sqrt(this.eff_radius) * mat.E_eff;
                    double v2    = sys.GetCharacteristicImpactVelocity() * sys.GetCharacteristicImpactVelocity();
                    double loge  = (mat.cr_eff < eps) ? Math.Log(eps) : Math.Log(mat.cr_eff);
                    loge = (mat.cr_eff > 1 - eps) ? Math.Log(1 - eps) : loge;
                    double tmp_g = 1 + Math.Pow(ChMaths.CH_C_PI / loge, 2);
                    kn = tmp_k * Math.Pow(eff_mass * v2 / tmp_k, 1.0 / 5);
                    kt = kn;
                    gn = Math.Sqrt(4 * eff_mass * kn / tmp_g);
                    gt = gn;
                }
                else
                {
                    kn = mat.kn;
                    kt = mat.kt;
                    gn = eff_mass * mat.gn;
                    gt = eff_mass * mat.gt;
                }

                break;

            case ChSystemSMC.ContactForceModel.Hertz:
                if (use_mat_props)
                {
                    double sqrt_Rd = Math.Sqrt(this.eff_radius * delta);
                    double Sn      = 2 * mat.E_eff * sqrt_Rd;
                    double St      = 8 * mat.G_eff * sqrt_Rd;
                    double loge    = (mat.cr_eff < eps) ? Math.Log(eps) : Math.Log(mat.cr_eff);
                    double beta    = loge / Math.Sqrt(loge * loge + ChMaths.CH_C_PI * ChMaths.CH_C_PI);
                    kn = (2.0 / 3) * Sn;
                    kt = St;
                    gn = -2 * Math.Sqrt(5.0 / 6) * beta * Math.Sqrt(Sn * eff_mass);
                    gt = -2 * Math.Sqrt(5.0 / 6) * beta * Math.Sqrt(St * eff_mass);
                }
                else
                {
                    double tmp = this.eff_radius * Math.Sqrt(delta);
                    kn = tmp * mat.kn;
                    kt = tmp * mat.kt;
                    gn = tmp * eff_mass * mat.gn;
                    gt = tmp * eff_mass * mat.gt;
                }

                break;

            case ChSystemSMC.ContactForceModel.PlainCoulomb:
                if (use_mat_props)
                {
                    double sqrt_Rd = Math.Sqrt(delta);
                    double Sn      = 2 * mat.E_eff * sqrt_Rd;
                    double St      = 8 * mat.G_eff * sqrt_Rd;
                    double loge    = (mat.cr_eff < eps) ? Math.Log(eps) : Math.Log(mat.cr_eff);
                    double beta    = loge / Math.Sqrt(loge * loge + ChMaths.CH_C_PI * ChMaths.CH_C_PI);
                    kn = (2.0 / 3) * Sn;
                    gn = -2 * Math.Sqrt(5.0 / 6) * beta * Math.Sqrt(Sn * eff_mass);
                }
                else
                {
                    double tmp = Math.Sqrt(delta);
                    kn = tmp * mat.kn;
                    gn = tmp * mat.gn;
                }

                kt = 0;
                gt = 0;

                {
                    double forceNb = kn * delta - gn * relvel_n_mag;
                    if (forceNb < 0)
                    {
                        forceNb = 0;
                    }
                    double forceTb = mat.mu_eff * Math.Tanh(5.0 * relvel_t_mag) * forceNb;
                    switch (adhesion_model)
                    {
                    case ChSystemSMC.AdhesionForceModel.Constant:
                        forceNb -= mat.adhesion_eff;
                        break;

                    case ChSystemSMC.AdhesionForceModel.DMT:
                        forceNb -= mat.adhesionMultDMT_eff * Math.Sqrt(this.eff_radius);
                        break;
                    }
                    ChVector forceb = forceNb * normal_dir;
                    if (relvel_t_mag >= sys.GetSlipVelocityThreshold())
                    {
                        forceb -= (forceTb / relvel_t_mag) * relvel_t;
                    }

                    return(forceb);
                }
            }

            // Tangential displacement (magnitude)
            double delta_t = 0;

            switch (tdispl_model)
            {
            case ChSystemSMC.TangentialDisplacementModel.OneStep:
                delta_t = relvel_t_mag * dT;
                break;

            case ChSystemSMC.TangentialDisplacementModel.MultiStep:
                //// TODO: implement proper MultiStep mode
                delta_t = relvel_t_mag * dT;
                break;

            default:
                break;
            }

            // Calculate the magnitudes of the normal and tangential contact forces
            double forceN = kn * delta - gn * relvel_n_mag;
            double forceT = kt * delta_t + gt * relvel_t_mag;

            // If the resulting normal contact force is negative, the two shapes are moving
            // away from each other so fast that no contact force is generated.
            if (forceN < 0)
            {
                forceN = 0;
                forceT = 0;
            }

            // Include adhesion force
            switch (adhesion_model)
            {
            case ChSystemSMC.AdhesionForceModel.Constant:
                forceN -= mat.adhesion_eff;
                break;

            case ChSystemSMC.AdhesionForceModel.DMT:
                forceN -= mat.adhesionMultDMT_eff * Math.Sqrt(this.eff_radius);
                break;
            }

            // Coulomb law
            forceT = Math.Min(forceT, mat.mu_eff * Math.Abs(forceN));

            // Accumulate normal and tangential forces
            ChVector force = forceN * normal_dir;

            if (relvel_t_mag >= sys.GetSlipVelocityThreshold())
            {
                force -= (forceT / relvel_t_mag) * relvel_t;
            }

            return(force);
        }