5,Matlab仿真passive walker

动力学

行走动力学

平面被动行走机器人共有四个自由度,分别是两个夹角和两个绝对坐标,可以使用拉格朗日方程得到被动行走机器人的动力学方程。需要注意的是,在行走过程中,只有一只腿撑住地面,因此只需要求解一条腿的雅可比矩阵

碰撞动力学

当空中摆动腿和地面接触时,会产生一个顺势冲量,此时,行走动力学方程失效,可以将动力学方程对这个瞬间做积分,而后求解方程,得到碰撞后的解。

代码

动力学推导部分

本部分使用符号推导,得到被动行走机器人的行走动力学模型和碰撞动力学模型。

function my_drive
clc 
clear
close all

syms M m I real; % M:Hip的质量,m:腿的质量,I:绕质心转动惯量
syms c l real;
syms gam g real;
syms theta1 theta2 real;
syms theta1dot theta2dot real;
syms theta1ddot theta2ddot real;
syms theta1_n theta2_n real;
syms theta1dot_n theta2dot_n real;
syms x y real;
syms xdot ydot real;
syms xddot yddot real;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%            坐标转换            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
G11 = [(l-c);0;1];
G22 = [c;0;1];
C22 = [l;0;1];
H11 = [l;0;1];
O01 = [x;y];
O12 = [l;0];
% 变换矩阵
R01 = simplify([cos(pi/2+theta1-gam) -sin(pi/2+theta1-gam); ...
               sin(pi/2+theta1-gam) cos(pi/2+theta1-gam)]);
R12 = simplify([cos(pi+theta2) -sin(pi+theta2); ...
               sin(pi+theta2) cos(pi+theta2)]);

H01 = [R01 O01;0 0 1];
H12 = [R12 O12;0 0 1];
% 坐标变换
R_G1 = H01*G11;
r_G1 = R_G1(1:2);
x_G1 = r_G1(1); y_G1 = r_G1(2);

R_H = H01*H11;
r_H = R_H(1:2);
x_H = r_H(1); y_H = r_H(2);

R_G2 = H01*H12*G22;
r_G2 = R_G2(1:2);
x_G2 = r_G2(1); y_G2 = r_G2(2);

