ConicLogSpiral
Problem Statement
I like antennas. I also like soviet spacecraft. In the photo of Lunakhod-1 there is a strange looking white antenna on the left side of the rover, with a black spiral. I wanted to know what this antenna was, why it was used, and maybe how hard it would be to make.
Extensive googling turned up the antenna design, a directional, extremely broadband, circularly polarized, traveling wave antenna referred to as the Conical Log Spiral Antenna. This antenna is commonly used as a feed on radio telescopes due to the extreme bandwidth and configurable directionality. This sounds amazing. I want to make one.
Biggest Problem: Though I can find many analyses of the performance of the antenna, I cannot find any calculators, generators, or other design tools. This is a tricky geometry to create, and I want to fabricate in 2D, then fold into 3D. I decided the best way to go about this was to design such a tool myself. The matlab code is listed below, though I would like to create a php version as an online realtime calculator with pdf results downloadable.
Maths
%flattened cone clear all; baseRadius=2; %tipRadius = 0.1591; %starting radius, determined by the starting radius tipRadius = baseRadius/10; %starting radius, determined by the starting radius %Pick one code block %Height=10; %AspectRatio=Height/baseRadius; %HalfAngle = pi/2-atan(AspectRatio); %or pick the other code block HalfAngle = degtorad(10); AspectRatio = tan(HalfAngle); Height = baseRadius/AspectRatio; tipHeight = tipRadius/AspectRatio; stripWidth = pi/2; %this is sometime called signal, and is an ANGLE in RADIANS pitchAngleDesired = 60; sideLength = sqrt(Height^2+baseRadius^2); %or Height/cos(HalfAngle)! tipSideLength = sqrt(tipHeight^2+tipRadius^2); %or Height/cos(HalfAngle)! CircumpherenceBottom = 2*pi*baseRadius; CircumpherenceFlat = 2*pi*sideLength; GapAngle = (CircumpherenceFlat - CircumpherenceBottom)/sideLength; radtodeg(GapAngle) %% Polar coordinates, 2D cone %rho = a*e^(b*theta) %x=r*cos(theta); %y=r*sin(theta); pitchAngle=atand(tand(pitchAngleDesired)*(sideLength/baseRadius));%Correction factor for the pitch angle due to conal distortion ((sideLength/baseRadius) is the scale factor) a=tipRadius; b=tand(90-pitchAngle); minRadians = log(tipRadius/a)/b; maxRadians = log(baseRadius/a)/b; theta = minRadians:pi/100:maxRadians; windingAngle = radtodeg(maxRadians-minRadians); %not sure what use this is rho = a.*exp(b.*theta); %polar(rho,theta); %first leg, with a width x1a=rho.*cos(theta); y1a=rho.*sin(theta); x1b=rho.*cos(theta+stripWidth); y1b=rho.*sin(theta+stripWidth); %Second leg, with a width x2a=rho.*cos(theta+pi); y2a=rho.*sin(theta+pi); x2b=rho.*cos(theta+stripWidth+pi); y2b=rho.*sin(theta+stripWidth+pi); plot([0 0],[-tipRadius -baseRadius],x1a,y1a,'bl',x1b,y1b,'bl',x2a,y2a,'r',x2b,y2b,'r',tipRadius*cos(0:0.01:2*pi),tipRadius*sin(0:0.01:2*pi),baseRadius*cos(0:0.01:2*pi),baseRadius*sin(0:0.01:2*pi)); grid on; %max_value = max(abs([x1a y1a ])); axis([-baseRadius baseRadius -baseRadius baseRadius]); pbaspect([1 1 1]); %% 3D spiral %rho = a*e^(b*theta) %x=r*cos(theta); %y=r*sin(theta); pitchAngle=atand(tand(pitchAngleDesired)*(sideLength/baseRadius));%Correction factor for the pitch angle due to conal distortion ((sideLength/baseRadius) is the scale factor) %pitchAngle = 60*atand(tand(45)*sideLength); a=tipRadius; b=tand(90-pitchAngle); minRadians = log(tipRadius/a)/b; maxRadians = log(baseRadius/a)/b; %this doesn't quite give us max radius? theta = minRadians:pi/200:maxRadians; windingAngle = radtodeg(maxRadians-minRadians); %not sure what use this is rho = a.*exp(b.*theta); %rho now stands for distance down ALONG cone surface, not outward z = Height-(Height/baseRadius)*(rho);% x1a=rho.*cos(theta); y1a=rho.*sin(theta); x1b=rho.*cos(theta+stripWidth); y1b=rho.*sin(theta+stripWidth); %Second leg, with a width x2a=rho.*cos(theta+pi); y2a=rho.*sin(theta++pi); x2b=rho.*cos(theta+stripWidth+pi); y2b=rho.*sin(theta+stripWidth+pi); %z=Height-z; plot3([0 0],[0 -baseRadius],[Height 0],x1a,y1a,z,'bl',x1b,y1b,z,'bl',x2a,y2a,z,'r',x2b,y2b,z,'r',tipRadius*cos(0:0.01:2*pi),tipRadius*sin(0:0.01:2*pi),Height-tipHeight * ones(numel(0:0.01:2*pi),1),baseRadius*cos(0:0.01:2*pi),baseRadius*sin(0:0.01:2*pi),zeros(numel(0:0.01:2*pi),1)); view(90,0); %view(90,radtodeg(HalfAngle)); grid on; max_value = max(abs([tipRadius baseRadius Height z])); axis([-max_value max_value -max_value max_value -max_value*1.5 max_value*1.5]); pbaspect([1 1 1]); %% Convert to flat disc numPtsPerRev = numel(find(theta<2*pi)); radiansPerPtOut = (2*pi-GapAngle)/numPtsPerRev; clear idxList1a idxList1b idxList2a idxList2b; thetaCount1a = 0; thetaCount1b = stripWidth / (2*pi/(2*pi-GapAngle))-radiansPerPtOut; thetaCount2a = pi / (2*pi/(2*pi-GapAngle))-radiansPerPtOut; thetaCount2b = (stripWidth+pi) / (2*pi/(2*pi-GapAngle))-radiansPerPtOut; for i=1:numel(theta) %z = Height-(Height/baseRadius)*(rho(i));% rhoOut(i) = rho(i)/sin(HalfAngle); thetaCount1a = thetaCount1a+radiansPerPtOut; thetaCount1b = thetaCount1b+radiansPerPtOut; thetaCount2a = thetaCount2a+radiansPerPtOut; thetaCount2b = thetaCount2b+radiansPerPtOut; wrapTheta=mod(theta(i),2*pi); if wrapTheta == 0 %this controls the reset point if exist('idxList1a','var') idxList1a(end+1)=i; else idxList1a=i; end thetaCount1a = 0; end wrapTheta=mod(theta(i)+stripWidth,2*pi); if wrapTheta == 0 %this controls the reset point if exist('idxList1b','var') idxList1b(end+1)=i; else idxList1b=i; end thetaCount1b = 0; end wrapTheta=mod(theta(i)+pi,2*pi); if wrapTheta == 0 %this controls the reset point if exist('idxList2a','var') idxList2a(end+1)=i; else idxList2a=i; end thetaCount2a = 0; end wrapTheta=mod(theta(i)+pi+stripWidth,2*pi); if wrapTheta == 0 %this controls the reset point if exist('idxList2b','var') idxList2b(end+1)=i; else idxList2b=i; end thetaCount2b = 0; end thetaOut1a(i) = thetaCount1a; thetaOut1b(i) = thetaCount1b; thetaOut2a(i) = thetaCount2a; thetaOut2b(i) = thetaCount2b; %rhoOut(i) = (Height-z(i))+0.0175; end xf1a=rhoOut.*cos(thetaOut1a); yf1a=rhoOut.*sin(thetaOut1a); xf1b=rhoOut.*cos(thetaOut1b); yf1b=rhoOut.*sin(thetaOut1b); xf2a=rhoOut.*cos(thetaOut2a); yf2a=rhoOut.*sin(thetaOut2a); xf2b=rhoOut.*cos(thetaOut2b); yf2b=rhoOut.*sin(thetaOut2b); %insert nans to keep matlab from connecting points [xf1a,yf1a] = insertValues(xf1a,yf1a,idxList1a); [xf1b,yf1b] = insertValues(xf1b,yf1b,idxList1b); [xf2a,yf2a] = insertValues(xf2a,yf2a,idxList2a); [xf2b,yf2b] = insertValues(xf2b,yf2b,idxList2b); plot([tipSideLength sideLength],[0 0],[tipSideLength*cos(2*pi-GapAngle) sideLength*cos(2*pi-GapAngle)],[tipSideLength*sin(2*pi-GapAngle) sideLength*sin(2*pi-GapAngle)],tipSideLength*cos(0:0.01:2*pi-GapAngle),tipSideLength*sin(0:0.01:2*pi-GapAngle),sideLength*cos(0:0.01:2*pi-GapAngle),sideLength*sin(0:0.01:2*pi-GapAngle),xf1a,yf1a,'bl',xf1b,yf1b,'bl',xf2a,yf2a,'r',xf2b,yf2b,'r'); axis([-sideLength sideLength -sideLength sideLength]); pbaspect([1 1 1]);
This script depends on a single function, insertValues, which inserts NaN numbers into an array, at the locations specified in a second array.
function [outputArrayX, outputArrayY]=insertValues(inputArrayX,inputArrayY,idxList) idx2 = 1; for i=1:numel(inputArrayX) outputArrayX(idx2) = inputArrayX(i); outputArrayY(idx2) = inputArrayY(i); if max(i == idxList-1) idx2 = idx2+1; outputArrayX(idx2) = NaN; outputArrayY(idx2) = NaN; end idx2 = idx2+1; end end