package jass.contact; import jass.engine.*; /** A force model based on stick slip model. Karnopp model. Model is in terms of q(t): Md^2q/dt^2 + k_d dq/dt + k_s q(t) = G(dq/dt) FOR |v-dq/dt| > vc @author Kees van den Doel (kvdoel@cs.ubc.ca) */ public class KarnoppFriction extends Out { private float srate; // sampling rate in Hertz private float k_damp; // damping of model private float k_spring; // spring constant of model private float mu_static; // static (Stribeck) friction coeff. private float mu_dynamic; // dynamic friction coeff. private float v_crit; // critical velocity of model private float mass; // masss of effective model private double qt_1,rt_1; // last state private float v=1; // external slide velocity in m/s private float fn=1; // external normal force in Newton /** Construct force. @param srate sampling rate in Hertz. @param bufferSize bufferSize of this Out. */ public KarnoppFriction(float srate, int bufferSize) { super(bufferSize); this.srate = srate; reset(); } /** Set stick-slip model parameters (all in S.I. units). @param k_damp damping of spring system @param mu_static static friction coeff @param mu_dynamic dynamic friction coeff @param v_crit critical velocity for transition from dyn. to static friction */ public void setStickSlipParameters(float mass,float k_damp,float k_spring,float mu_static,float mu_dynamic,float v_crit) { this.k_damp = k_damp; this.k_spring = k_spring; this.mu_static = mu_static; this.mu_dynamic = mu_dynamic; this.v_crit = v_crit; this.mass = mass; } /** Set normal force magnitude. @param val normal force in Newton */ public void setNormalForce(float val) { fn = val; } /** Set velocity. @param v velocity in m/s */ public void setSpeed(float v) { this.v = v; } /** Reset state. */ public void reset() { qt_1 = rt_1 = 0; } /** G2(r) = Fn*sign(v-r) *[ mu_dyn + mu_stat (if|(v-r)|>vc] */ private double G2(double r) { double x = v - r; int signOf = (x > 0 ? 1 : -1); double absx = Math.abs(x); double ret = signOf*fn*(mu_dynamic + mu_static * (absx>v_crit?0:1)); return ret; } /** Compute the next buffer. Discrete model with r = dq/dt: r(t+1) = (1-k_d/(srate*M))r(t) - k_s/(srate*M) * q(t)+G(r(t))/(M*srate) q(t+1) = q(t)+r(t)/srate */ public void computeBuffer() { double foos = k_spring/(mass * srate); double food = 1. - k_damp/(mass * srate); double bard = fn*mu_dynamic/(mass * srate); double bars = fn*mu_static/(mass * srate); int bufsz = getBufferSize(); for(int k=0;k<bufsz;k++) { double vdiff = v - rt_1; double absvdiff,rnew,qnew; int signOf; if(vdiff>0) { absvdiff = vdiff; signOf = 1; } else { absvdiff = -vdiff; signOf = -1; } if(absvdiff > v_crit) { // slip rnew = food * rt_1 - foos*qt_1 + bard*signOf; qnew = qt_1 + rt_1/srate; } else { // sticking double breakAwayForce = fn * mu_static; double appliedForce = Math.abs(k_spring*qt_1+k_damp*rt_1); if(appliedForce > breakAwayForce) { // slipping in static friction region rnew = food * rt_1 - foos*qt_1 + bars*signOf; qnew = qt_1 + rt_1/srate; } else { // stick rnew = v; //rnew = rt_1; // zero force qnew = qt_1 + rt_1/srate; } } buf[k] = (float)(rt_1+rnew); qt_1 = qnew; rt_1 = rnew; //System.out.println("q="+qnew); } } }