Appendices
Appendix A: MATLAB Scripts
Note, all scripts are included as text below and as an .m file attachment
A1 - Main Script
Download here → analysis7.m
%This script performs calculations for a Jansen walking mechanism
%If you run this script as-is, it will save 360 images and a video to your
%default MATLAB folder. If you want to run the script without saving those
%images remove lines 168, 239-256, 226-230.
close all
clear
clc
%%
%%Known Values
global A B C D E F G H I J K M %These global values get used in mechanismState.m
ao=38;
lo=7.8;
B=41.5;
C=39.3;
D=40.1;
E=55.8;
F=39.4;
G=36.7;
H=65.7;
I=59;
J=50;
K=61.9;
M=15;
%create a new diagonal link A from orthogonal links ao and lo
A=(ao^2+lo^2)^0.5;
ta=atan(lo/ao);
rotLength=360; %Max rotation of Link M for this sim
%%
%%Solve the two fourbars
L1=A;
L2=M;
for i=1:rotLength
thetaM(i)=i;
%solve first fourbar
theta2=180+thetaM(i)-rad2deg(ta); %rotate sub-mechanism so that it fits the fourbarpos.m parameters
L3=J;
L4=B;
t2=deg2rad(theta2);
[theta]=fourbarpos(L2,L3,L4,L1,0,t2,-1);
%rotate mechanism back and convert back to degrees
thetaJt(i)=rad2deg(theta(3)-pi+ta);
thetaBt(i)=rad2deg(theta(4)-pi+ta);
%solve second fourbar
theta2=thetaM(i)-rad2deg(ta)-180; %rotate sub-mechanism so that it fits the fourbarpos.m parameters
t2=deg2rad(theta2);
L3=K;
L4=C;
[theta]=fourbarpos(L2,L3,L4,L1,0,t2,1);
%rotate mechanism back and convert back to degrees
thetaKt(i)=rad2deg(pi+ta+theta(3));
thetaCt(i)=rad2deg(pi+ta+theta(4));
end
%set all angles to be between 0 and 360
[thetaB] = Range360Deg(thetaBt);
[thetaJ] = Range360Deg(thetaJt);
[thetaK] = Range360Deg(thetaKt);
[thetaC] = Range360Deg(thetaCt);
%%
%%Solve other links
%Define interior triangle angles for the two couplers
%BDE
ThetaTriD1=acosd((E^2+B^2-D^2)/(2*E*B));
ThetaTriB=asind(B/D*sind(ThetaTriD1));
ThetaTriE=asind(E/D*sind(ThetaTriD1));
%HIG
ThetaTriG=acosd((H^2+I^2-G^2)/(2*H*I));
ThetaTriH=asind(H/G*sind(ThetaTriG));
ThetaTriI=asind(I/G*sind(ThetaTriG));
for i=1:rotLength
%Solve Using Geometry of Triangle BDE
thetaD(i)=thetaB(i)+ThetaTriE;
thetaE(i)=thetaD(i)+ThetaTriB;
%Solve Using quadrilateral DCFG with long diagonal S
Dx=D*cosd(thetaD(i));
Dy=D*sind(thetaD(i));
Cx=C*cosd(thetaC(i));
Cy=C*sind(thetaC(i));
%Find values of "ghost link" S which connects point CIKG to DEF
Sx=Dx-Cx;
Sy=Dy-Cy;
temp=atand(Sy/Sx);
if temp<0 %theta S will be in Q1 or Q2, not Q4
thetaS=temp+180;
else
thetaS=temp;
end
S=(Sx^2+Sy^2)^0.5;
ThetaTriF=acosd((G^2+S^2-F^2)/(2*G*S));%Angle of triangle FGS that is opposite F
ThetaTriS2=asind(S/F*sind(ThetaTriF)); %Angle of triangle FGS that is opposite S
thetaG(i)=thetaS+ThetaTriF;
thetaF(i)=thetaG(i)-ThetaTriS2;
%Using Triangle HIG
thetaI(i)=thetaG(i)+ThetaTriH;
thetaH(i)=180+thetaG(i)-ThetaTriI;
end
%%
%%Create Plots
%Plot Angles vs ThetaM
figure
hold on
plot (thetaM,thetaB,'c-')
plot (thetaM,thetaC,'r-')
plot (thetaM,thetaD,'m--')
plot (thetaM,thetaE,'k--')
plot (thetaM,thetaF,'g--')
plot (thetaM,thetaG,'b--')
plot (thetaM,thetaH,'c-.')
plot (thetaM,thetaI,'m-.')
plot (thetaM,thetaJ,'b-')
plot (thetaM,thetaK,'y-')
xlabel('Link M Angle [deg]')
ylabel('Output Angles [deg]')
title('Mechanism Angles vs Input Angle (all measured from horizontal)')
legend('thetaB','thetaC','thetaD','thetaE','thetaF','thetaG','thetaH','thetaI','thetaJ','thetaK')
%Create Animation of Jansen Visualization
figure
figure
hold off
fig2=figure(2);
xlabel('x')
ylabel('y')
title('Jansen Mechanism Visualization')
axis([-80 80 -100 60])
hold on;
%acquire XY coordinates of all the points
[xMJK,yMJK,xBDC,yBDC,xBEJ,yBEJ,xDEF,yDEF,xCIKG,yCIKG,xM,yM,xFGH,yFGH,xHI,yHI] = ...
mechanismState(rad2deg(ta),thetaB(1),thetaC(1),thetaD(1),thetaE(1),thetaF(1),thetaG(1),thetaH(1),thetaI(1),thetaJ(1),thetaK(1),thetaM(1));
%Plot all the points
plotBDC=plot(xBDC,yBDC,'rx');
plotMm=plot(xM,yM,'bx');
plotMJK=plot(xMJK,yMJK,'o');
plotBEJ=plot(xBEJ,yBEJ,'o');
plotDEF=plot(xDEF,yDEF,'o');
plotCIKG=plot(xCIKG,yCIKG,'o');
plotFGH=plot(xFGH,yFGH,'o');
plotHI=plot(xHI,yHI,'o');
%Plot all the links
plotB=plot([xBDC xBEJ],[yBDC yBEJ],'-') ;%B
plotD=plot([xBDC xDEF],[yBDC yDEF],'-');%D
plotM=plot([xM xMJK],[yM yMJK],'-');%M
plotJ=plot([xMJK xBEJ],[yMJK yBEJ],'-');%J
plotE=plot([xDEF xBEJ],[yDEF yBEJ],'-') ;%E
plotC=plot([xBDC xCIKG],[yBDC yCIKG]);%C
plotK=plot([xMJK xCIKG],[yMJK yCIKG]);%K
plotF=plot([xDEF xFGH],[yDEF yFGH]);%F
plotG=plot([xCIKG xFGH],[yCIKG yFGH]);%G
plotH=plot([xFGH xHI],[yFGH yHI]);%H
plotI=plot([xHI xCIKG],[yHI yCIKG]);%I
hold off
images=cell(rotLength,1); %initialize matrix of images for video
for i=1:rotLength %repeat the previous plot for all values of ThetaM
[xMJK,yMJK,xBDC,yBDC,xBEJ,yBEJ,xDEF,yDEF,xCIKG,yCIKG,xM,yM,xFGH,yFGH,xHI,yHI] = ...
mechanismState(rad2deg(ta),thetaB(i),thetaC(i),thetaD(i),thetaE(i),thetaF(i),thetaG(i),thetaH(i),thetaI(i),thetaJ(i),thetaK(i),thetaM(i));
plotBDC=plot(xBDC,yBDC,'rx');
hold on
axis([-80 80 -100 60])
xlabel('X')
ylabel('Y')
title('Jansen Mechanism Visualization')
plotMm=plot(xM,yM,'bx');
plotMJK=plot(xMJK,yMJK,'o');
plotBEJ=plot(xBEJ,yBEJ,'o');
plotDEF=plot(xDEF,yDEF,'o');
plotCIKG=plot(xCIKG,yCIKG,'o');
plotFGH=plot(xFGH,yFGH,'o');
plotHI=plot(xHI,yHI,'o');
%Plot links and also calculate length of each link (for double checking
%work later)
plotB=plot([xBDC xBEJ],[yBDC yBEJ],'-'); %B
Bdist(i)=((xBDC-xBEJ)^2+(yBDC-yBEJ)^2)^0.5;
plotD=plot([xBDC xDEF],[yBDC yDEF],'-');%D
Ddist(i)=((xBDC-xDEF)^2+(yBDC-yDEF)^2)^0.5;
plotM=plot([xM xMJK],[yM yMJK],'-');%M
Mdist(i)=((xM-xMJK)^2+(yM-yMJK)^2)^0.5;
plotJ=plot([xMJK xBEJ],[yMJK yBEJ],'-');%J
Jdist(i)=((xMJK-xBEJ)^2+(yMJK-yBEJ)^2)^0.5;
plotE=plot([xDEF xBEJ],[yDEF yBEJ],'-'); %E
Edist(i)=((xDEF-xBEJ)^2+(yDEF-yBEJ)^2)^0.5;
plotC=plot([xBDC xCIKG],[yBDC yCIKG]);%C
Cdist(i)=((xBDC-xCIKG)^2+(yBDC-yCIKG)^2)^0.5;
plotK=plot([xMJK xCIKG],[yMJK yCIKG]);%K
Kdist(i)=((xMJK-xCIKG)^2+(yMJK-yCIKG)^2)^0.5;
plotF=plot([xDEF xFGH],[yDEF yFGH]);%F
Fdist(i)=((xDEF-xFGH)^2+(yDEF-yFGH)^2)^0.5;
plotG=plot([xCIKG xFGH],[yCIKG yFGH]);%G
Gdist(i)=((xCIKG-xFGH)^2+(yCIKG-yFGH)^2)^0.5;
plotH=plot([xFGH xHI],[yFGH yHI]);%H
Hdist(i)=((xFGH-xHI)^2+(yFGH-yHI)^2)^0.5;
plotI=plot([xHI xCIKG],[yHI yCIKG]);%I
Idist(i)=((xHI-xCIKG)^2+(yHI-yCIKG)^2)^0.5;
%create a vector of foot positions for the Trajectory plot
Xfoot(i)=xHI;
Yfoot(i)=yHI;
%save image for video
GraphFileName=join(['JansenPic',num2str(i)]);
GraphNamePNG=join([GraphFileName,'.png']);
saveas(gcf, GraphFileName, 'png') %save current plot
images{i}=imread(GraphNamePNG);%add current plot to image matrix
%If you want the animation to run smoothly/quickly in this code,
%remove the parts that update the video and set the pause value to be >0.07
%(see line 5)
pause(.08)
hold off
end
%Create video of all the saved images
% create the video writer with 1 fps
writerObj = VideoWriter('myVideo.avi');
writerObj.FrameRate = 1;
% set the seconds per image
secsPerImage(1:rotLength)=1;
% open the video writer
open(writerObj);
% write the frames to the video
for u=1:length(images)
% convert the image to a frame
frame = im2frame(images{u});
for v=1:secsPerImage(u)
writeVideo(writerObj, frame);
end
end
% close the writer object
close(writerObj);
%Plot Foot Trajectory
figure
plot(Xfoot,Yfoot)
xlabel('X Position')
ylabel('Y Position')
title('Trajectory of Foot Joint')
axis([-55 25 -110 -50])
axis square
%%
%%Double Check work by ensuring that links do not change lengths
errB=max(abs(Bdist-B));
errC=max(abs(Cdist-C));
errD=max(abs(Ddist-D));
errE=max(abs(Edist-E));
errF=max(abs(Fdist-F));
errG=max(abs(Gdist-G));
errH=max(abs(Hdist-H));
errI=max(abs(Idist-I));
errJ=max(abs(Jdist-J));
errK=max(abs(Kdist-K));
MaxError=max([errB,errC,errD,errE,errF,errG,errH,errI,errJ,errK]);
if MaxError>0.0001
disp('error, a link is changing length during animation')
disp(MaxError)
else
disp('Simulation successful')
end
A2 - mechanismState.m
Download here → mechanismState.m
function [xMJK,yMJK,xBDC,yBDC,xBEJ,yBEJ,xDEF,yDEF,xCIKG,yCIKG,xM,yM,xFGH,yFGH,xHI,yHI] = mechanismState(thetaA,thetaB,thetaC,thetaD,thetaE,thetaF,thetaG,thetaH,thetaI,thetaJ,thetaK,thetaM)
%DRAWS OUT THE POINTS FOR THE JANSEN MECHANISM GIVEN THE VECTOR OF ANGLES
%ASSUME ORIGIN POINT AT JOINT BDC
global A B C D E F G H I J K M
%Calculate Cartesian Distances
Ax=A*cosd(thetaA);
Ay=A*sind(thetaA);
Bx=B*cosd(thetaB);
By=B*sind(thetaB);
Cx=C*cosd(thetaC);
Cy=C*sind(thetaC);
Dx=D*cosd(thetaD);
Dy=D*sind(thetaD);
%Ex=E*cosd(thetaE);
%Ey=E*sind(thetaE);
%Fx=F*cosd(thetaF);
%Fy=F*sind(thetaF);
Gx=G*cosd(thetaG);
Gy=G*sind(thetaG);
%Hx=H*cosd(thetaH);
%Hy=H*sind(thetaH);
Ix=I*cosd(thetaI);
Iy=I*sind(thetaI);
%Jx=J*cosd(thetaJ);
%Jy=J*sind(thetaJ);
%Kx=K*cosd(thetaK);
%Ky=K*sind(thetaK);
Mx=M*cosd(thetaM);
My=M*sind(thetaM);
%Calculate Point Locations
xMJK=Ax+Mx;
yMJK=Ay+My;
xBDC=0;
yBDC=0;
xBEJ=Bx;
yBEJ=By;
xDEF=Dx;
yDEF=Dy;
xCIKG=Cx;
yCIKG=Cy;
xM=Ax;
yM=Ay;
xFGH=xCIKG+Gx;
yFGH=yCIKG+Gy;
xHI=xCIKG+Ix;
yHI=yCIKG+Iy;
end
A3 - Range360Deg.m
Download here →Range360Deg.m
function [thetanew] = Range360Deg(theta)
%takes a vector of angles in degrees "theta" and converts all angles into
%the range between 0<theta<360
thetanew(1:length(theta))=0;
for i=1:length(theta)
key=true;
thetanew(i)=theta(i);
k=0;
while key==true
k=k+1;
if thetanew(i)>=0 && thetanew(i)<=360
key=false;
elseif thetanew(i)<0
a=ceil(abs(thetanew(i)/360));
thetanew(i)=thetanew(i)+a*360;
elseif thetanew(i)>360
a=floor(abs(thetanew(i)/360));
thetanew(i)=thetanew(i)-a*360;
end
if k>6
disp('error, Range360Deg is not fixing the angle')
disp(i)
end
end
end
end
A4 - fourbarpos.m
Download here ->fourbarpos.m
function [theta]=fourbarpos(a,b,c,d,theta1,theta2,delta)
%%%%%%%%%%
% This code is downloaded from the RMD Canvas page.
% Originally written by Bonnie Chan 2020
type='fourbar';
if d==0
type='crank-slider';
end
switch type
case 'fourbar'
%vector loop equation for a fourbar linkage
k1=d/a;
k2=d/c;
k3=(a^2-b^2+c^2+d^2)/(2*a*c);
k4=d/b;
k5=(c^2-d^2-a^2-b^2)/(2*a*b);
A=cos(theta2)-k1-k2*cos(theta2)+k3;
B=-2*sin(theta2);
C=k1-(k2+1)*cos(theta2)+k3;
D=cos(theta2)-k1+k4*cos(theta2)+k5;
E=-2*sin(theta2);
F=k1+(k4-1)*cos(theta2)+k5;
if delta==1
theta4=2*atan((-B-sqrt(B^2-4*A*C))/(2*A));
theta3=2*atan((-E-sqrt(E^2-4*D*F))/(2*D));
elseif delta==-1
theta4=2*atan((-B+sqrt(B^2-4*A*C))/(2*A));
theta3=2*atan((-E+sqrt(E^2-4*D*F))/(2*D));
end
theta=[theta1,theta2,theta3,theta4];
case 'crank-slider'
%vector loop equation for a fourbar crank-slider linkage
theta4=0;
if delta==1
theta3=asin((a*sin(theta2)-c)/b);
d=a*cos(theta2)-b*cos(theta3);
elseif delta==-1
theta3=asin(-(a*sin(theta2)-c)/b)+pi;
d=a*cos(theta2)-b*cos(theta3);
end
theta=[theta1 theta2 theta3 theta4];
end
Appendix B: Additional Prototype Pictures
These pictures are supplemental to the pictures included in Section 3.
Welcome to the University Wiki Service! Please use your IID (yourEID@eid.utexas.edu) when prompted for your email address during login or click here to enter your EID. If you are experiencing any issues loading content on pages, please try these steps to clear your browser cache.