# Gas station without pumps

## 2017 November 10

### Single-arm design probably won’t work

Filed under: Robotics — gasstationwithoutpumps @ 11:57
Tags: , ,

In yesterday’s post Preliminary design review in mechatronics, I contemplated using a single arm to put balls in both targets, with the arm vertical for the higher Ren-ship target and past vertical for the AT-M6 target.  I tried doing some calculations with a hand calculator, and it looked like this might work.  I then drew out the geometry, labeling all the dimensions, and wrote a program to check the constraints carefully.   The program did not accept the values I’d computed by hand, so I did some search in the program and had it report what constraints failed.

Here is a sketch of the geometry: The pivot is X from the edge and Y from the floor. The arm is A long with a cup that is W wide and D deep. The target is S from the edge and between L and H high.
The top and bottom of the cup should fit inside the target range.

The program selected the arm length based on the Ren-ship target, then checked that the arm would meet all constraints for both targets.

Unfortunately, an arm long enough to reach the Ren-ship target is too long to hit the AT-M6 target, no matter where I put the pivot. The problem is that AT-M6 target gets very small if the ball is approaching it with the arm almost horizontal, and the inner edge and outer edge of the ball cup can’t both clear the edges of the target.

I simplified the code to check just one target, and I do have a range of pivot positions that would make the arm work for a each target.  For the Ren-ship target I’d need to have the pivot at least 4.7″ off the floor in order for the arm to be short enough to fit in the initial box, and 6.5″ off the floor if I want the rest position of the arm to be horizontal (assuming the pivot is 1″ from the edge).

For the AT-M6 target, I’d need the pivot to be at least 2″ off the floor and and no more than 5″ off the floor.  The shortest arm would be about 7″ long with the pivot 1″ from the edge and 4″ up, with a separation of 3.8″.  The longest arm would be 10.58″ with the pivot 1″ from the edge and 2″ up, with a separation of 6″.  The best arm length (giving the most flexibility in position of the pivot and separation) seems to be around 7.5″.  I’d have to play around a bit with the computations to take into account other constraints (like interaction with other parts of the robot).  I’ll have to build some track-wired detectors, to see if I can get good sensitivity at large separations (which allows sloppier tape following, since I can be further from going out of bounds).  If sensitivity of the track-wire detector is low, then I can either try to make the robot follow the tape more precisely and risk going out of bounds, or I can deploy the track-wire detector outside the original 11″ box.

Now that the robot is not going to use a single arm for both targets, the don’t have to face the same direction.  The high arm can be on top facing front, and the low arm can be on a lower layer, facing sideways (but there needs to be clearance for the low arm to swing through the higher layers).

Here is the program trying to find a single-arm solution:

