diff --git a/python/smc/control/cartesian_space/cartesian_space_trajectory_following.py b/python/smc/control/cartesian_space/cartesian_space_trajectory_following.py index 280cb399b0a07d0c8ae7b00c41eb41093ce50661..5b8b6772fc7b77626568d717644030f52d336654 100644 --- a/python/smc/control/cartesian_space/cartesian_space_trajectory_following.py +++ b/python/smc/control/cartesian_space/cartesian_space_trajectory_following.py @@ -1,5 +1,6 @@ from smc.control.control_loop_manager import ControlLoopManager from smc.multiprocessing.process_manager import ProcessManager +from smc.robots.interfaces.mobile_base_interface import MobileBaseInterface from smc.robots.interfaces.single_arm_interface import SingleArmInterface from smc.control.controller_templates.path_following_template import ( PathFollowingFromPlannerCtrllLoopTemplate, @@ -8,6 +9,7 @@ from smc.control.cartesian_space.ik_solvers import getIKSolver, dampedPseudoinve from smc.path_generation.path_math.path2d_to_6d import ( path2D_to_SE3, ) +from smc.path_generation.path_math.path_to_trajectory import path2D_to_trajectory2D from functools import partial import pinocchio as pin @@ -19,9 +21,9 @@ import types def cartesianPathFollowingControlLoop( + rot_x: float, ik_solver: Callable[[np.ndarray, np.ndarray], np.ndarray], path: list[pin.SE3] | np.ndarray, - rot_x: float, args: Namespace, robot: SingleArmInterface, t: int, @@ -35,12 +37,19 @@ def cartesianPathFollowingControlLoop( # TODO: refactor this horror out of here if type(path) == np.ndarray: + # TODO: this would be cool but i can't unfortunatelly + # velocity = args.max_v_percentage + # traj = path2D_to_trajectory2D(args, path, velocity) + # path = path2D_to_SE3(traj[:, :2], 0.0, rot_x) path = path2D_to_SE3(path[:, :2], 0.0, rot_x) # TODO: arbitrary bs, read a book and redo this # NOTE: assuming the first path point coincides with current pose SEerror = robot.T_w_e.actInv(path[1]) - # V_path = pin.log6(path[0].actInv(path[1])).vector - err_vector = pin.log6(SEerror).vector # + V_path + err_vector = pin.log6(SEerror).vector + if np.linalg.norm(err_vector) < 0.2: + V_path = 5 * pin.log6(path[1].actInv(path[2])).vector + err_vector += V_path + err_vector[3:] = err_vector[3:] * 2 J = robot.getJacobian() v_cmd = ik_solver(J, err_vector) @@ -60,29 +69,35 @@ def cartesianPathFollowingControlLoop( if t % int(np.ceil(args.ctrl_freq / 25)) == 0: robot.visualizer_manager.sendCommand({"frame_path": path[:20]}) - return v_cmd, {}, {} + return ( + v_cmd, + {}, + {"err_vec_ee": err_vector}, + ) def cartesianPathFollowingWithPlanner( args: Namespace, robot: SingleArmInterface, path_planner: ProcessManager | types.FunctionType, + x_rot: float, run=True, ) -> None | ControlLoopManager: ik_solver = getIKSolver(args, robot) get_position = lambda robot: robot.T_w_e.translation[:2] + loop = partial(cartesianPathFollowingControlLoop, x_rot) controlLoop = partial( PathFollowingFromPlannerCtrllLoopTemplate, path_planner, get_position, ik_solver, - cartesianPathFollowingControlLoop, + loop, args, robot, ) log_item = { - "qs": np.zeros(robot.model.nq), - "dqs": np.zeros(robot.model.nv), + "qs": np.zeros(robot.nq), + "dqs": np.zeros(robot.nv), "err_vec_ee": np.zeros(6), } save_past_item = {} diff --git a/python/smc/path_generation/path_math/path2d_to_6d.py b/python/smc/path_generation/path_math/path2d_to_6d.py index 5adcce9c23af09c9dd597eb6017b00b8da4da7bc..64d893de48c666ee05bdd11896f6808b5d3d05e7 100644 --- a/python/smc/path_generation/path_math/path2d_to_6d.py +++ b/python/smc/path_generation/path_math/path2d_to_6d.py @@ -25,8 +25,8 @@ def path2D_to_SE3( y_diff = y_i_plus_1 - y_i # elementwise arctan2 # should be y first, then x - # thetas = np.arctan2(y_diff, x_diff) - thetas = np.arctan2(x_diff, y_diff) + thetas = np.arctan2(y_diff, x_diff) + # thetas = np.arctan2(x_diff, y_diff) ###################################### # construct SE3 from SE2 reference # @@ -44,15 +44,16 @@ def path2D_to_SE3( # [0.0, 0.0, -1.0], # ] # ) - rotation = np.array( - [ - [np.cos(thetas[i]), -np.sin(thetas[i]), 0.0], - [np.sin(thetas[i]), np.cos(thetas[i]), 0.0], - [0.0, 0.0, 1.0], - ] - ) - rot_mat_x = pin.rpy.rpyToMaxtrix(rox_t, 0.0, 0.0) - rotation = rot_mat_x @ rotation + # rotation = np.array( + # [ + # [np.cos(thetas[i]), -np.sin(thetas[i]), 0.0], + # [np.sin(thetas[i]), np.cos(thetas[i]), 0.0], + # [0.0, 0.0, 1.0], + # ] + # ) + rotation = pin.rpy.rpyToMatrix(0.0, 0.0, thetas[i]) + rot_mat_x = pin.rpy.rpyToMatrix(rot_x, 0.0, 0.0) + rotation = rotation @ rot_mat_x # rotation = pin.rpy.rpyToMatrix(0.0, 0.0, thetas[i]) # rotation = pin.rpy.rpyToMatrix(np.pi / 2, np.pi / 2, 0.0) @ rotation translation = np.array([path2D[i][0], path2D[i][1], path_height]) diff --git a/python/smc/robots/interfaces/whole_body_dual_arm_interface.py b/python/smc/robots/interfaces/whole_body_dual_arm_interface.py index 9ab517bf074d6fb56ae5fc550ffdaca47bad654c..231a852274ad6fcdb2ced62a0bde4686d4cee926 100644 --- a/python/smc/robots/interfaces/whole_body_dual_arm_interface.py +++ b/python/smc/robots/interfaces/whole_body_dual_arm_interface.py @@ -166,14 +166,13 @@ class DualArmWholeBodyInterface(DualArmInterface, MobileBaseInterface): if self._mode == self.control_mode.left_arm_only: return J_left_with_base[:, 3:] - # NOTE: the base jacobian can be extracted from either left or right frame - - # since it's a body jacobian both have to be the same at the base. - # for efficiency of course it would be best to construct it in place, - # but who cares if it runs on time either way. + # NOTE: for some reason this is necessary as the J_left_with_base does not produce what i want + # ALSO, the assumption is that the error is given in the body frame (like all others) if self._mode == self.control_mode.base_only: J_base = np.zeros((6, 3)) - J_base[:2, :2] = self.T_w_b.rotation[:2, :2] - J_base[5, 2] = 1 + J_base[0, 0] = 1.0 + J_base[1, 1] = 1.0 + J_base[5, 2] = 1.0 return J_base # return J_left_with_base[:, :3]