% Force-Length-Velocity function of MuJoCo muscle model % Defaults: FLV(0.5, 1.6, 1.5, 1.3, 1.2) function FLV(lmin, lmax, vmax, fpmax, fvmax) % derived quantities a = 0.5*(lmin+1); b = 0.5*(1+lmax); c = fvmax-1; % length and velocity ranges to plot LL = linspace(lmin, lmax, 51); VV = linspace(-vmax, vmax, 51); % length-passive FP = zeros(size(LL)); for i=1:length(LL) L = LL(i); if L<=1 FP(i) = 0; elseif L<=b x = (L-1)/(b-1); FP(i) = 0.25*fpmax*x*x*x; else x = (L-b)/(b-1); FP(i) = 0.25*fpmax*(1+3*x); end end % length-active FL = zeros(size(LL)); for i=1:length(LL) L = LL(i); FL(i) = bump(L, lmin, 1, lmax) + 0.15*bump(L, lmin, 0.5*(lmin+0.95), 0.95); end % velocity-active FV = zeros(size(VV)); for i=1:length(VV) V = VV(i)/vmax; if V<=-1 FV(i) = 0; elseif V<=0 FV(i) = (V+1)*(V+1); elseif V<=c FV(i) = fvmax - (c-V)*(c-V)/c; else FV(i) = fvmax; end end % plot length figure(1); clf; subplot(2,2,1); plot(LL, FL, 'r', 'linewidth', 1); hold on; plot(LL, 0.5*FL, 'b', 'linewidth', 1); plot(LL, FP, 'k', 'linewidth', 1); axis tight; xlabel('length (L0)'); ylabel('force (F0)'); text(0.9, 0.85, 'act = 1.0'); text(0.9, 0.4, 'act = 0.5'); text(1.3, 1.2, 'passive'); box off; grid on; set(gca, 'xtick', [lmin 1 lmax], 'xticklabel', {'lmin', '1', 'lmax'}, ... 'ytick', [0 1 fpmax], 'yticklabel', {'0', '1', 'fpmax'}); % plot velocity subplot(2,2,2); set( plot(VV, FV, 'linewidth', 1), 'color', [.1 .5 .1]); axis tight; xlabel('velocity (L0/s)'); ylabel('force (F0)'); box off; grid on; set(gca, 'xtick', [-vmax 0 vmax], 'xticklabel', {'-vmax', '0', 'vmax'}, ... 'ytick', [0 1 fvmax], 'yticklabel', {'0', '1', 'fvmax'}); % plot full activation subplot(2,2,3); surf(LL, VV, FV'*FL + ones(size(VV))'*FP); axis tight; xlabel('length'); ylabel('velocity'); zlabel('force'); title('act = 1.0'); box off; set(gca, 'xtick', [lmin, 1, lmax], 'ytick', [-vmax, 0, vmax], 'ztick', [0, 1]); % plot half activation subplot(2,2,4); surf(LL, VV, 0.5*FV'*FL + ones(size(VV))'*FP); axis tight; xlabel('length'); ylabel('velocity'); zlabel('force'); title('act = 0.5'); box off; set(gca, 'xtick', [lmin, 1, lmax], 'ytick', [-vmax, 0, vmax], 'ztick', [0, 1]); end % skewed bump function: quadratic spline function y = bump(L, A, mid, B) left = 0.5*(A+mid); right = 0.5*(mid+B); if (L<=A) || (L>=B) y = 0; elseif L