Computing the cable tensions from the sag surveys.
oct 2020
Intro:
general steps to compute tension
Details of how it was done
Where the code is located
Intro
Each telescope cable hangs between two
connection points in a catenary curve. The sag of
the cable comes from the cable weight and gravity.
As the tension in the cable increases, the sag gets smaller.
By fitting a catenary to the cable curve we can compute the tension
in the cable.
The general steps to compute
the tension from the sag surveys
 collect the p50 data
 exclude extraneous points (so you can manipulate the data).
 for the aug2020 surveys there were 14 to 255 million
3d points per data set. To exclude points:
 window in the xy, xz, or yz plane. This projection is easy
since you just ignore the other 3d coordinate.
 select 2 points from a cable or set of cables and
use it to generate a line (in 2d or 3d space)
 Compute the perpendicular distance from each point to this
line (dot product and then Pythagorean theorem).
 Use this distance to exclude points
 These things can typically reduce the points from
10's of million to a few 100 thousand.
 move 3d to 2d
 project the 3d points onto the xy place
 select 2 points on the cables to generate a line
 Use the fit coef to rotate the xy line to the x axis. This
leaves you with data points clustered around the x,z plane.
 select points for each cable
 after rotating the 3d points to the xz plane, plot the 3d
data in the y,z plane
 This will separate the cables by their y distance.
 select 2 points on each cable, define a line, and compute
the distance from all points to each line
 let the user iterate on the clipping distance.
 These points will be the starting point for fits to each
cable.
 fit a catenary to the set of points for each cable.
 In the xz plane first fit a parabola to each cable set:
 zp=p0 + p1*x + p2*x^2
 Use the parabola coefs to compute the starting values for
the catenary fit:
 zc= a + b*(cosh(xc)/b 1)
 Use a Leven marquardt non linear least squares fit
to fit for the catenary coef a,b,c
 compute the tension from the catenary parameters and the
cable slope.
 cableTension=b * cableWeight/linearDistance *
cos(cableZAngle)
 The cableZ angle was initially taken from the linear
coef of the xz parabolic fit.
 this gave xz cable angles that differed by up to a degree
for the same set of main cables (pointed out by pierre
ghisbain)
 i switched over to using the catenary fit and the actual