```#!/usr/bin/env  python
""" arm-swing.py
Fri Nov 10 07:56:41 PST 2017 Kevin Karplus

Computations to see whether a single arm can be used for both
the AT-M6 and Ren-ship targets for the 2017 Mechatronics course.

The arm is
A inches long with a
D inch deep cup
W inches wide (not extending arm)
R inches above the floor at rest.
The arm pivots
X inches from the edge of the robot,
Y inches from the floor.
The targets are
S inches from the edge of the robot
L inches from the floor at the bottom of the hole
H inches from the floor at the top of the hole

Known values:
L=6, H=10 for AT-M6
L=13, H=15 for Ren ship

Computed values:
B to tip of cup:  sqrt(A^2+D^2)
C to bottom edge of cup: sqrt((A-W)^2+D^2)

Constraints:
sqrt(A^2 - (R-Y)^2) + X < 11" to fit in initial cube
R + (R-Y)D/A  < 11"     height restriction

sqrt(A^2 - (R-Y)^2) + X approx 9" to load balls

sqrt((S+X)^2 + (L-Y)^2) <= C (bottom edge clears) sqrt((S+X)^2 + (H-Y)^2) >= B  (top edge clears)

S for AT-M6:  2"<S<6"  (probably around 4")
S for Ren ship:  0<=S<=0.3"

# mounting space for servo
min_mount_X <=X <= 11"-min_mount_X
min_mount_Y <=Y <= 11"-min_mount_Y

If 1 1/2" Schedule 40 PVC pipe used for cup, then W=1.9"
"""

from __future__ import division, print_function
from math import sqrt
from numpy import arange

min_mount_X = 0.5
min_mount_Y = 1

def ConstraintsMet(A=7, D=1, W=1.9, R=6, X=2, Y=6, S=0, L=13, H=15,
reason=False):
"""Check all the constraints, returning True is constraints met,
False if one fails.

if reason, then print the first constraint that fails
"""

if X<min_mount_X or 11-X<min_mount_X:
if reason: print("too close to edge")
return False    # too close to edge for mounting servo
if Y<min_mount_Y: if reason: print("pivot too low") return False # too low to mount servo if Y>11-min_mount_Y:
if reason: print("pivot too high")
return False    # too high to mount servo

if S<0: if reason: print("overlap target") return False # edge intersects target rest_above_pivot = R-Y rest_width = sqrt(A**2 - rest_above_pivot**2) if rest_width+X >= 11:
if reason: print("too wide")
return False    # too wide for initial box

rest_tip_height = R + rest_above_pivot*D/A  # resting height of tip
if rest_tip_height >= 11:
if reason: print("too tall")
return False    # too tall for initial box

if rest_width+X < 8 or rest_width+X>=9.5:

# distance from pivot to tip of cup
tip_to_pivot= sqrt(A**2 + D**2)
pivot_to_top = sqrt((S+X)**2 + (H-Y)**2)
if tip_to_pivot > pivot_to_top:
#        print("DEBUG: hits top Y={:.2f}, A={:.2f}, tip_to_pivot={:.2f}, pivot_to_top={:.2f}".format(Y,A,tip_to_pivot,pivot_to_top))
if reason: print("doesn't clear top, tip_to_pivot={:.2f} pivot_to_top={:.2f}".format(tip_to_pivot,pivot_to_top))
return False    # doesn't clear top of hole

# distance from pivot to inner lip of cup
inner_to_pivot= sqrt((A-W)**2 + D**2)
pivot_to_bottom = sqrt((S+X)**2 + (L-Y)**2)
if inner_to_pivot < pivot_to_bottom:
#        print("DEBUG: hits bottom Y={:.2f}, A={:.2f}, inner_to_pivot={:.2f}, pivot_to_bottom={:.2f}".format(Y,A,inner_to_pivot,pivot_to_bottom))
if reason: print("doesn't clear bottom inner_to_pivot={:.2f}, pivot_to_bottom={:.2f}".format(inner_to_pivot,pivot_to_bottom))
return False    # doesn't clear bottom of hole

return True

# tops and bottoms of targets
H_Ren = 15
L_Ren = 13

H_ATM6 = 10
L_ATM6 = 6

# some fixed values
W = 1.9
D = 1
X = 1

# some values to explore
for Y in arange(2., 9.05, 0.1):
for R in arange(Y, 11.05, 0.1):
# set arm length to just clear top of hole when touching Ren ship
pivot_to_top = sqrt(X**2+(H_Ren-Y)**2)
A_long = sqrt(pivot_to_top**2 - D**2)

# set arm length to just clear bottom of hole when touching Ren ship
pivot_to_bottom = sqrt(X**2 + (L_Ren-Y)**2)
A_short = sqrt(pivot_to_bottom**2 -D**2) + W

for A in [A_short, A_long]:
if not ConstraintsMet(A=A, D=D, W=W, R=R, X=X, Y=Y,
S=0, L=L_Ren, H=H_Ren):
continue
print ("Y={:.2f} met Ren constraints".format(Y))
for S in arange(2.,6.05, 0.2):
if ConstraintsMet(A=A, D=D, W=W, R=R, X=X, Y=Y,
S=S, L=L_ATM6, H=H_ATM6, reason=True):
print ("X={:.2f}, Y={:.2f}, A={:.2f}, R={:.2f}, SATM6={:.2f}".format(X,Y,A,R,S))
```