|
|
import qpsolvers |
|
|
import numpy as np |
|
|
try: |
|
|
SPATIAL_MATH = True |
|
|
from spatialmath import SE3,SO3, base |
|
|
import spatialmath |
|
|
except ImportError: |
|
|
SPATIAL_MATH = False |
|
|
print("spatialmath is not installed") |
|
|
|
|
|
import pinocchio as pin |
|
|
import time |
|
|
|
|
|
from cvxopt import matrix |
|
|
import cvxopt.glpk |
|
|
|
|
|
from scipy.optimize import linprog |
|
|
from scipy.linalg import block_diag |
|
|
|
|
|
from pynocchio import RobotWrapper |
|
|
|
|
|
def solve_lp(c, A_eq, b_eq, x_min, x_max): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c = matrix(c) |
|
|
A = matrix(A_eq) |
|
|
b = matrix(b_eq) |
|
|
G = matrix(np.vstack((-np.identity(len(x_min)),np.identity(len(x_min))))) |
|
|
h = matrix(np.hstack((list(-np.array(x_min)),x_max))) |
|
|
solvers_opt={'tm_lim': 100000, 'msg_lev': 'GLP_MSG_OFF', 'it_lim':10000} |
|
|
res = cvxopt.glpk.lp(c=c, A=A, b=b, G=G,h=h, options=solvers_opt) |
|
|
return np.array(res[1]).reshape((-1,)) |
|
|
|
|
|
|
|
|
def solve_qp(A,s,x_min,x_max, grad = None, reg_w=1e-7, solver=None): |
|
|
|
|
|
if (solver is None) or('cvxopt' in solver ) : |
|
|
A =np.matrix(A) |
|
|
s = np.matrix(s) |
|
|
|
|
|
P = A.T@A |
|
|
if grad is not None: |
|
|
grad = np.matrix(grad).reshape(1,-1) |
|
|
q = matrix(-A.T@s + reg_w*grad.T) |
|
|
P = P + np.eye(len(grad))*reg_w |
|
|
else: |
|
|
q = matrix(-A.T@s) |
|
|
P = matrix(P) |
|
|
G = matrix(np.vstack((-np.identity(len(x_max)),np.identity(len(x_min))))) |
|
|
h = matrix(np.hstack((list(-np.array(x_min)),x_max))) |
|
|
return np.array(cvxopt.solvers.qp(P, q, G, h)['x']).flatten() |
|
|
|
|
|
else: |
|
|
|
|
|
P = A.T@A |
|
|
if grad is not None: |
|
|
q = -A.T@s + reg_w*grad[:,None] |
|
|
P= P+np.eye(len(grad))*reg_w |
|
|
else: |
|
|
q = -A.T@s |
|
|
G = np.vstack((-np.identity(len(x_max)),np.identity(len(x_min)))) |
|
|
h = np.hstack((list(-np.array(x_min)),x_max)) |
|
|
|
|
|
return qpsolvers.solve_qp(P, q.flatten(), G,h, solver=solver) |
|
|
|
|
|
from copy import copy |
|
|
from pathlib import Path |
|
|
from sys import path |
|
|
import time |
|
|
|
|
|
from ruckig import InputParameter, OutputParameter, Result, Ruckig |
|
|
|
|
|
class TrajData(): |
|
|
name = '' |
|
|
|
|
|
|
|
|
def compute_capacity_aware_trajectory(X_init, X_final,q0, robot=None, robot_pyn=None, lims=[], scale=1.0, options = None , verbose=False): |
|
|
|
|
|
|
|
|
|
|
|
if type(X_init) == np.ndarray: |
|
|
X_init = pin.SE3(X_init[:3,:3], X_init[:3,3]) |
|
|
X_final = pin.SE3(X_final[:3,:3], X_final[:3,3]) |
|
|
elif type(X_init) == pin.SE3: |
|
|
pass |
|
|
elif SPATIAL_MATH and (type(X_init) == spatialmath.pose3d.SE3): |
|
|
X_init = pin.SE3(X_init.R, X_init.t) |
|
|
X_final = pin.SE3(X_final.R, X_final.t) |
|
|
else: |
|
|
print("Unknown type of X_init") |
|
|
return |
|
|
|
|
|
if robot_pyn is not None: |
|
|
X_r = robot_pyn.forward(q0) |
|
|
n_dof = robot_pyn.n |
|
|
elif robot is not None: |
|
|
X_r = robot.fkine(q0) |
|
|
n_dof = robot.n |
|
|
else: |
|
|
print("Please provide either robot or robot_pyn") |
|
|
return |
|
|
|
|
|
|
|
|
if options is not None and 'uptate_current_position' in options.keys(): |
|
|
uptate_current_position = options['uptate_current_position'] |
|
|
else: |
|
|
uptate_current_position = False |
|
|
|
|
|
if options is not None and 'qp_form' in options.keys(): |
|
|
qp_form = options['qp_form'] |
|
|
else: |
|
|
qp_form = 'acceleration' |
|
|
|
|
|
|
|
|
if options is not None and 'calculate_limits' in options.keys(): |
|
|
calculate_limits = options['calculate_limits'] |
|
|
else: |
|
|
calculate_limits = True |
|
|
|
|
|
if options is not None and 'scale_limits' in options.keys(): |
|
|
scale_limits = options['scale_limits'] |
|
|
else: |
|
|
scale_limits = True |
|
|
|
|
|
if options is not None and 'stop_on_singular' in options.keys(): |
|
|
stop_on_singular = options['stop_on_singular'] |
|
|
else: |
|
|
stop_on_singular = False |
|
|
|
|
|
if options is not None and 'downsampling_ratio' in options.keys(): |
|
|
n_ruckig = options['downsampling_ratio'] |
|
|
else: |
|
|
n_ruckig = 1.0 |
|
|
|
|
|
if options is not None and 'jerk_scale' in options.keys(): |
|
|
jerk_scale = options['jerk_scale'] |
|
|
else: |
|
|
jerk_scale =scale |
|
|
|
|
|
if lims is None: |
|
|
print('no limits specified') |
|
|
data = [] |
|
|
return |
|
|
else: |
|
|
if scale_limits: |
|
|
dq_max = scale*lims['dq_max'].copy() |
|
|
ddq_max = scale*lims['ddq_max'].copy() |
|
|
dddq_max = jerk_scale*lims['dddq_max'].copy() |
|
|
t_max = scale*lims['t_max'].copy() |
|
|
else: |
|
|
dq_max = lims['dq_max'].copy() |
|
|
ddq_max = lims['ddq_max'].copy() |
|
|
dddq_max = lims['dddq_max'].copy() |
|
|
t_max = lims['t_max'].copy() |
|
|
q_min, q_max = lims['q_min'].copy(), lims['q_max'].copy() |
|
|
dq_min = -dq_max |
|
|
ddq_min = -ddq_max |
|
|
dddq_min = -dddq_max |
|
|
t_min = -t_max |
|
|
|
|
|
|
|
|
dddx_max = scale*lims['dddx_max'].copy() |
|
|
dddx_min = -dddx_max |
|
|
ddx_max = scale*lims['ddx_max'].copy() |
|
|
ddx_min = -ddx_max |
|
|
dx_max = scale*lims['dx_max'].copy() |
|
|
dx_min = -dx_max |
|
|
|
|
|
if options is not None and 'scaled_qp_limits' in options.keys(): |
|
|
scaled_qp_limits = options['scaled_qp_limits'] |
|
|
else: |
|
|
scaled_qp_limits = True |
|
|
|
|
|
if options is not None and 'Kp' in options.keys(): |
|
|
Kp = options['Kp'] |
|
|
Kd = options['Kd'] |
|
|
Ki = options['Ki'] |
|
|
else: |
|
|
Kp = 170 |
|
|
Kd = 40 |
|
|
Ki = 0 |
|
|
|
|
|
if options is not None and 'clamp_velocity' in options.keys(): |
|
|
clamp_velocity = options['clamp_velocity'] |
|
|
else: |
|
|
clamp_velocity = True |
|
|
|
|
|
if options is not None and 'clamp_min_accel' in options.keys(): |
|
|
clamp_min_accel = options['clamp_min_accel'] |
|
|
else: |
|
|
clamp_min_accel = False |
|
|
|
|
|
|
|
|
|
|
|
if options is not None and 'override_acceleration' in options.keys(): |
|
|
override_acceleration = options['override_acceleration'] |
|
|
else: |
|
|
override_acceleration = True |
|
|
|
|
|
|
|
|
if options is not None and 'use_manip_grad' in options.keys(): |
|
|
use_manip_grad = options['use_manip_grad'] |
|
|
else: |
|
|
use_manip_grad = False |
|
|
|
|
|
if use_manip_grad and robot is None: |
|
|
print("We need RTB model to calculate the manipulability gradient") |
|
|
return |
|
|
|
|
|
if options is not None and 'manip_grad_w' in options.keys(): |
|
|
manip_grad_w = options['manip_grad_w'] |
|
|
else: |
|
|
manip_grad_w = 50000.0 |
|
|
|
|
|
data = TrajData() |
|
|
u = np.zeros(6) |
|
|
u[:3] = X_final.translation-X_init.translation |
|
|
d = np.linalg.norm(u) |
|
|
u = u/d |
|
|
|
|
|
U,S,V = np.linalg.svd(u[:,None]) |
|
|
V2 = U[:,1:].T |
|
|
|
|
|
U,S,V = np.linalg.svd(u[:3,None]) |
|
|
V23 = U[:,1:].T |
|
|
|
|
|
if options is not None and 'dt' in options.keys(): |
|
|
dt = options['dt'] |
|
|
else: |
|
|
dt = 0.001 |
|
|
|
|
|
dt_ruckig = n_ruckig*dt |
|
|
|
|
|
|
|
|
if options is not None and 'Tf' in options.keys(): |
|
|
Tf = options['Tf'] |
|
|
alpha = Tf/(Tf + dt) |
|
|
else: |
|
|
Tf = 0.00 |
|
|
alpha = Tf/(Tf + dt) |
|
|
|
|
|
|
|
|
otg = Ruckig(1, dt_ruckig) |
|
|
inp = InputParameter(1) |
|
|
out = OutputParameter(1) |
|
|
|
|
|
|
|
|
inp.current_position = [0.0] |
|
|
inp.current_velocity = [0.0] |
|
|
inp.current_acceleration = [0.0] |
|
|
|
|
|
inp.target_position = [d] |
|
|
inp.target_velocity = [0.0] |
|
|
inp.target_acceleration = [0.0] |
|
|
|
|
|
inp.max_velocity = [dx_max[0]] |
|
|
inp.max_acceleration = [ddx_max[0]] |
|
|
inp.max_jerk = [dddx_max[0]] |
|
|
|
|
|
print('\t'.join(['t'] + [str(i) for i in range(otg.degrees_of_freedom)])) |
|
|
|
|
|
|
|
|
data.qr_list = [] |
|
|
data.x_list, data.dx_list, data.ddx_list, data.dddx_list = [], [], [], [] |
|
|
data.x_q_list, data.dx_q_list, data.ddx_q_list, data.dddx_q_list = [], [], [], [] |
|
|
data.dx_max_list, data.ddx_max_list, data.dddx_max_list = [], [], [] |
|
|
data.dx_min_list, data.ddx_min_list, data.dddx_min_list = [], [], [] |
|
|
data.e_pos_list_ruckig, data.e_rot_list_ruckig = [], [] |
|
|
data.x3d_ruckig = [] |
|
|
|
|
|
out_list = [] |
|
|
res = Result.Working |
|
|
|
|
|
s = time.time() |
|
|
|
|
|
if robot_pyn is None: |
|
|
sol = robot.ikine_LM(X_final.np, q0) |
|
|
q_final = sol.q |
|
|
J = robot.jacob0(q_final) |
|
|
else: |
|
|
q_final = robot_pyn.ik(X_final, q0, qlim=True, verbose=False) |
|
|
J = robot_pyn.jacobian(q_final) |
|
|
c = u@J |
|
|
Aeq = V2@J |
|
|
beq = np.zeros(5) |
|
|
c_ext = np.hstack((c,c,c,-c)) |
|
|
Aeq_ext=block_diag(Aeq,Aeq,Aeq,Aeq) |
|
|
beq_ext = b_eq=np.hstack((beq,beq,beq,beq)) |
|
|
x_min_ext = np.hstack((dq_min,ddq_min,dddq_min,ddq_min)) |
|
|
x_max_ext = np.hstack((dq_max,ddq_max,dddq_max,ddq_max)) |
|
|
q_ext = solve_lp(-c_ext, Aeq_ext, beq_ext, x_min_ext, x_max_ext) |
|
|
ds_final = (c@q_ext[:n_dof]) |
|
|
dds_final = (c@q_ext[n_dof:(2*n_dof)]) |
|
|
ddds_final = (c@q_ext[(2*n_dof):(3*n_dof)]) |
|
|
dds_min_final = (c@q_ext[(3*n_dof):(4*n_dof)]) |
|
|
|
|
|
|
|
|
|
|
|
db_old, dds_min_old, dds_max_old = 0, 0, 0 |
|
|
alpha_ds = 1.0 |
|
|
|
|
|
err_sum = 0 |
|
|
|
|
|
data.solved= True |
|
|
|
|
|
ruckig_current_accel, old_accel = [0], 0 |
|
|
|
|
|
|
|
|
if robot_pyn is None: |
|
|
sol = robot.ikine_LM(X_init.np, q0) |
|
|
q_c = sol.q |
|
|
else: |
|
|
q_c = robot_pyn.ik(X_init, q0, qlim=True, verbose=False) |
|
|
|
|
|
dq_c, ddq_c = np.zeros(7), np.zeros(7) |
|
|
dddq_c = np.zeros(7) |
|
|
t_sim = 0 |
|
|
t_sim_ruckig, t_old_ruckig = 0, -1 |
|
|
out_position = 0.0 |
|
|
out_velocity = 0.0 |
|
|
out_acceleration = 0.0 |
|
|
beq_filt = np.zeros(5) |
|
|
t0 = time.time() |
|
|
while res == Result.Working : |
|
|
|
|
|
if t_sim > 10000: |
|
|
print("ERROR: 10 sec simulation time exceeded! Stopping!") |
|
|
data.solved = False |
|
|
break |
|
|
|
|
|
if robot_pyn is None: |
|
|
J = robot.jacob0(q_c) |
|
|
X_c = robot.fkine(q_c) |
|
|
X_c = pin.SE3(X_c.R, X_c.t) |
|
|
J_dot = robot.jacob0_dot(q_c, dq_c) |
|
|
else: |
|
|
J = robot_pyn.jacobian(q_c) |
|
|
J_dot = robot_pyn.jacobian_dot(q_c, dq_c) |
|
|
X_c = robot_pyn.forward(q_c) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data.qr_list.append(q_c) |
|
|
data.x_q_list.append(u[:3]@(X_c.translation-X_init.translation)) |
|
|
data.x3d_ruckig.append(X_c.translation) |
|
|
data.dx_q_list.append(u@J@dq_c) |
|
|
data.ddx_q_list.append(u@J@ddq_c + u@J_dot@dq_c) |
|
|
data.dddx_q_list.append(u@J@dddq_c + u@J_dot@ddq_c) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if t_old_ruckig != t_sim_ruckig: |
|
|
if len(data.x_list) == 0: |
|
|
delta_x = (inp.current_position[0] )/dt_ruckig |
|
|
delta_dx = (inp.current_velocity[0])/dt_ruckig |
|
|
delta_ddx = (inp.current_acceleration[0])/dt_ruckig |
|
|
|
|
|
data.x_list.append([delta_x*dt]) |
|
|
data.dx_list.append([delta_dx*dt]) |
|
|
data.ddx_list.append([delta_ddx*dt]) |
|
|
data.dddx_list.append([delta_ddx]) |
|
|
else: |
|
|
|
|
|
delta_x = (inp.current_position[0] - data.x_list[-1][0])/dt_ruckig |
|
|
delta_dx = (inp.current_velocity[0] - data.dx_list[-1][0])/dt_ruckig |
|
|
delta_ddx = (inp.current_acceleration[0] - data.ddx_list[-1][0])/dt_ruckig |
|
|
data.x_list.append([data.x_list[-1][0] + delta_x*dt]) |
|
|
data.dx_list.append([data.dx_list[-1][0]+ delta_dx*dt]) |
|
|
data.ddx_list.append([data.ddx_list[-1][0] + delta_ddx*dt]) |
|
|
data.dddx_list.append([delta_ddx]) |
|
|
|
|
|
out_position = inp.current_position[0] |
|
|
out_velocity = inp.current_velocity[0] |
|
|
out_acceleration = inp.current_acceleration[0] |
|
|
|
|
|
t_old_ruckig = t_sim_ruckig |
|
|
else: |
|
|
|
|
|
data.x_list.append([data.x_list[-1][0] + delta_x*dt]) |
|
|
data.dx_list.append([data.dx_list[-1][0] + delta_dx*dt]) |
|
|
data.ddx_list.append([data.ddx_list[-1][0] + delta_ddx*dt]) |
|
|
data.dddx_list.append([delta_ddx]) |
|
|
|
|
|
if t_sim % n_ruckig == 0: |
|
|
if ds_final > 1e-1: ds_p=[ds_final] |
|
|
else: ds_p= [] |
|
|
if dds_final > 1e-1: dds_p=[dds_final] |
|
|
else: dds_p= [] |
|
|
if ddds_final > 1e-1: ddds_p=[ddds_final] |
|
|
else: ddds_p= [] |
|
|
if dds_min_final < -1e-1: dds_min_p=[dds_min_final] |
|
|
else: dds_min_p= [] |
|
|
|
|
|
|
|
|
c = u@J |
|
|
Aeq = V2@J |
|
|
try: |
|
|
c_ext = np.hstack((c,c,c,-c)) |
|
|
Aeq_ext=block_diag(Aeq,Aeq,Aeq,Aeq) |
|
|
|
|
|
|
|
|
beq_filt = -V2@J_dot@dq_c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
beq_ext = np.hstack((beq,-V2@J_dot@dq_c,-V2@J_dot@ddq_c,beq_filt)) |
|
|
|
|
|
x_min_ext = np.hstack((alpha_ds*dq_min,ddq_min,dddq_min,ddq_min)) |
|
|
x_max_ext = np.hstack((alpha_ds*dq_max,ddq_max,dddq_max,ddq_max)) |
|
|
q_ext = solve_lp(-c_ext, Aeq_ext, beq_ext, x_min_ext, x_max_ext) |
|
|
ds_p.append(c@q_ext[:n_dof]) |
|
|
dds_p.append(c@q_ext[n_dof:(2*n_dof)] + u@J_dot@dq_c) |
|
|
ddds_p.append(c@q_ext[(2*n_dof):(3*n_dof)] + u@J_dot@ddq_c) |
|
|
dds_min_p.append(c@q_ext[(3*n_dof):(4*n_dof)] + u@J_dot@dq_c) |
|
|
|
|
|
|
|
|
dt_to_zero = 1.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except: |
|
|
if verbose: print("except dds") |
|
|
|
|
|
beq = np.zeros(5) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
beq_filt = -V2@J_dot@dq_c |
|
|
try: |
|
|
ds_p.append(c@solve_lp(-c, A_eq=Aeq, b_eq=beq, x_min=dq_min, x_max=dq_max)) |
|
|
except: |
|
|
ds_p.append(ds_p[-1]) |
|
|
try: |
|
|
dds_p.append(c@solve_lp(-c, A_eq=Aeq, b_eq=-V2@J_dot@dq_c, x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
except: |
|
|
done = False |
|
|
for i in range(1,10): |
|
|
try: |
|
|
dds_p.append(c@solve_lp(-c, A_eq=Aeq, b_eq=-V2@J_dot@dq_c/i, x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
done = True |
|
|
break |
|
|
except: |
|
|
continue |
|
|
if not done: |
|
|
dds_p.append(dds_p[-1]) |
|
|
try: |
|
|
ddds_p.append(c@solve_lp(-c, A_eq=Aeq, b_eq=-V2@J_dot@ddq_c, x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c) |
|
|
except: |
|
|
ddds_p.append(ddds_p[-1]) |
|
|
try: |
|
|
dds_min_p.append(c@solve_lp(c, A_eq=Aeq, b_eq=beq_filt, x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
except: |
|
|
done = False |
|
|
for i in range(1,10): |
|
|
try: |
|
|
dds_min_p.append(c@solve_lp(c, A_eq=Aeq, b_eq=beq_filt/i, x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
done = True |
|
|
break |
|
|
except: |
|
|
continue |
|
|
if not done: |
|
|
dds_min_p.append(dds_min_p[-1]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data.dx_max_list.append(ds_p[-1]) |
|
|
data.ddx_max_list.append(dds_p[-1]) |
|
|
data.dddx_max_list.append(ddds_p[-1]) |
|
|
data.dx_min_list.append(-ds_p[-1]) |
|
|
data.ddx_min_list.append(dds_min_p[-1]) |
|
|
data.dddx_min_list.append(-ddds_p[-1]) |
|
|
|
|
|
if ds_p[-1]<=1e-4 : |
|
|
if verbose: print("Error - sinularity or infeasible position for ds") |
|
|
data = None |
|
|
return |
|
|
if dds_p[-1]<=1e-4: |
|
|
if verbose: print("Error - sinularity or infeasible position for dds") |
|
|
if stop_on_singular: |
|
|
data = None |
|
|
return |
|
|
else: |
|
|
dds_p[-1] = 0.05 |
|
|
if ddds_p[-1]<=1e-4: |
|
|
if verbose: print("Error - sinularity or infeasible position for ddds") |
|
|
if stop_on_singular: |
|
|
data = None |
|
|
return |
|
|
else: |
|
|
ddds_p[-1] = 0.05 |
|
|
|
|
|
if dds_min_p[-1]>=-1e-4: |
|
|
if verbose: print("Error - sinularity or infeasible position for dds_min") |
|
|
if stop_on_singular: |
|
|
data = None |
|
|
return |
|
|
else: |
|
|
dds_min_p[-1] = -0.05 |
|
|
|
|
|
|
|
|
if uptate_current_position: |
|
|
|
|
|
|
|
|
|
|
|
if np.abs(data.x_q_list[-1] - inp.target_position[0]) > 0.01: |
|
|
inp.current_position = [data.x_q_list[-1]] |
|
|
|
|
|
if t_sim % n_ruckig == 0: |
|
|
|
|
|
|
|
|
tmp_max_vel = inp.max_velocity[0] |
|
|
tmp_current_vel = inp.current_velocity[0] |
|
|
|
|
|
if calculate_limits: |
|
|
if override_acceleration: |
|
|
inp.current_acceleration = ruckig_current_accel |
|
|
|
|
|
clamped = False |
|
|
if calculate_limits: |
|
|
inp.max_velocity =[(ds_p[-1])] |
|
|
inp.max_acceleration=[(dds_p[-1])] |
|
|
inp.max_jerk=[(ddds_p[-1])] |
|
|
if clamp_min_accel: |
|
|
inp.min_acceleration=[np.max(dds_min_p)] |
|
|
else: |
|
|
inp.min_acceleration=[(dds_min_p[-1])] |
|
|
|
|
|
if clamp_velocity: |
|
|
if inp.current_velocity[0] > inp.max_velocity[0]: |
|
|
clamped = True |
|
|
inp.current_velocity = inp.max_velocity |
|
|
|
|
|
res = otg.update(inp, out) |
|
|
out.pass_to_input(inp) |
|
|
|
|
|
|
|
|
if calculate_limits: |
|
|
if clamped: |
|
|
inp.current_acceleration = [np.max([(inp.max_velocity[0] - tmp_max_vel)/dt_ruckig, inp.min_acceleration[0]])] |
|
|
|
|
|
|
|
|
if override_acceleration: |
|
|
ruckig_current_accel = inp.current_acceleration |
|
|
inp.current_acceleration = [(inp.current_velocity[0] - tmp_current_vel)/dt_ruckig] |
|
|
|
|
|
inp.current_acceleration = [(1-alpha)*inp.current_acceleration[0] + alpha*old_accel] |
|
|
old_accel = inp.current_acceleration[0] |
|
|
t_sim_ruckig = t_sim_ruckig + out.time; |
|
|
|
|
|
|
|
|
if 'acceleration' in qp_form: |
|
|
t_h = 0.01 |
|
|
if not scaled_qp_limits: |
|
|
ddq_ub = np.vstack( |
|
|
[ |
|
|
lims['ddq_max'], |
|
|
(t_h*lims['dddq_max'] + ddq_c).flatten(), |
|
|
((lims['dq_max'] - dq_c)/t_h).flatten(), |
|
|
(2*(lims['q_max'] - dq_c*t_h - q_c)/t_h**2).flatten() |
|
|
]).min(axis=0) |
|
|
ddq_lb = np.vstack( |
|
|
[ |
|
|
-lims['ddq_max'], |
|
|
(t_h*-lims['dddq_max'] + ddq_c).flatten(), |
|
|
((-lims['dq_max'] - dq_c)/t_h).flatten(), |
|
|
(2*(lims['q_min'] - dq_c*t_h - q_c)/t_h**2).flatten() |
|
|
]).max(axis=0) |
|
|
else: |
|
|
ddq_ub = np.vstack( |
|
|
[ |
|
|
ddq_max, |
|
|
(t_h*dddq_max + ddq_c).flatten(), |
|
|
((dq_max - dq_c)/t_h).flatten(), |
|
|
(2*(q_max - dq_c*t_h - q_c)/t_h**2).flatten() |
|
|
]).min(axis=0) |
|
|
ddq_lb = np.vstack( |
|
|
[ |
|
|
ddq_min, |
|
|
(t_h*dddq_min + ddq_c).flatten(), |
|
|
((dq_min - dq_c)/t_h).flatten(), |
|
|
(2*(q_min - dq_c*t_h - q_c)/t_h**2).flatten() |
|
|
]).max(axis=0) |
|
|
elif 'velocity' in qp_form: |
|
|
t_h = dt |
|
|
if not scaled_qp_limits: |
|
|
dq_ub = np.vstack( |
|
|
[ |
|
|
lims['dq_max'], |
|
|
(t_h*lims['ddq_max'] + dq_c).flatten(), |
|
|
((lims['q_max'] - q_c)/t_h).flatten(), |
|
|
(0.5*((t_h*5)**2)*lims['dddq_max'] + t_h*ddq_c + dq_c).flatten() |
|
|
] |
|
|
).min(axis=0) |
|
|
dq_lb = np.vstack( |
|
|
[ |
|
|
-lims['dq_max'], |
|
|
(t_h*-lims['ddq_max'] + dq_c).flatten(), |
|
|
((lims['q_min'] - q_c)/t_h).flatten(), |
|
|
((0.5*((t_h*5)**2)*-lims['dddq_max'] + t_h*ddq_c + dq_c).flatten()) |
|
|
] |
|
|
).max(axis=0) |
|
|
else: |
|
|
dq_ub = np.vstack( |
|
|
[ |
|
|
dq_max, |
|
|
(t_h*ddq_max + dq_c).flatten(), |
|
|
((q_max - q_c)/t_h).flatten(), |
|
|
(0.5*((t_h*5)**2)*dddq_max + t_h*ddq_c + dq_c).flatten() |
|
|
] |
|
|
).min(axis=0) |
|
|
dq_lb = np.vstack( |
|
|
[ |
|
|
dq_min, |
|
|
(t_h*ddq_min + dq_c).flatten(), |
|
|
((q_min - q_c)/t_h).flatten(), |
|
|
((0.5*((t_h*5)**2)*dddq_min + t_h*ddq_c + dq_c).flatten()) |
|
|
] |
|
|
).max(axis=0) |
|
|
|
|
|
|
|
|
c = u@J |
|
|
q_c_old = q_c.copy() |
|
|
dq_c_old = dq_c.copy() |
|
|
ddq_c_old = ddq_c.copy() |
|
|
|
|
|
if 'acceleration' in qp_form: |
|
|
|
|
|
ddx_des = data.ddx_list[-1]*u[:,None] |
|
|
ddx_des = ddx_des + Kd*(data.dx_list[-1]*u - J@dq_c_old)[:,None] |
|
|
|
|
|
|
|
|
|
|
|
X_dk = pin.SE3(X_init.rotation, X_init.translation+np.array(data.x_list[-1]*u[:3])) |
|
|
X_wa = pin.SE3(X_init.rotation, np.zeros(3)) |
|
|
X_rk = pin.SE3(X_c.rotation, X_c.translation) |
|
|
X_log = X_dk.actInv(X_rk) |
|
|
log_dk = pin.log6(X_log) |
|
|
err = (-(X_wa.toActionMatrix()@log_dk)[:,None]) |
|
|
err_sum = err_sum + err*dt |
|
|
ddx_des = ddx_des + Kp*err + Ki*err_sum |
|
|
ddx_des = ddx_des - (J_dot@dq_c_old)[:,None] |
|
|
grad = (q0-q_c_old) + 2*(-dq_c_old) |
|
|
if use_manip_grad: |
|
|
grad = manip_grad_w*robot.jacobm(q_c).reshape((-1,)) |
|
|
|
|
|
ddq_c = solve_qp(J,ddx_des, ddq_lb, ddq_ub, grad=-grad, reg_w=5*0.00001, solver='cvxopt') |
|
|
if ddq_c is None: |
|
|
print("No QP solution found") |
|
|
data.solved= False |
|
|
break |
|
|
|
|
|
dq_c = dq_c + ddq_c*dt |
|
|
q_c = np.clip(dq_c*dt + ddq_c*(dt**2)/2 + q_c, q_min,q_max) |
|
|
dq_c = np.clip(dq_c, dq_min, dq_max) |
|
|
dddq_c = (ddq_c - ddq_c_old)/dt |
|
|
|
|
|
elif 'velocity' in qp_form: |
|
|
|
|
|
dx_des = data.dx_list[-1]*u[:,None] |
|
|
X_dk = pin.SE3(X_init.rotation, X_init.translation+np.array(data.x_list[-1]*u[:3])) |
|
|
X_rk = pin.SE3(X_c.rotation, X_c.translation) |
|
|
X_log = X_dk.actInv(X_rk) |
|
|
log_dk = pin.log6(X_log) |
|
|
dx_des = dx_des + Kp/1000.0*(-(X_dk.toActionMatrix()@log_dk)[:,None]) |
|
|
|
|
|
grad = ((q_min+q_max)/2-q_c_old) + 0.1*(-dq_c_old) |
|
|
if use_manip_grad: |
|
|
grad = manip_grad_w*robot.jacobm(q_c).reshape((-1,)) |
|
|
|
|
|
dq_c = solve_qp(J, dx_des, dq_lb, dq_ub, grad=-grad, reg_w=5*0.00001, solver='quadprog') |
|
|
if dq_c is None: |
|
|
print("No QP solution found") |
|
|
data.solved= False |
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
if np.any(dq_c > dq_max) or np.any(dq_c < dq_min) : |
|
|
print("vel outside limits") |
|
|
ddq_c = (dq_c - dq_c_old)/dt |
|
|
if np.any(ddq_c > 1.01*ddq_max) or np.any(ddq_c < 1.01*ddq_min) : |
|
|
|
|
|
print("accel outside limits") |
|
|
dddq_c = (ddq_c - ddq_c_old)/dt |
|
|
if np.any(dddq_c > 1.5*dddq_max) or np.any(dddq_c < 1.5*dddq_min) : |
|
|
|
|
|
print("jerk outside limits") |
|
|
q_c = np.clip(dq_c_old*dt + ddq_c*(dt**2)/2 + q_c_old, q_min,q_max) |
|
|
|
|
|
|
|
|
t_sim = t_sim+1 |
|
|
|
|
|
|
|
|
data.e_pos_list_ruckig.append(np.linalg.norm((X_c.translation-X_init.translation-np.array(data.x_list[-1]*u[:3])))) |
|
|
data.e_rot_list_ruckig.append(np.linalg.norm(pin.log3(X_init.rotation.T@X_c.rotation))) |
|
|
|
|
|
print(f'Calculation duration: {time.time()-s} [s]') |
|
|
data.t_ruckig = np.array(range(0,len(data.x_list)))*dt |
|
|
print(f'Trajectory duration: {data.t_ruckig[-1]:0.4f} [s]') |
|
|
return data |
|
|
|
|
|
|
|
|
|
|
|
def rand_num(delta): |
|
|
return np.random.rand()*2*delta - delta |
|
|
|
|
|
def find_random_poses_with_distance(distance, robot, q0, iterations = 10, joint_limits=True, verify_line = False , n_waypoints = 10 ,angle =np.pi/6): |
|
|
X_r = robot.fkine(q0) |
|
|
found = False |
|
|
while not found: |
|
|
print("searching") |
|
|
X_init = None |
|
|
while X_init is None or np.linalg.norm(robot.fkine(robot.ikine_LM(X_init, q0, joint_limits=joint_limits).q).t-X_init.t) > 1e-5: |
|
|
X_init = SE3(np.random.rand(1,3)*distance-0.5*distance+np.array([0.5,0,0.4]))*SE3(SO3(X_r.R))*SE3(SO3.Rx(rand_num(angle)))*SE3(SO3.Ry(rand_num(angle))) |
|
|
|
|
|
X_final = None |
|
|
i = 0 |
|
|
while (X_final is None or np.linalg.norm(robot.fkine(robot.ikine_LM(X_final, q0, joint_limits=joint_limits).q).t-X_final.t) > 1e-5) and i <= iterations: |
|
|
print("not attainable final") |
|
|
v= np.random.rand(3)*2-1 |
|
|
v = v/np.linalg.norm(v)*distance |
|
|
X_final = SE3(X_init.t + v)*SE3(SO3(X_init.R)) |
|
|
i = i+1 |
|
|
if i < iterations: |
|
|
found = True |
|
|
|
|
|
if verify_line: |
|
|
q_line = [ robot.ikine_LM(X_init,q0,joint_limits=joint_limits).q ] |
|
|
X_i = np.linspace(X_init.t, X_final.t, n_waypoints) |
|
|
print(n_waypoints) |
|
|
for x in X_i[1:]: |
|
|
T = SE3(x)*SE3(SO3(X_init.R)) |
|
|
sol = robot.ikine_LM(T,q_line[-1],joint_limits=joint_limits) |
|
|
X_found = robot.fkine(sol.q) |
|
|
if np.linalg.norm(robot.fkine(robot.ikine_LM(X_found, joint_limits=joint_limits).q).t-T.t) > 1e-5: |
|
|
break |
|
|
q_line.append(sol.q) |
|
|
|
|
|
if len(q_line) < len(X_i): |
|
|
print("staright line not possible") |
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
return X_init, X_final, q_line |
|
|
|
|
|
|
|
|
def find_random_poses_with_distance_pinocchio(distance, robot, q0, iterations = 10, joint_limits=True, verify_line = False , n_waypoints = 10,angle =np.pi/6): |
|
|
X_r = robot.forward(q0) |
|
|
found = False |
|
|
while not found: |
|
|
print("searching") |
|
|
X_init = None |
|
|
while X_init is None or np.linalg.norm(robot.forward(robot.ik(X_init, q0, qlim=joint_limits, verbose=False)).translation-X_init.translation) > 1e-3: |
|
|
X_init = pin.SE3(X_r.rotation, (np.random.rand(1,3)*distance-0.5*distance+np.array([0.5,0,0.4])).reshape((3,))) |
|
|
x,y = rand_num(angle),rand_num(angle) |
|
|
X_init = X_init*pin.SE3(pin.rpy.rpyToMatrix(x, y,0), np.zeros(3)) |
|
|
|
|
|
X_final = None |
|
|
i = 0 |
|
|
while (X_final is None or np.linalg.norm(robot.forward(robot.ik(X_final, q0, qlim=joint_limits, verbose=False)).translation-X_final.translation) > 1e-3) and i <= iterations: |
|
|
print("not attainable final") |
|
|
v= np.random.rand(3)*2-1 |
|
|
v = v/np.linalg.norm(v)*distance |
|
|
X_final = pin.SE3(X_init.rotation, X_init.translation + v) |
|
|
i = i+1 |
|
|
|
|
|
if i < iterations: |
|
|
found = True |
|
|
|
|
|
if verify_line: |
|
|
print("verify straitgh line") |
|
|
q_line = [ robot.ik(X_init,q0,qlim=joint_limits, verbose=False) ] |
|
|
X_i = np.linspace(X_init.translation, X_final.translation, n_waypoints) |
|
|
print(n_waypoints) |
|
|
for x in X_i[1:]: |
|
|
T = pin.SE3(X_init.rotation, x) |
|
|
q = robot.ik(T, q_line[-1], qlim=joint_limits, verbose=False) |
|
|
X_found = robot.forward(q) |
|
|
if np.linalg.norm(robot.forward(robot.ik(X_found, qlim=joint_limits, verbose=False)).translation-T.translation) > 1e-3: |
|
|
print(robot.forward(robot.ik(X_found, qlim=joint_limits, verbose=False)).translation, T.translation) |
|
|
break |
|
|
q_line.append(q) |
|
|
|
|
|
if len(q_line) < len(X_i): |
|
|
print("staright line not possible") |
|
|
found = False |
|
|
continue |
|
|
|
|
|
return X_init, X_final, q_line |
|
|
|
|
|
|
|
|
def simulate_toppra(X_init, X_final, ts, qs, qds, qdds, q0, lims, scale, robot = None, options=None , robot_pyn = None ): |
|
|
s = time.time() |
|
|
data = TrajData() |
|
|
|
|
|
print('simulating trajectory') |
|
|
|
|
|
|
|
|
if type(X_init) == np.ndarray: |
|
|
X_init = pin.SE3(X_init[:3,:3], X_init[:3,3]) |
|
|
X_final = pin.SE3(X_final[:3,:3], X_final[:3,3]) |
|
|
elif type(X_init) == pin.SE3: |
|
|
pass |
|
|
elif SPATIAL_MATH and (type(X_init) == spatialmath.pose3d.SE3): |
|
|
X_init = pin.SE3(X_init.R, X_init.t) |
|
|
X_final = pin.SE3(X_final.R, X_final.t) |
|
|
else: |
|
|
print("Unknown type of X_init") |
|
|
return |
|
|
|
|
|
u = np.zeros(6) |
|
|
u[:3] = X_final.translation-X_init.translation |
|
|
u = u/np.linalg.norm(u) |
|
|
|
|
|
|
|
|
scale = float(scale) |
|
|
dq_max = scale*lims['dq_max'] |
|
|
ddq_max = scale*lims['ddq_max'] |
|
|
dddq_max = scale*lims['dddq_max'] |
|
|
q_min, q_max = lims['q_min'], lims['q_max'] |
|
|
dq_min = -dq_max |
|
|
ddq_min = -ddq_max |
|
|
dddq_min = -dddq_max |
|
|
|
|
|
if options is not None and 'calculate_limits' in options.keys(): |
|
|
calculate_limits = options['calculate_limits'] |
|
|
else: |
|
|
calculate_limits = True |
|
|
|
|
|
|
|
|
if calculate_limits: |
|
|
U,S,V = np.linalg.svd(u[:,None]) |
|
|
V2 = U[:,1:].T |
|
|
|
|
|
data.ds_max_list=[] |
|
|
data.dds_max_list=[] |
|
|
data.ddds_max_list=[] |
|
|
data.ds_min_list=[] |
|
|
data.dds_min_list=[] |
|
|
data.ddds_min_list=[] |
|
|
|
|
|
data.x3d_top = [] |
|
|
data.x_top = [] |
|
|
data.dx_top = [] |
|
|
data.ddx_top = [] |
|
|
data.dddx_top = [] |
|
|
data.qr_list = [] |
|
|
|
|
|
U,S,V = np.linalg.svd(u[:3,None]) |
|
|
V23 = U[:,1:].T |
|
|
data.e_pos_list, data.e_rot_list = [], [] |
|
|
|
|
|
q_c = qs[0] |
|
|
|
|
|
if robot_pyn is not None: |
|
|
dq_c, ddq_c, dddq_c = np.zeros(robot_pyn.n), np.zeros(robot_pyn.n), np.zeros(robot_pyn.n) |
|
|
elif robot is not None: |
|
|
dq_c, ddq_c, dddq_c = np.zeros(robot.n), np.zeros(robot.n), np.zeros(robot.n) |
|
|
else: |
|
|
print("No robot model provided") |
|
|
return |
|
|
|
|
|
t_last = 0 |
|
|
for t, q,qd,qdd in zip(ts, qs,qds,qdds): |
|
|
|
|
|
|
|
|
if robot_pyn is not None: |
|
|
X_c = robot_pyn.forward(q_c) |
|
|
X_dc = robot_pyn.forward(q) |
|
|
J =robot_pyn.jacobian(q_c) |
|
|
J_dot = robot_pyn.jacobian_dot(q_c,dq_c) |
|
|
x_t = X_c.translation |
|
|
data.x3d_top.append(x_t) |
|
|
data.x_top.append(u[:3]@(x_t-X_init.translation)) |
|
|
c = u@J |
|
|
c_dot = u@J_dot |
|
|
data.dx_top.append(c@dq_c) |
|
|
data.ddx_top.append(c@ddq_c + c_dot@dq_c) |
|
|
data.dddx_top.append(c@dddq_c+ c_dot@ddq_c) |
|
|
|
|
|
data.qr_list.append(q_c) |
|
|
|
|
|
data.e_pos_list.append(np.linalg.norm((X_c.translation-X_dc.translation))) |
|
|
|
|
|
data.e_rot_list.append(np.linalg.norm(pin.log3(X_init.rotation.T@X_c.rotation))) |
|
|
|
|
|
elif robot is not None: |
|
|
X_c = robot.fkine(q_c) |
|
|
X_dc = robot.fkine(q) |
|
|
J =robot.jacob0(q_c) |
|
|
J_dot = robot.jacob0_dot(q_c,dq_c) |
|
|
|
|
|
x_t = X_c.t |
|
|
data.x3d_top.append(x_t) |
|
|
data.x_top.append(u[:3]@(x_t-X_init.translation)) |
|
|
c = u@J |
|
|
c_dot = u@J_dot |
|
|
data.dx_top.append(c@dq_c) |
|
|
data.ddx_top.append(c@ddq_c + c_dot@dq_c) |
|
|
data.dddx_top.append(c@dddq_c+ c_dot@ddq_c) |
|
|
|
|
|
data.qr_list.append(q_c) |
|
|
|
|
|
data.e_pos_list.append(np.linalg.norm((X_c.t-X_dc.t))) |
|
|
|
|
|
data.e_rot_list.append(np.linalg.norm(pin.log3(X_init.rotation.T@X_c.R))) |
|
|
|
|
|
dt = t - t_last |
|
|
t_last = t |
|
|
if not dt: |
|
|
dt =0.001 |
|
|
|
|
|
|
|
|
q_c = q |
|
|
q_c = np.clip(q_c, q_min, q_max) |
|
|
|
|
|
dq_c_old = dq_c |
|
|
ddq_c_old = ddq_c |
|
|
|
|
|
|
|
|
dq_c = qd |
|
|
dq_c = np.clip(dq_c, dq_min, dq_max) |
|
|
|
|
|
ddq_c = qdd |
|
|
|
|
|
|
|
|
ddq_c = np.clip(ddq_c, ddq_min, ddq_max) |
|
|
|
|
|
dddq_c = (ddq_c - ddq_c_old)/dt |
|
|
|
|
|
|
|
|
|
|
|
if calculate_limits: |
|
|
Aeq = V2@J |
|
|
beq = np.zeros(5) |
|
|
try: |
|
|
data.ds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=beq, x_min=dq_min, x_max=dq_max)) |
|
|
data.dds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=-V2@J_dot@dq_c, x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
data.ddds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=-V2@J_dot@ddq_c, x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c) |
|
|
data.ds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=beq, x_min=dq_min, x_max=dq_max)) |
|
|
data.dds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=-V2@J_dot@dq_c, x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
data.ddds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=-V2@J_dot@ddq_c, x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c) |
|
|
except: |
|
|
print("except dds") |
|
|
try: |
|
|
data.ds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dq_min, x_max=dq_max)) |
|
|
data.dds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
data.ddds_max_list.append(c@solve_lp(-c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c) |
|
|
data.ds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dq_min, x_max=dq_max)) |
|
|
data.dds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=ddq_min, x_max=ddq_max) + u@J_dot@dq_c) |
|
|
data.ddds_min_list.append(c@solve_lp(c, A_eq=Aeq, b_eq=np.zeros(5), x_min=dddq_min, x_max=dddq_max) + u@J_dot@ddq_c) |
|
|
except: |
|
|
print("except dds 2") |
|
|
data.ds_max_list.append(data.ds_max_list[-1]) |
|
|
data.dds_max_list.append(data.dds_max_list[-1]) |
|
|
data.ddds_max_list.append(data.ddds_max_list[-1]) |
|
|
data.ds_min_list.append(data.ds_min_list[-1]) |
|
|
data.dds_min_list.append(data.dds_min_list[-1]) |
|
|
data.ddds_min_list.append(data.ddds_min_list[-1]) |
|
|
data.t_toppra = ts |
|
|
print('TOPPRA trajecotry simulation time',time.time() - s) |
|
|
print(f'Trajectory duration: {data.t_toppra[-1]:0.4f} [s]') |
|
|
return data |
|
|
|
|
|
|
|
|
import toppra as ta |
|
|
import toppra.constraint as constraint |
|
|
import toppra.algorithm as algo |
|
|
|
|
|
def caclulate_toppra_trajectory(X_init, X_final, q0, lims, scale, d_waypoint, robot=None, robot_pyn=None, data=None): |
|
|
s = time.time() |
|
|
|
|
|
|
|
|
|
|
|
if robot_pyn is not None: |
|
|
|
|
|
if type(X_init) == np.ndarray: |
|
|
X_init = pin.SE3(X_init[:3,:3], X_init[:3,3]) |
|
|
X_final = pin.SE3(X_final[:3,:3], X_final[:3,3]) |
|
|
elif type(X_init) == pin.SE3: |
|
|
pass |
|
|
elif SPATIAL_MATH and (type(X_init) == spatialmath.pose3d.SE3): |
|
|
X_init = pin.SE3(X_init.R, X_init.t) |
|
|
X_final = pin.SE3(X_final.R, X_final.t) |
|
|
else: |
|
|
print("Unknown type of X_init") |
|
|
return |
|
|
|
|
|
|
|
|
dq_max = scale*lims['dq_max'] |
|
|
ddq_max = scale*lims['ddq_max'] |
|
|
|
|
|
|
|
|
if robot_pyn is not None: |
|
|
d = np.linalg.norm(X_final.translation-X_init.translation) |
|
|
else: |
|
|
d = np.linalg.norm(X_final.t-X_init.t) |
|
|
|
|
|
n_waypoints = int(d/d_waypoint) |
|
|
|
|
|
|
|
|
if data is not None: |
|
|
print('using provided data') |
|
|
x_np = np.array(data.x_list) |
|
|
x_v = np.linspace(0,x_np[-1], n_waypoints) |
|
|
inds = [] |
|
|
for x_wp in x_v: |
|
|
inds.append(np.where(x_np >= x_wp)[0][0]) |
|
|
q_line = [data.qr_list[int(i)] for i in inds] |
|
|
|
|
|
else: |
|
|
if robot is not None: |
|
|
|
|
|
X_i = np.linspace(X_init.t,X_final.t,n_waypoints) |
|
|
q_line = [ robot.ikine_LM(X_init, q0).q ] |
|
|
for x in X_i[1:]: |
|
|
T = SE3(x)*SE3(SO3(X_init.R)) |
|
|
sol = robot.ikine_LM(T,q_line[-1]) |
|
|
q_line.append(sol.q) |
|
|
else: |
|
|
|
|
|
X_i = np.linspace(X_init.translation,X_final.translation,n_waypoints) |
|
|
q_line = [ robot_pyn.ik(X_init, q0, qlim=True, verbose=False) ] |
|
|
for x in X_i[1:]: |
|
|
T= pin.SE3(X_init.rotation, x) |
|
|
q_line.append(robot_pyn.ik(T,q_line[-1], qlim=True, verbose=False)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s1 = time.time() |
|
|
|
|
|
ss = np.linspace(0,1,len(q_line)) |
|
|
path = ta.SplineInterpolator(ss, q_line) |
|
|
pc_vel = constraint.JointVelocityConstraint(dq_max) |
|
|
pc_acc = constraint.JointAccelerationConstraint(ddq_max) |
|
|
instance = algo.TOPPRA([pc_vel, pc_acc], path, parametrizer="ParametrizeConstAccel") |
|
|
jnt_traj = instance.compute_trajectory() |
|
|
|
|
|
ts_sample = np.arange(0, jnt_traj.duration, 0.001) |
|
|
qs_sample = jnt_traj(ts_sample) |
|
|
qds_sample = jnt_traj(ts_sample, 1) |
|
|
qdds_sample = jnt_traj(ts_sample, 2) |
|
|
|
|
|
|
|
|
|
|
|
return ts_sample, qs_sample, qds_sample, qdds_sample |
|
|
|
|
|
|