R_C2 = H01*H12*C22;
r_C2 = R_C2(1:2);
x_C2 = r_C2(1); y_C2 = r_C2(2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%            速度变换            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

v_H = jacobian(r_H,[x y theta1 theta2])*[xdot ydot theta1dot theta2dot]';
v_G1 = jacobian(r_G1,[x y theta1 theta2])*[xdot ydot theta1dot theta2dot]';
v_G2 = jacobian(r_G2,[x y theta1 theta2])*[xdot ydot theta1dot theta2dot]';


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%          拉格朗日方程           %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

T = 0.5*(simplify((M*dot(v_H,v_H)+m*dot(v_G1,v_G1)+m*dot(v_G2,v_G2) + ...
         I*dot(theta1dot,theta1dot)+I*dot(theta1dot + theta2dot,theta1dot + theta2dot))));
V = simplify(m*g*(y_G1 + y_G2) + M*g*y_H);
L = T - V;

q = [x y theta1 theta2];
qdot = [xdot ydot theta1dot theta2dot];
qddot = [xddot yddot theta1ddot theta2ddot];


for i = 1:4
    dLdqdot(i) = diff(L,qdot(i));
    % 链式法则求解对时间的导数
    ddt_dLdqdot(i) = diff(dLdqdot(i),q(1))*qdot(1) + diff(dLdqdot(i),qdot(1)) * qddot(1) + ...
                     diff(dLdqdot(i),q(2))*qdot(2) + diff(dLdqdot(i),qdot(2)) * qddot(2) + ...
                     diff(dLdqdot(i),q(3))*qdot(3) + diff(dLdqdot(i),qdot(3)) * qddot(3) + ...
                     diff(dLdqdot(i),q(4))*qdot(4) + diff(dLdqdot(i),qdot(4)) * qddot(4);
    dLdq(i) = diff(L,q(i));
    Eom(i) = simplify(ddt_dLdqdot(i) - dLdq(i));
end

%%%% 分别计算矩阵 %%%%
% M(q)qddot = B(q,qdot) +JPc
M_ss = jacobian(Eom,[xddot yddot theta1ddot theta2ddot]); % 4*4 矩阵
b_ss(1,1) = -subs(Eom(1),qddot,[0 0 0 0]);
b_ss(2,1) = -subs(Eom(2),qddot,[0 0 0 0]);
b_ss(3,1) = -subs(Eom(3),qddot,[0 0 0 0]);
b_ss(4,1) = -subs(Eom(4),qddot,[0 0 0 0]);

disp('以下是本程序使用符号推导得到的内容');
disp('1,摆动相');

% 摆动相过程中,x,y并不运动,不参与动力学方程,只要M_ss右下角的2*2方阵和B的(3:4)
disp(['A11 = ',char(simplify(M_ss(3,3))),';']);
disp(['A12 = ',char(simplify(M_ss(3,4))),';']);
disp(['A21 = ',char(simplify(M_ss(4,3))),';']);
disp(['A22 = ',char(simplify(M_ss(4,4))),';']);
disp('A_ss = [A11 A12;A21 A22]');
disp(' ');
disp(['b1 = ',char(simplify(b_ss(3,1))),';']);
disp(['b2 = ',char(simplify(b_ss(4,1))),';']);
disp(['b_ss = [b1;b2]',';']);
disp(' ');
disp(['qddot = M_ss\b_ss',';']);
disp(' ');
disp(' ');

% 两脚同时触地
J_newleg = jacobian(r_C2,q);% 2*4的矩阵
J_num_newleg = subs(J_newleg,[theta1 theta2],[theta1_n theta2_n]);
A_num_newleg = subs(M_ss,[theta1 theta2],[theta1_n theta2_n]);
disp(' ');
disp('两腿触地瞬间的方程如下:');
disp(' ');
disp(['J11 = ',char(simplify(J_num_newleg(1,1))),';']);
disp(['J12 = ',char(simplify(J_num_newleg(1,2))),';']);
disp(['J13 = ',char(simplify(J_num_newleg(1,3))),';']);
disp(['J14 = ',char(simplify(J_num_newleg(1,4))),';']);
disp(['J21 = ',char(simplify(J_num_newleg(2,1))),';']);
disp(['J22 = ',char(simplify(J_num_newleg(2,2))),';']);
disp(['J23 = ',char(simplify(J_num_newleg(2,3))),';']);
disp(['J24 = ',char(simplify(J_num_newleg(2,4))),';']);
disp('J = [J11 J12 J13 J14;J21 J22 J23 J24];');
disp(' ')

disp(['A11 = ',char(simplify(A_num_newleg(1,1))),';']);
disp(['A12 = ',char(simplify(A_num_newleg(1,2))),';']);
disp(['A13 = ',char(simplify(A_num_newleg(1,3))),';']);
disp(['A14 = ',char(simplify(A_num_newleg(1,4))),';']);
disp(['A21 = ',char(simplify(A_num_newleg(2,1))),';']);
disp(['A22 = ',char(simplify(A_num_newleg(2,2))),';']);
disp(['A23 = ',char(simplify(A_num_newleg(2,3))),';']);
disp(['A24 = ',char(simplify(A_num_newleg(2,4))),';']);
disp(['A31 = ',char(simplify(A_num_newleg(3,1))),';']);
disp(['A32 = ',char(simplify(A_num_newleg(3,2))),';']);
disp(['A33 = ',char(simplify(A_num_newleg(3,3))),';']);
disp(['A34 = ',char(simplify(A_num_newleg(3,4))),';']);
disp(['A41 = ',char(simplify(A_num_newleg(4,1))),';']);
disp(['A42 = ',char(simplify(A_num_newleg(4,2))),';']);
disp(['A43 = ',char(simplify(A_num_newleg(4,3))),';']);
disp(['A44 = ',char(simplify(A_num_newleg(4,4))),';']);
disp('A_n_hs = [A11 A12 A13 A14; A21 A22 A23 A24; A31 A32 A33 A34; A41 A42 A43 A44];');
disp(' ');

disp('X_num_newleg = [0 0 theta1dot_n theta2dot_n]'';'); %[vx_stance vy_stance omega1 omega2]
disp('b_hs = [A_n_hs*X_n_hs; 0; 0];'); %[momentum before footstrike = A_n_hs*X_n_hs; v_swing_foot_after_foot_strike = 0 0 
disp('A_hs = [A_n_hs -J'' ; J zeros(2,2)];');
disp('X_hs = A_hs\b_hs;');
disp('thetadot(1) = X_hs(3)+X_hs(4); thetadot(2) = -X_hs(4);');
disp(' ');
disp(' ');

仿真部分

本部分带入动力学模型,带入数据,得到仿真结果。

function passivewalker_sim

clc
close all
format long
 
%%%% Dimensions %%
%%% c = COM on the leg from hip M = hip mass, m = leg mass, I = leg inertia, l = leg length
walker.M = 1.0; walker.m = 0.5; walker.I = 0.02; walker.l = 1.0; 
walker.c = 0.5; walker.g = 1.0; walker.gam = 0.01; 

%%%% Initial State %%%%%
q1 = 0.2; u1 = -0.25; %q1 = theta1; u1 = omega1
q2 = -0.4; u2 = 0.2; %Try different u2 to get second root

z0 = [q1 u1 q2 u2];

steps = 3; %number of steps to animate
fps = 20; %Use low frames per second for low gravity
flag_analyze = 1;

if (flag_analyze==0)
%%% forward simulation  %%%
[z,t] = onestep(z0,walker,steps);
figure(1)
animate(t,z,walker,steps,fps);
else
% % %%% Root finding will give this stable root 
% zstar = [0.162597833780041  -0.231869638058930  -0.325195667560083   0.037978468073743]
% onestep(zstar,walker)
% %%%%%%%%%%%%%%%%%%%%%%%%%

%%%% Root finding, Period one gait %%%%
options = optimset('TolFun',1e-12,'TolX',1e-12,'Display','off');
[zstar,fval,exitflag] = fsolve(@fixedpt,z0,options,walker);
if exitflag == 1
    disp('Fixed point:');
    disp(zstar);
else
    error('Root finder not converged, change guess or change system parameters')
end

%%% Stability, using eigenvalues of Poincare map %%%
J=partialder(@onestep,zstar,walker);
disp('EigenValues for linearized map are');
eigJ = eig(J);
for i=1:4
    disp(norm(eigJ(i)));
end

%%% forward simulation  %%%
[z,t] = onestep(zstar,walker,steps);

%%%% Animate result %%%
disp('Animating...');
figure(1)
animate(t,z,walker,steps,fps);

end

%%% Plot data %%%
disp('Some plots...')
figure(2)
subplot(2,1,1);
title('passive walker position and velocity as a function of time');
plot(t,z(:,1),'r--','Linewidth',3); hold on
plot(t,z(:,3),'b','Linewidth',2);
ylabel('position','Fontsize',12);
legend('\theta_1','\theta_2','Location','best','Fontsize',12);
subplot(2,1,2)
plot(t,z(:,2),'r--','Linewidth',3); hold on
plot(t,z(:,4),'b','Linewidth',2);
ylabel('velocity','Fontsize',12);
xlabel('time','Fontsize',12);
legend('\theta_1','\theta_2','Location','best','Fontsize',12);

% %%% forward simulation  %%%
% z_pert = zstar + [0 0.01 0 0.05];
% [z,t] = onestep(z_pert,walker,steps);
% 

% figure(4)
% subplot(2,1,1);
% title('passive walker absolute leg angle rate versus absolute leg angle');
% plot(z(:,1),z(:,2),'r','Linewidth',3); hold on;
% plot(z(1,1),z(1,2),'ko','Markersize',10,'MarkerFaceColor','k');
% text(z(1,1)+0.01,z(1,2)+0.01,'start','Fontsize',12)
% ylabel('$\dot{\theta}_1$','Fontsize',12,'Interpreter','Latex');
% xlabel('\theta_1','Fontsize',12);
% subplot(2,1,2);
% plot(z(:,1)+z(:,3),z(:,2)+z(:,4),'b','Linewidth',2); hold on;
% plot(z(1,1)+z(1,3),z(1,2)+z(1,4),'ko','Markersize',10,'MarkerFaceColor','k');
% text(z(1,1)+z(1,3)+0.01,z(1,2)+z(1,4)+0.01,'start','Fontsize',12)
% ylabel('$\dot{\theta}_1+\dot{\theta}_2$','Fontsize',12,'Interpreter','Latex');
% xlabel('\theta_1+\theta_2','Fontsize',12);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% FUNCTIONS START HERE %%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%===================================================================
function zdiff=fixedpt(z0,walker)
%===================================================================
zdiff=onestep(z0,walker)-z0; 

%===================================================================
function J=partialder(FUN,z,walker)
%===================================================================
pert=1e-5;
n = length(z);
J = zeros(n,n);

%%%% Using forward difference, accuracy linear %%%
% y0=feval(FUN,z,walker); 
% for i=1:n
%     ztemp=z;
%     ztemp(i)=ztemp(i)+pert; 
%     J(:,i)=(feval(FUN,ztemp,walker)-y0) ;
% end
% J=(J/pert);

%%% Using central difference, accuracy quadratic %%%
for i=1:n
    ztemp1=z; ztemp2=z;
    ztemp1(i)=ztemp1(i)+pert; 
    ztemp2(i)=ztemp2(i)-pert; 
    J(:,i)=(feval(FUN,ztemp1,walker)-feval(FUN,ztemp2,walker)) ;
end
J=J/(2*pert);

%===================================================================
function [z,t]=onestep(z0,walker,steps)
%===================================================================

l = walker.l;

flag = 1;
if nargin<2
    error('need more inputs to onestep');
elseif nargin<3
    flag = 0; %send only last state, for root finder and jacobian
    steps = 1;
end

theta1 = z0(1);
xh = 0;
yh = l*cos(theta1);
xh_start = xh;

t0 = 0; 
dt = 4; %might need to be changed based on estimate of time taken for one step
time_stamps = 100;
t_ode = t0;
z_ode = [z0 xh yh];

for i=1:steps
    options=odeset('abstol',1e-13,'reltol',1e-13,'events',@collision);
    tspan = linspace(t0,t0+dt,time_stamps);
    [t_temp, z_temp] = ode113(@single_stance,tspan,z0,options,walker);

    zplus=footstrike(t_temp(end),z_temp(end,:),walker);    
    
    z0 = zplus;
    t0 = t_temp(end);
    
    xh_temp = xh_start + l*sin(z_temp(1,1))-l*sin(z_temp(:,1)); 
    yh_temp =  l*cos(z_temp(:,1));
    
    t_ode = [t_ode; t_temp(2:end)];
    z_ode = [z_ode; [z_temp(2:(end-1),:); zplus] xh_temp(2:end) yh_temp(2:end)];
    xh_start = xh_temp(end);
end

z = zplus(1:4);

if flag==1
   z=z_ode;
   t=t_ode;
end

%===================================================================
function zdot=single_stance(t,z,walker)  
%===================================================================
theta1 = z(1);   omega1 = z(2);                         
theta2 = z(3);   omega2 = z(4);                         
                    
M = walker.M;  m = walker.m; I = walker.I;   
l = walker.l;  c = walker.c; 
g = walker.g; gam = walker.gam;

%%%%%%%%% copy pasted from passivewalker_derive.m %%%%%%
A11 = 2*I + M*l^2 + 2*c^2*m + 2*l^2*m - 2*c*l*m - 2*c*l*m*cos(theta2);
A12 = I + c^2*m - c*l*m*cos(theta2);
A21 = I + c^2*m - c*l*m*cos(theta2);
A22 = I + c^2*m;
A_ss = [A11 A12; A21 A22];
 
b1 = c*g*m*sin(gam - theta1) - M*g*l*sin(gam - theta1) - c*g*m*sin(theta1 - gam + theta2) - 2*g*l*m*sin(gam - theta1) - c*l*m*omega2^2*sin(theta2) - 2*c*l*m*omega1*omega2*sin(theta2);
b2 = -c*m*(g*sin(theta1 - gam + theta2) - l*omega1^2*sin(theta2));
b_ss = [b1; b2];
 
alpha = A_ss\b_ss;

%%%%%%%%%%% ends %%%%%%%%%%%%%
 
zdot = [omega1 alpha(1) omega2 alpha(2)]';  

%===================================================================
function [gstop, isterminal,direction]=collision(t,z,walker)
%===================================================================

theta1 = z(1); theta2 = z(3); 

gstop = theta2 + 2*theta1;
if (theta1>-0.05) %allow legs to pass through for small hip angles (taken care in real walker using stepping stones)
    isterminal = 0;
else
    isterminal=1; %ode should terminate is conveyed by 1, if you put 0 it goes till the final time u specify
end
direction=[]; % The t_final can be approached by any direction is indicated by the direction

%===================================================================
function zplus=footstrike(t,z,walker)      
%===================================================================

theta1_n = z(1);   omega1_n = z(2);                         
theta2_n = z(3);   omega2_n = z(4);                         
                      
theta1 = theta1_n + theta2_n;                         
theta2 = -theta2_n;                                       

M = walker.M;  m = walker.m; I = walker.I;   
l = walker.l;  c = walker.c;  

%%%%%%%%% copy pasted from passivewalker_derive.m %%%%%%
J11 = 1;
J12 = 0;
J13 = l*(cos(theta1_n + theta2_n) - cos(theta1_n));
J14 = l*cos(theta1_n + theta2_n);
J21 = 0;
J22 = 1;
J23 = l*(sin(theta1_n + theta2_n) - sin(theta1_n));
J24 = l*sin(theta1_n + theta2_n);
J = [J11 J12 J13 J14; J21 J22 J23 J24];
 
A11 = M + 2*m;
A12 = 0;
A13 = (m*(2*c*cos(theta1_n + theta2_n) - 2*l*cos(theta1_n)))/2 + m*cos(theta1_n)*(c - l) - M*l*cos(theta1_n);
A14 = c*m*cos(theta1_n + theta2_n);
A21 = 0;
A22 = M + 2*m;
A23 = (m*(2*c*sin(theta1_n + theta2_n) - 2*l*sin(theta1_n)))/2 - M*l*sin(theta1_n) + m*sin(theta1_n)*(c - l);
A24 = c*m*sin(theta1_n + theta2_n);
A31 = (m*(2*c*cos(theta1_n + theta2_n) - 2*l*cos(theta1_n)))/2 + m*cos(theta1_n)*(c - l) - M*l*cos(theta1_n);
A32 = (m*(2*c*sin(theta1_n + theta2_n) - 2*l*sin(theta1_n)))/2 - M*l*sin(theta1_n) + m*sin(theta1_n)*(c - l);
A33 = 2*I + M*l^2 + 2*c^2*m + 2*l^2*m - 2*c*l*m - 2*c*l*m*cos(theta2_n);
A34 = I + c^2*m - c*l*m*cos(theta2_n);
A41 = c*m*cos(theta1_n + theta2_n);
A42 = c*m*sin(theta1_n + theta2_n);
A43 = I + c^2*m - c*l*m*cos(theta2_n);
A44 = I + c^2*m;
A_n_hs = [A11 A12 A13 A14; A21 A22 A23 A24; A31 A32 A33 A34; A41 A42 A43 A44];
 
X_n_hs = [0 0 omega1_n omega2_n]';
b_hs = [A_n_hs*X_n_hs; 0; 0];
A_hs = [A_n_hs -J' ; J zeros(2,2)];
X_hs = A_hs\b_hs;
omega(1) = X_hs(3)+X_hs(4); omega(2) = -X_hs(4);
 

%%%%%%%%%%%%% ends %%%%%%%%%%%%%

zplus = [theta1 omega(1) theta2 omega(2)];                     


%===================================================================
function animate(t_all,z_all,walker,steps,fps)
%===================================================================

%%%% Interpolate linearly using fps %%%%%
z_all_plot = [z_all(:,1) z_all(:,3) z_all(:,5) z_all(:,6)];
nn = size(z_all_plot,2);
total_frames = round(t_all(end)*fps);
t = linspace(0,t_all(end),total_frames);
z = zeros(total_frames,nn);
for i=1:nn
    z(:,i) = interp1(t_all,z_all_plot(:,i),t);
end

%%%%% Now animate the results %%%%%%%  
l = walker.l;    
c = walker.c;

mm = size(z,1);

min_xh = min(z(:,3)); max_xh = max(z(:,3)); 
dist_travelled = max_xh - min_xh;
camera_rate = dist_travelled/mm;

window_xmin = -1*l; window_xmax = 1*l;
window_ymin = -0.1; window_ymax = 1.1*l;

axis('equal')
axis([window_xmin window_xmax window_ymin window_ymax])
axis off
set(gcf,'Color',[1,1,1])

%%%% create ramp %%%%
rampref=[min_xh-1 max_xh+l ; 0 0];

%%%% Draw ramp %%%%%%%%%%
line('xdata',rampref(1,:),'ydata',rampref(2,:),'linewidth', 1,'color','black'); hold on;
 
for i=1:mm
   %moving window %%%%%%%
   window_xmin = window_xmin + camera_rate;
   window_xmax = window_xmax + camera_rate;
   axis('equal')
   axis([window_xmin window_xmax window_ymin window_ymax])

   %%% get angles and hip position 
   theta1 = z(i,1); theta2 = z(i,2); 
   xh = z(i,3); yh = z(i,4);
   
   %%% coordinates of points of interest %
   hinge=[xh; yh];  
   stance_foot = [xh+l*sin(theta1);         yh-l*cos(theta1)];
   stance_leg_com = [xh+c*sin(theta1);         yh-c*cos(theta1)];
   swing_foot =  [xh+l*sin(theta1 + theta2),yh-l*cos(theta1 + theta2)];
   swing_leg_com =  [xh+c*sin(theta1 + theta2),yh-c*cos(theta1 + theta2)];
   
   %animate 
   h0 = plot(hinge(1),hinge(2),'ko','MarkerFaceColor','k','Markersize',15);
   h1 = plot(stance_leg_com(1),stance_leg_com(2),'ko','MarkerFaceColor','k','Markersize',10);
   h2 = plot(swing_leg_com(1),swing_leg_com(2),'ko','MarkerFaceColor','k','Markersize',10);
   h3 = line([hinge(1) stance_foot(1)],[hinge(2) stance_foot(2)],'Color','red','Linewidth',2);
   h4 = line([hinge(1) swing_foot(1)], [hinge(2) swing_foot(2)],'Color','red','Linewidth',2);
   
   %delay to create animation
   pause(0.01);
   
   if (i~=mm)     %delete all but not the last entry
       delete(h0);
       delete(h1);
       delete(h2);
       delete(h3);
       delete(h4);
   end
   
end


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_46536094

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值