cable length.
 For xmax use the x value for the maxium z value (this is
at the tower)
 compute xmin=xmax cable length (taking this from the
drawings.
 This works since the platform side of the cable was
usually the one blocked by the platform or other
cables.
 Evaluate the catenary fit at xmax,xmin, get the
slope and then the xz angle of the cable.
 projecting tensions to balance forces on platform and
measure imbalances on the towers.
 The catenary fits is used to compute the xz vertical angle
 The linear fits in the x,y plane give the rotation angle to
move the cables to the x,z plane
 The angles are biased by the y axis of the p50 scanner
 the difference in the angles tells the relative angle
between the main and aux main cables.
Details of how the tension was computed
Collecting the data
The leica p50 laser scanner is used to
collect the data. It scans an area that includes the cables. We
typically collect between 5 and 90 million points for each set of
cables scanned.
After the collecting the data some leica software is get the 3d
points into a .las file that can be read by the
processing programs. These leica programs run on windows.
 leica xxx will move the project from the p50 to the windows
computer
 cyclone can then be used to input the data files, plot the
data, and then output the data as .las files.
 the .las files are then moved to Linux computers.
Idl software.
Idl routines have been written to input the
.las files and compute the tensions. The major processing steps
are:
 Exclude points far from cables
 this can remove a large number of points
 select points that belong to each cable
 since the cables should hang vertically we can rotate the
points to lie close to the xz plane
 Points are excluded by defining lines (via 2 points) and
then computing the distance from all points for each line
 The final exclusion is by fitting a parabola to each set of
cable points.
 fit a catenary to the points.
Inputting the data
 getxyzpnts() will input the data
 plcdinplas() will input the .las file
 an xyz[3,n] is then generated by scaling the .las
input data to floating point
Localizing the cables:
Most of this code is trying to exclude points
that don't belong to the cable. findcables() tries to select
points around the cables and reducing the # of points to a
manageable number (typically going from 64e6 to around 2e5 points.
preproccable() then does a more in depth attempt at selecting the
points for each cable.
 findcables(xyz, p3, p3cbIar) will exclude most points
that don't belong to a cable
 input xyz[3,n)
 output: p3[3,m] and p3cblIAr[ncables]
 plot all points in the x,z plane. let the user exclude
points using x and z ranges.
 user selects 2 points in the x,z plane that lies along
the middle of the cables.
 generate a line and compute the distance from all points to
this line
 plot the distance from all points to this line. let the user
exclude points by this distance.
 set p3[3,*] to the included points
 do a robust linear fit to p3 points in the x,y plane.
 copy p3 to a rvec[3,m] (a temp variable)
 rotate the rvec variable by the x,y slope (after removing
the y offset)
 force the x,z slope to be positive.
 this should put the cables close to the x,z plane, only
separated by their y offsets
 plot the rotated points y vs z. this will spread
the cables out because of their y differences
 let the user select 2 points along each of the cables,
generate a line for each cable
 loop through each cable
 plot the distance of all points to the line for this cable
 let the user specify the maximum distance to keep
 use this to select indices in p3[3,M] for this cable.
store the indices in p3CblI[icable].pind (ptr to array of
indices)
 return p3[*,m] and p3CblIar[ncables] holding the indices
into p3 for each cable.
 preproccable(p3, p3cblIAr,index,fitI) This is called
for each cable found in findcables
 refit the points for the cable
 x,y linear
 y,z, x,z 2nd order
 compute the distance of all points from each fit and let the
user exclude points
 rotate the points to the x,z plane
 fit a parabola to this and plot the residuals vs x,y, and
z.. let the user exclude points
 When done refit the points in the x,y plane
 For each cable we end up with
 indices into p3[3,m] for this cable
 the x,y rotation angle needed to move this cable to the
x,z plane
 the x,z angle giving the vertical slope of each cable
 the parabolic fit parameters that can be used to generate
the initial values for the catenary fit.
Fitting a catenary and computing the tension.
 fitcatenary3dlm(p3,p3cblIar,index,fitI,fitcat)
 this uses a Leven Marquardt non linear least squares fit a
catenary to the data points.
 I ended up having to compute the derivatives for each
parameter :).
 zc= a + b*(cosh(xc)/b 1 ) is a catenary.
 a parabola is a close approximation to a catenary.
 computing the initial values from the parabolic fit
 zp=p0 + p1*x + p2*x^2 is a parabolic fit
 for the catenary let u=(xc)/b . since the cosh is
exponential , u must be small and we can do a taylor series
expansion in u.
 cosh(u)= 1 + u^2/2! + ...
 replacing u with (xc)/b and expanding gives
 zc=a + b*((1+(xc)/b)^2/2 1) = (1/b)*x^2 +
(2c/b)*x + (a +c^2/b)
 equating each term with the parabola's coef gives:
 b=1/p2
 c=(b*p1)/2 = p1/(2*p2)
 a=(p0 c^2/b)=p0  (p1^2/(4*p2)
 These are used for the initial values of the fit
 Computing the tension.
 The cable tension is b * cableWeight/linearDistance *
cos(cableAngle)
 the cableAngle is computed from the catenary fit and the
max,min x values (more
info)
 The tension was computed in Newtons (since i used meters
for distance in the p50) and then it was converted to lbs of
force.
 the routine cmpcbltension() does this.
 The cable tension error is linearly related to the error
in the cable linear density. The values used were:

cable diameter
(inches)

linearDensity
lbs/foot

locations for
cable

3" 
18.9 
platform mains
catwalk to T4

3 1/4" 
22.18 
platform aux
backstay mains
catwalk to T8

3 5/8" 
27.60

backstay aux

1 7/8"

7.39 
catwalk to t12?

Where the code is located
 /share/megs/phil/x101/p50/pro has:
 cmpcbltension.pro,findcables.pro,fitcatenary3dlm.pro,getxyzpnts.pro,pntlinedist2.pro,
and preproccable.pro.
 cbl.h (defines lots of the structures used.
 /share/megs/phi/x101/p50/cables
 proccableall.pro .. this is a template that is located for
each measurement location (eg t4 min,t8main,
t12backstays..etc)
 /share/megs/phil/x101/p50/2008xx,2009xx/ has the
code for each location (by measurement date).
home_~phil