Commit a961277c authored by Steve T's avatar Steve T
Browse files

added relative constraints

parent 67e0bb96
......@@ -239,7 +239,7 @@ def RelativeDistanceConstraint(pb, phaseDataT, A, b, startCol, endCol, startRow,
for (footId, Kk ) in constraintsInFootIdFrame:
K = Kk[0]; k = Kk[1]
consLen = K.shape[0]
A[idRow:idRow+consLen, startCol:startCol+DEFAULT_NUM_VARS] = K.dot(footExpressionMatrix[footId] - footExpressionMatrix[footIdFrame])
A[idRow:idRow+consLen, startCol:startCol+DEFAULT_NUM_VARS] = K.dot(-footExpressionMatrix[footId] + footExpressionMatrix[footIdFrame])
b[idRow:idRow+consLen] = k
idRow += consLen
return idRow
......@@ -355,7 +355,7 @@ def convertProblemToLp(pb, convertSurfaces = True):
#inequality
endCol = startCol + numVariablesForPhase(phaseDataT)
startRow = FootCOMKinConstraint(pb, phaseDataT, A, b, previousStartCol, startCol, endCol, startRow, phaseId)
startRow = RelativeDistanceConstraint(pb, phaseDataT, A, b, startCol, endCol, startRow, phaseId)
# ~ startRow = RelativeDistanceConstraint(pb, phaseDataT, A, b, startCol, endCol, startRow, phaseId)
startRow = SurfaceConstraint(phaseDataT, A, b, startCol, endCol, startRow)
startRow = SlackPositivityConstraint(phaseDataT, A, b, startCol, endCol, startRow)
......@@ -368,9 +368,9 @@ def convertProblemToLp(pb, convertSurfaces = True):
print ('startRow ', startRow)
print ('A.shape[0] ', A.shape[0])
assert endCol == A.shape[1]
assert startRowEq == E.shape[0]
assert startRow == A.shape[0]
# ~ assert endCol == A.shape[1]
# ~ assert startRowEq == E.shape[0]
# ~ assert startRow == A.shape[0]
A,b = normalize([A,b])
E,e = normalize([E,e])
......@@ -438,7 +438,7 @@ def retrieve_points_from_res(pb, res):
# ~ footPos = [[pb["p0"][LF]],[pb["p0"][RF]]]
# ~ allFeetPos = [footPos[0][0], footPos[1][0]]
# ~ else:
footPos = [[],[]]
footPos = [[] for _ in range(N_EFFECTORS)]
allFeetPos = []
col = 0
......@@ -502,20 +502,26 @@ def plotQPRes(pb, res, linewidth=2, ax = None, plot_constraints = False, show =
if ax is None:
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.grid(False)
ax.grid(False)
ax.set_xlim3d(0, 2)
ax.set_ylim3d(0,2)
ax.set_zlim3d(0,2)
ax.set_autoscale_on(False)
ax.view_init(elev=8.776933438381377, azim=-99.32358055821186)
plotPoints(ax, coms, color = "b")
plotPoints(ax, footpos[RF], color = "r")
plotPoints(ax, footpos[LF], color = "g")
footColors = ['r', 'g', 'y', 'b']
# ~ plotPoints(ax, coms, )
[plotPoints(ax, footpos[idx], color = footColors[idx]) for idx in range(N_EFFECTORS)]
cx = [c[0] for c in coms]
cy = [c[1] for c in coms]
cz = [c[2] for c in coms]
ax.plot(cx, cy, cz)
# ~ px = [c[0] for c in allfeetpos]
px = [c[0] for c in allfeetpos]
py = [c[1] for c in allfeetpos]
pz = [c[2] for c in allfeetpos]
# ~ ax.plot(px, py, pz)
......@@ -526,7 +532,8 @@ def plotQPRes(pb, res, linewidth=2, ax = None, plot_constraints = False, show =
def addInitEndConstraint(pb, E, e, posInit= array([0.16, 0.585, 0.0]), posEnd = array([1.2, 0.37, 0.40])):
# ~ def addInitEndConstraint(pb, E, e, posInit= array([0.16, 0.585, 0.0]), posEnd = array([1.2, 0.37, 0.40])):
def addInitEndConstraint(pb, E, e, posInit= array([0.16, 0.585, 0.0]), posEnd = array([1., 0.585, 0.])):
# ~ def addInitEndConstraint(pb, E, e, posInit= array([0.0, 0.0, 0.4]), posEnd = array([-0.0, 0.0, 0.4])):
nE = zeros((E.shape[0] +9, E.shape[1] ))
ne = zeros(E.shape[0] +9)
......@@ -536,12 +543,14 @@ def addInitEndConstraint(pb, E, e, posInit= array([0.16, 0.585, 0.0]), posEnd =
nE[idRow:idRow+3,:DEFAULT_NUM_VARS] = footExpressionMatrix[0][:]
ne[idRow:idRow+3] = posInit
idRow += 3
nE[idRow:idRow+3,:DEFAULT_NUM_VARS] = footExpressionMatrix[1][:]
ne[idRow:idRow+3] = posInit + array([0., -.20, 0.0])
# ~ nE[idRow:idRow+3,:DEFAULT_NUM_VARS] = footExpressionMatrix[1][:]
# ~ nE[idRow:idRow+3,:DEFAULT_NUM_VARS] = footExpressionMatrix[0][:]
# ~ ne[idRow:idRow+3] = posInit
# ~ ne[idRow:idRow+3] = posInit + array([0., -.20, 0.0])
nVarEnd = numVariablesForPhase(pb["phaseData"][-1])
# ~ print ("nVarEnd", nVarEnd, E.shape[1]-nVarEnd, E.shape[1]-nVarEnd,E.shape[1]-nVarEnd+DEFAULT_NUM_VARS )
# ~ nE[-3:,E.shape[1]-nVarEnd:E.shape[1]-nVarEnd+DEFAULT_NUM_VARS] = footExpressionMatrix[1][:]
# ~ ne[-3:] = posEnd
nE[-3:,E.shape[1]-nVarEnd:E.shape[1]-nVarEnd+DEFAULT_NUM_VARS] = footExpressionMatrix[0][:]
ne[-3:] = posEnd
return nE, ne
####################### MAIN ###################"
......@@ -653,7 +662,7 @@ def solveMIPGurobi(pb, surfaces, MIP = True, draw_scene = None, plot = True, ini
grb.setParam('OutputFlag', 1)
A, b, E, e = convertProblemToLp(pb)
# ~ E,e = addInitEndConstraint(pb, E, e)
E,e = addInitEndConstraint(pb, E, e)
slackMatrix = wSelectionMatrix(pb)
slackIndices = [i for i,el in enumerate (slackMatrix) if el > 0]
numSlackVariables = len([el for el in slackMatrix if el > 0])
......
......@@ -10,8 +10,11 @@ np.set_printoptions(formatter={'float': lambda x: "{0:0.1f}".format(x)})
############### Problem definition #############
#same as in constraints
LF = 0
RF = 1
LH = 2
RH = 3
def normalize(Ab):
A = Ab[0]
......
import numpy as np
from numpy import array, asmatrix, matrix, zeros, ones
from numpy import array, dot, stack, vstack, hstack, asmatrix, identity, cross, concatenate
from numpy.linalg import norm
from sl1m.constants_and_tools import *
from sl1m.planner_l1_generic_equalities_as_ineq import *
from sl1m.stand_alone_scenarios.constraints_anymal import *
floor = [ [-10, -10., 0.], [10, -10., 0.], [10, 10., 0.], [-10, 10., 0.] ]
afloor = array(floor).T
all_surfaces = [floor]
surfaces = [[afloor] for _ in range (10)]
def gen_flat_pb():
kinematicConstraints = genCOMConstraints()
relativeConstraints = genRelativeConstraints()
nphases = len(surfaces)
p0 = None
res = { "p0" : p0, "c0" : None, "nphases": nphases}
phaseData = [ {"K" : [copyKin(kinematicConstraints) for _ in range(len(surfaces[i]))], "S" : surfaces[i], "allRelativeK" : [relativeConstraints] } for i in range(nphases)]
res ["phaseData"] = phaseData
return res
import mpl_toolkits.mplot3d as a3
import matplotlib.colors as colors
import scipy as sp
def draw_rectangle(l, ax):
#~ plotPoints(ax,l)
lr = l + [l[0]]
cx = [c[0] for c in lr]
cy = [c[1] for c in lr]
cz = [c[2] for c in lr]
ax.plot(cx, cy, cz)
def draw_scene(surfaces, ax = None, color = "p"):
if ax is None:
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
[draw_rectangle(l,ax) for l in all_surfaces]
return ax
############# main ###################
if __name__ == '__main__':
from sl1m.planner_l1_generic_equalities_as_ineq import solveMIPGurobi, plotQPRes, initGlobals
# ~ from sl1m.fix_sparsity import solveL1, solveMIP
initGlobals(nEffectors = 4)
pb = gen_flat_pb()
pb, res, time = solveMIPGurobi(pb, surfaces, MIP = True, draw_scene = None, plot = True, l1Contact = False)
ax = draw_scene(None)
plotQPRes(pb, res, ax=ax, plot_constraints = False)
from sl1m.constants_and_tools import *
import sl1m.stand_alone_scenarios
import os
insdir = os.path.dirname(sl1m.stand_alone_scenarios.__file__) + "/constraints_files/anymal/"
limbNames = ['LFleg', 'RFleg', 'LHleg', 'RHleg']
effectorNames = ['LF_ADAPTER_TO_FOOT', 'RF_ADAPTER_TO_FOOT', 'LH_ADAPTER_TO_FOOT', 'RH_ADAPTER_TO_FOOT']
__ineq_com = [None for _ in range(len(limbNames))]
__ineq_relative = [ [None for _ in range(len(limbNames)-1)] for __ in range(len(limbNames))]
# add foot offset
def com_in_limb_effector_frame_constraint(transform, limbId):
global __ineq_com
assert (limbId <= len(effectorNames))
if __ineq_com[limbId] is None:
# ~ filekin = insdir +"anymal_LF_ADAPTER_TO_FOOT_constraints_in_LHleg_reduced.obj"
filekin = insdir +"anymal_COM_constraints_in_"+limbNames[limbId]+ "_effector_frame_quasi_static_reduced.obj"
obj = load_obj(filekin)
__ineq_com[limbId] = as_inequalities(obj)
transform2 = transform.copy()
# ~ transform2[2,3] += 0.105
ine = rotate_inequalities(__ineq_com[limbId], transform2)
return (ine.A, ine.b)
def realIdxFootId(limbId, footId):
if footId > limbId:
return footId -1
return footId
# add foot offset
def foot_in_limb_effector_frame_constraint(transform, limbId, footId):
global __ineq_relative
assert (limbId != footId)
if __ineq_relative[limbId][realIdxFootId(limbId,footId)] is None:
# ~ filekin = insdir +"RF_constraints_in_LF.obj"
filekin = insdir +"anymal_"+effectorNames[footId]+"_constraints_in_"+limbNames[limbId]+"_reduced.obj"
obj = load_obj(filekin)
__ineq_relative[limbId][realIdxFootId(limbId,footId)] = as_inequalities(obj)
transform2 = transform.copy()
ine = rotate_inequalities(__ineq_relative[limbId][realIdxFootId(limbId,footId)], transform2)
return (ine.A, ine.b)
def genCOMConstraints(rotation = [Id for _ in range(len(limbNames))], normals = [z for _ in range(len(limbNames))]):
return [com_in_limb_effector_frame_constraint(default_transform_from_pos_normal_(rotation[idx], zero3, normals[idx]),idx) for idx in range(len(limbNames))]
def genRelativeConstraints(rotation = [Id for _ in range(len(limbNames))], normals = [z for _ in range(len(limbNames))]):
transforms = [default_transform_from_pos_normal_(rotation[idx], zero3, normals[idx]) for idx in range(len(limbNames))]
res = []
for limbId, transform in enumerate(transforms):
res += [[(footId, foot_in_limb_effector_frame_constraint(transform, limbId, footId)) for footId in range(len(limbNames)) if footId != limbId]]
return res
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
o anymal_COM_constraints_in_LFleg_effector_frame_quasi_static.001_anymal_COM_constraints_in_LFleg_effector_frame_quasi_static.003
v -0.018386 -0.044425 0.423556
v -0.481759 0.019530 0.305900
v -0.072333 0.615141 0.307145
v 0.084900 0.149811 0.501762
v -0.370580 -0.070909 0.352599
v -0.044000 0.261389 0.581238
v -0.217687 0.104211 0.531897
v -0.487585 0.137149 0.424248
v -0.305798 0.335635 0.563475
v -0.553603 0.334793 0.397078
v 0.047762 0.494796 0.456596
v 0.087900 0.323488 0.535304
v -0.470652 0.535433 0.301701
v -0.252438 0.519702 0.460385
v -0.473448 0.487710 0.376126
v -0.039544 0.499984 0.495780
vn -0.0982 -0.6688 0.7369
vn -0.1167 -0.1778 0.9771
vn 0.9317 0.0533 -0.3592
vn 0.3982 -0.1806 0.8993
vn -0.9318 -0.2794 0.2318
vn 0.2235 -0.1517 -0.9628
vn -0.3746 -0.4832 0.7913
vn -0.8360 0.4757 0.2736
vn -0.0078 0.8529 0.5220
vn -0.3677 0.5333 0.7619
vn 0.2609 0.8435 0.4696
vn -0.0954 0.5073 0.8565
vn -0.7661 0.0113 -0.6426
vn 0.2089 -0.2336 -0.9496
vn 0.6846 -0.0720 -0.7253
vn -0.1884 0.9176 0.3500
vn 0.7803 0.0021 -0.6254
vn 0.3865 0.4583 0.8004
vn -0.3092 0.8058 0.5051
vn -0.5559 -0.0718 0.8282
vn 0.1552 -0.4479 0.8805
vn 0.0154 -0.0085 -0.9998
vn -0.6611 -0.5482 0.5123
vn -0.5173 0.3765 0.7685
vn 0.0316 0.3365 0.9412
vn 0.1683 0.3296 0.9290
vn -0.3850 -0.2671 0.8834
vn 0.1543 -0.4385 0.8854
s off
f 5//1 1//1 7//1
f 9//2 7//2 6//2
f 4//3 11//3 12//3
f 6//4 4//4 12//4
f 10//5 2//5 8//5
f 2//6 3//6 1//6
f 8//7 5//7 7//7
f 13//8 10//8 15//8
f 3//9 14//9 16//9
f 15//10 9//10 14//10
f 3//11 16//11 11//11
f 9//12 16//12 14//12
f 10//13 13//13 2//13
f 5//14 2//14 1//14
f 1//15 3//15 4//15
f 13//16 14//16 3//16
f 3//17 11//17 4//17
f 16//18 12//18 11//18
f 13//19 15//19 14//19
f 8//20 9//20 10//20
f 7//21 4//21 6//21
f 2//22 13//22 3//22
f 8//23 2//23 5//23
f 15//24 10//24 9//24
f 9//25 6//25 16//25
f 16//26 6//26 12//26
f 8//27 7//27 9//27
f 7//28 1//28 4//28
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
o anymal_COM_constraints_in_LHleg_effector_frame_quasi_static.001
v -0.054874 0.100247 0.389137
v -0.400228 0.079547 0.302220
v 0.087799 -0.189625 0.514526
v -0.027934 -0.540928 0.348958
v -0.169779 -0.159468 0.557656
v -0.140080 -0.310725 0.557420
v -0.499523 -0.404849 0.305046
v -0.517937 -0.053547 0.330596
v 0.034088 -0.386705 0.503386
v -0.251636 -0.006534 0.473648
v 0.026624 -0.045964 0.483921
v -0.517395 -0.344335 0.382635
v -0.475166 -0.161480 0.438948
v -0.375959 -0.248443 0.512439
v -0.388765 -0.526001 0.304080
v -0.227169 -0.449345 0.481984
vn -0.0942 -0.8803 0.4649
vn -0.1974 -0.0403 0.9795
vn -0.8996 0.0753 0.4301
vn -0.4288 -0.4374 0.7904
vn -0.1909 0.8009 0.5676
vn 0.9046 0.3270 -0.2735
vn 0.1904 0.2814 0.9405
vn 0.7380 0.0730 -0.6708
vn -0.0123 -0.0033 -0.9999
vn 0.0492 0.5625 0.8253
vn -0.4730 0.5238 0.7085
vn 0.2455 -0.1213 0.9618
vn -0.6410 -0.0868 0.7626
vn -0.6936 -0.6368 0.3369
vn 0.1186 -0.7260 0.6774
vn -0.3615 0.3259 0.8736
vn -0.9797 -0.0370 -0.1968
vn 0.9583 -0.2537 -0.1315
vn -0.2915 0.0542 -0.9550
vn -0.2602 -0.3303 0.9073
vn 0.2440 0.0016 -0.9698
vn -0.4448 -0.6018 0.6633
vn 0.1687 0.0316 0.9852
vn 0.0384 0.4968 0.8670
vn -0.4668 0.5590 0.6853
vn 0.0494 -0.5012 0.8639
vn -0.3302 0.3125 0.8907
vn 0.1259 0.0673 -0.9898
s off
f 16//1 15//1 4//1
f 14//2 6//2 5//2
f 12//3 13//3 8//3
f 12//4 16//4 14//4
f 2//5 10//5 1//5
f 1//6 11//6 3//6
f 5//7 3//7 11//7
f 4//8 1//8 3//8
f 15//9 7//9 2//9
f 10//10 11//10 1//10
f 10//11 8//11 13//11
f 6//12 9//12 3//12
f 13//13 12//13 14//13
f 12//14 7//14 15//14
f 9//15 16//15 4//15
f 14//16 10//16 13//16
f 7//17 12//17 8//17
f 9//18 4//18 3//18
f 7//19 8//19 2//19
f 14//20 16//20 6//20
f 1//21 15//21 2//21
f 12//22 15//22 16//22
f 5//23 6//23 3//23
f 10//24 5//24 11//24
f 10//25 2//25 8//25
f 9//26 6//26 16//26
f 14//27 5//27 10//27
f 1//28 4//28 15//28
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
o anymal_COM_constraints_in_RFleg_effector_frame_quasi_static.002_anymal_COM_constraints_in_RFleg_effector_frame_quasi_static.007
v -0.035300 -0.028139 0.420626
v 0.135414 -0.066174 0.422354
v 0.442539 -0.067861 0.295447
v 0.549138 0.239282 0.399845
v 0.053547 0.597657 0.327900
v 0.517040 0.443135 0.366585
v 0.312669 0.526835 0.449509
v -0.084929 0.371628 0.517995
v 0.384166 0.054585 0.455483
v 0.115362 0.162605 0.572758
v 0.181693 0.464411 0.524442
v 0.443946 0.557788 0.294550
v 0.100834 0.333519 0.577835
v -0.047473 0.489802 0.475945
v 0.397380 0.302306 0.517721
v -0.081900 0.210004 0.535760
vn 0.1485 -0.5341 0.8323
vn 0.1974 -0.0123 0.9802
vn 0.5345 -0.2327 0.8125
vn -0.8267 0.0342 -0.5616
vn 0.2176 0.2504 0.9434
vn 0.6850 -0.4361 0.5835
vn -0.9571 -0.0493 -0.2854
vn -0.1901 -0.8734 -0.4483
vn 0.4981 0.6662 0.5550
vn 0.6999 -0.0026 -0.7143
vn 0.2625 -0.7177 0.6449
vn -0.2866 0.0994 0.9529
vn -0.0427 0.8211 0.5691
vn -0.2101 0.3862 0.8982
vn -0.8508 0.0852 -0.5185
vn -0.2694 -0.4614 0.8453
vn 0.1219 0.9484 0.2927
vn 0.3146 0.3826 0.8687
vn 0.7061 -0.0044 -0.7081
vn 0.6538 0.2210 0.7236
vn -0.0382 0.7996 0.5993
vn -0.2535 -0.0008 -0.9673
vn 0.3022 -0.2474 0.9206
vn 0.4830 0.4163 0.7703
vn -0.1947 -0.0457 0.9798
vn -0.1378 0.4459 0.8844
vn -0.1314 -0.5526 0.8230
vn -0.0978 -0.1323 -0.9864
s off
f 10//1 2//1 9//1
f 10//2 15//2 13//2
f 15//3 9//3 4//3
f 8//4 5//4 1//4
f 11//5 13//5 15//5
f 9//6 3//6 4//6
f 16//7 8//7 1//7
f 2//8 1//8 3//8
f 7//9 6//9 12//9
f 12//10 6//10 3//10
f 2//11 3//11 9//11
f 16//12 13//12 8//12
f 5//13 14//13 7//13
f 13//14 14//14 8//14
f 8//15 14//15 5//15
f 1//16 10//16 16//16
f 12//17 5//17 7//17
f 7//18 11//18 15//18
f 3//19 6//19 4//19
f 6//20 15//20 4//20
f 14//21 11//21 7//21
f 1//22 12//22 3//22
f 10//23 9//23 15//23
f 7//24 15//24 6//24
f 16//25 10//25 13//25
f 13//26 11//26 14//26
f 1//27 2//27 10//27
f 1//28 5//28 12//28
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
o anymal_COM_constraints_in_RHleg_effector_frame_quasi_static.002_anymal_COM_constraints_in_RHleg_effector_frame_quasi_static.003
v 0.479090 -0.470694 0.310964
v 0.482249 0.001535 0.310463
v 0.531194 -0.190226 0.419887
v 0.311800 -0.350711 0.521030
v 0.191090 -0.181422 0.566191
v 0.100590 -0.453116 0.494281
v 0.086756 0.083325 0.396658
v -0.085503 -0.129009 0.517376
v 0.364465 0.086658 0.314819
v 0.221714 -0.003856 0.481690
v 0.017039 -0.521369 0.368650
v -0.059611 -0.394215 0.485712
v 0.294791 -0.543863 0.306695
vn -0.1970 -0.1352 0.9710
vn 0.0236 -0.0012 -0.9997
vn 0.6031 -0.3836 0.6994
vn -0.3035 -0.7379 0.6028
vn 0.0310 -0.8868 0.4611
vn 0.2717 -0.7255 0.6323
vn 0.3957 0.0374 0.9176
vn 0.1590 0.8044 0.5724
vn 0.9085 -0.0065 -0.4178
vn 0.0019 -0.2565 0.9666
vn -0.6580 0.1104 -0.7449
vn 0.4410 0.5750 0.6891
vn -0.1393 0.5724 0.8080
vn -0.8457 -0.0189 -0.5332
vn 0.4596 0.5258 0.7158
vn -0.2829 0.0436 -0.9582
vn -0.1301 -0.2130 0.9684
vn -0.0256 0.0157 -0.9995
vn 0.2733 -0.7253 0.6319
vn -0.0748 0.4390 0.8954
vn 0.3786 0.3437 0.8594
vn -0.2118 0.0696 -0.9748
s off
f 12//1 5//1 8//1
f 13//2 2//2 1//2
f 4//3 1//3 3//3
f 11//4 6//4 12//4
f 6//5 11//5 13//5
f 13//6 4//6 6//6
f 5//7 4//7 3//7
f 9//8 7//8 10//8
f 1//9 2//9 3//9
f 6//10 4//10 5//10
f 11//11 8//11 7//11
f 9//12 10//12 2//12
f 8//13 10//13 7//13
f 11//14 12//14 8//14
f 10//15 3//15 2//15
f 13//16 7//16 9//16
f 12//17 6//17 5//17
f 13//18 9//18 2//18
f 13//19 1//19 4//19
f 8//20 5//20 10//20
f 10//21 5//21 3//21
f 13//22 11//22 7//22
# Blender v2.82 (sub 7) OBJ File: ''
# www.blender.org
o anymal_LF_ADAPTER_TO_FOOT_constraints_in_LHleg.001
v -0.331057 0.075295 -0.228294
v -0.324912 -0.866425 -0.320622
v 0.290834 -1.131798 0.081195
v -0.281043 -0.941883 0.181288
v 0.371916 -0.803123 -0.114969
v -0.398453 -1.084626 -0.134435
v 0.085618 0.112122 -0.076412
v 0.608208 -0.539307 0.108318
v -0.625007 -0.485214 -0.154593
v -0.455566 -0.078478 -0.021071
v 0.487871 -0.151508 0.234791
v 0.427479 -0.969340 0.308615
vn -0.7204 -0.2934 -0.6284
vn -0.6723 0.0374 0.7393
vn -0.8775 0.4331 -0.2058
vn -0.1521 0.6484 0.7459
vn -0.2483 0.8433 0.4766
vn -0.3953 0.0871 -0.9144
vn 0.6884 0.2441 -0.6830
vn -0.2452 0.1740 0.9537
vn -0.8405 -0.3026 0.4494
vn 0.8878 -0.3768 -0.2643
vn 0.7350 0.0069 0.6781
vn -0.2045 -0.8611 0.4654
vn 0.3336 0.0941 -0.9380
vn 0.1786 -0.6728 -0.7180