From 0e68e701d4f66732fc77419d957a4fc33b2323b9 Mon Sep 17 00:00:00 2001 From: m-guberina <gubi.guberina@gmail.com> Date: Sun, 14 Jan 2024 19:32:49 +0100 Subject: [PATCH] put in todos --- python/examples/pushing_via_friction_cones.py | 3 + python/examples/test_gripper.py | 177 ++++++++++++++++++ .../__pycache__/managers.cpython-310.pyc | Bin 7289 -> 7289 bytes .../basics/__pycache__/basics.cpython-310.pyc | Bin 1125 -> 1156 bytes .../clik_point_to_point.cpython-310.pyc | Bin 4777 -> 4959 bytes .../__pycache__/logging_utils.cpython-310.pyc | Bin 1369 -> 1369 bytes .../ur_simple_control/util/robotiq_gripper.py | 111 +++++++---- .../__pycache__/make_run.cpython-310.pyc | Bin 2727 -> 2727 bytes .../InverseKinematics.cpython-310.pyc | Bin 4919 -> 4919 bytes .../__pycache__/drawing.cpython-310.pyc | Bin 1443 -> 1443 bytes .../drawing_for_anim.cpython-310.pyc | Bin 1239 -> 1239 bytes .../__pycache__/follow_curve.cpython-310.pyc | Bin 2382 -> 2382 bytes .../__pycache__/forw_kinm.cpython-310.pyc | Bin 11455 -> 11455 bytes .../__pycache__/inv_kinm.cpython-310.pyc | Bin 6584 -> 6584 bytes .../joint_as_hom_mat.cpython-310.pyc | Bin 3448 -> 3448 bytes .../__pycache__/utils.cpython-310.pyc | Bin 1481 -> 1481 bytes .../webots_api_helper_funs.cpython-310.pyc | Bin 4122 -> 4122 bytes 17 files changed, 258 insertions(+), 33 deletions(-) create mode 100644 python/examples/pushing_via_friction_cones.py create mode 100644 python/examples/test_gripper.py diff --git a/python/examples/pushing_via_friction_cones.py b/python/examples/pushing_via_friction_cones.py new file mode 100644 index 0000000..e4405ac --- /dev/null +++ b/python/examples/pushing_via_friction_cones.py @@ -0,0 +1,3 @@ +# TODO: +# implement the zoe paper basically +# why? just to see how well it works diff --git a/python/examples/test_gripper.py b/python/examples/test_gripper.py new file mode 100644 index 0000000..b23d385 --- /dev/null +++ b/python/examples/test_gripper.py @@ -0,0 +1,177 @@ +# just import everything +import pinocchio as pin +import numpy as np +import matplotlib.pyplot as plt +import copy +import argparse +import time +from functools import partial +from ur_simple_control.util.get_model import get_model +from ur_simple_control.visualize.visualize import plotFromDict +from ur_simple_control.util.draw_path import drawPath +from ur_simple_control.managers import ControlLoopManager, RobotManager +# needed to access some functions directly, +# TODO: hide this for later use obviously +from ur_simple_control.util.robotiq_gripper import RobotiqGripper + +# TODO have a generic get_args function +# that just has all of them somewhere in utils +# so that i don't have to copy-paste this around +# for simple stuff like this gripper test +def get_args(): + parser = argparse.ArgumentParser(description='Run closed loop inverse kinematics \ + of various kinds. Make sure you know what the goal is before you run!', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('--simulation', action=argparse.BooleanOptionalAction, + help="whether you are running the UR simulator", default=False) + parser.add_argument('--pinocchio-only', action=argparse.BooleanOptionalAction, + help="whether you want to just integrate with pinocchio", default=False) + parser.add_argument('--visualize', action=argparse.BooleanOptionalAction, + help="whether you want to visualize with gepetto, but NOTE: not implemented yet", default=False) + parser.add_argument('--gripper', action=argparse.BooleanOptionalAction, \ + help="whether you're using the gripper", default=True) + parser.add_argument('--goal-error', type=float, \ + help="the final position error you are happy with", default=1e-2) + parser.add_argument('--max-iterations', type=int, \ + help="maximum allowable iteration number (it runs at 500Hz)", default=100000) + parser.add_argument('--acceleration', type=float, \ + help="robot's joints acceleration. scalar positive constant, max 1.7, and default 0.4. \ + BE CAREFUL WITH THIS. the urscript doc says this is 'lead axis acceleration'.\ + TODO: check what this means", default=0.3) + parser.add_argument('--speed-slider', type=float,\ + help="cap robot's speed with the speed slider \ + to something between 0 and 1, 0.5 by default \ + BE CAREFUL WITH THIS.", default=0.5) + parser.add_argument('--tikhonov-damp', type=float, \ + help="damping scalar in tiknohov regularization", default=1e-3) + # TODO add the rest + parser.add_argument('--clik-controller', type=str, \ + help="select which click algorithm you want", \ + default='dampedPseudoinverse', choices=['dampedPseudoinverse', 'jacobianTranspose']) + # maybe you want to scale the control signal + parser.add_argument('--controller-speed-scaling', type=float, \ + default='1.0', help='not actually_used atm') + + args = parser.parse_args() + if args.gripper and args.simulation: + raise NotImplementedError('Did not figure out how to put the gripper in \ + the simulation yet, sorry :/ . You can have only 1 these flags right now') + return args + + + +# TODO: when this makes some sense, +# integrate it into the RobotManager class +# let's call the gripper's position x for now +# then velocity is xd and acceleration is xdd +# TODO ALSO a problem: +# you're supposed to send this at 125Hz, not 500! +# but let's first try 500 and see what happens. +# if there will be problems, implement handling that into the +# controlLoop manager. count some seconds there, or have a different +# thread for the gripper (will be painfull, try getting +# away with 100Hz since that's a multiple of 500, no need +# to overengineer if it isn't necessary) +# TODO: add control frequency as a parameter to controlLoop +def gripperPositionControlLoop(robot, clik_controller, i, past_data): + breakFlag = False + log_item = {} + + # let's start simple: + # send position command, read as it goes (essential if you want + # to have a closed-loop system) + x_goal = robot.gripper.get_min_position() # or whatever really + # speed is in [0,255] + xd = 10 + # force is in [0,255] - acts while gripping I guess + F_x= 10 + # you'll need to pass some kind of a flag here + robot.gripper.move(x_goal, xd, F_x) + # wait until not moving + cur_obj = self._get_var(self.OBJ) + # TODO: this can't actually be in this control loop form + # so TODO: make it separate function for now, then a controlLoop? + # also NOTE: this is code straight from the RobotiqGripper class + while RobotiqGripper.ObjectStatus(cur_obj) == RobotiqGripper.ObjectStatus.MOVING: + cur_obj = robot.gripper._get_var(self.OBJ) + print(cur_obj) + +# log_item['x'] = x.reshape((,)) +# log_item['xd'] = xd.reshape((,)) +# log_item['xdd'] = xdd.reshape((,)) + return breakFlag, {}, log_item + + +# TODO: implement via hacks +def gripperLinearSlipControlLoop(robot, clik_controller, i, past_data): + breakFlag = False + log_item = {} + + # let's start simple: + # send position command, read as it goes (essential if you want + # to have a closed-loop system) + x_goal = robot.gripper.get_min_position() # or whatever really + # speed is in [0,255] + xd = 10 + # force is in [0,255] - acts while gripping I guess + F_x= 10 + # you'll need to pass some kind of a flag here + robot.gripper.move(x_goal, xd, F_x) + # wait until not moving + cur_obj = self._get_var(self.OBJ) + # TODO: this can't actually be in this control loop form + # so TODO: make it separate function for now, then a controlLoop? + # also NOTE: this is code straight from the RobotiqGripper class + while RobotiqGripper.ObjectStatus(cur_obj) == RobotiqGripper.ObjectStatus.MOVING: + cur_obj = robot.gripper._get_var(self.OBJ) + print(cur_obj) + +# log_item['x'] = x.reshape((,)) +# log_item['xd'] = xd.reshape((,)) +# log_item['xdd'] = xdd.reshape((,)) + return breakFlag, {}, log_item + +# TODO: implement as per yiannis' paper +def gripperTorsionalSlipControlLoop(robot, clik_controller, i, past_data): + breakFlag = False + log_item = {} + + # let's start simple: + # send position command, read as it goes (essential if you want + # to have a closed-loop system) + x_goal = robot.gripper.get_min_position() # or whatever really + # speed is in [0,255] + xd = 10 + # force is in [0,255] - acts while gripping I guess + F_x= 10 + # you'll need to pass some kind of a flag here + robot.gripper.move(x_goal, xd, F_x) + # wait until not moving + cur_obj = self._get_var(self.OBJ) + # TODO: this can't actually be in this control loop form + # so TODO: make it separate function for now, then a controlLoop? + # also NOTE: this is code straight from the RobotiqGripper class + while RobotiqGripper.ObjectStatus(cur_obj) == RobotiqGripper.ObjectStatus.MOVING: + cur_obj = robot.gripper._get_var(self.OBJ) + print(cur_obj) + +# log_item['x'] = x.reshape((,)) +# log_item['xd'] = xd.reshape((,)) +# log_item['xdd'] = xdd.reshape((,)) + return breakFlag, {}, log_item + + +if __name__ == "__main__": + args = get_args() + robot = RobotManager(args) + controlLoop = partial(gripperPositionControlLoop, robot, clik_controller) + log_dict = { + 'x' : np.zeros((args.max_iterations, 1)), + 'xd' : np.zeros((args.max_iterations, 1)), + 'xdd' : np.zeros((args.max_iterations, 1)), + } + # we're not using any past data or logging, hence the empty arguments + loop_manager = ControlLoopManager(robot, controlLoop, args, {}, log_dict) + log_dict, final_iteration = loop_manager.run() + saveLog(log_dict, final_iteration, args) + diff --git a/python/ur_simple_control/__pycache__/managers.cpython-310.pyc b/python/ur_simple_control/__pycache__/managers.cpython-310.pyc index 887f36a4e47f78717aeae754bdc4ee1ce9bb15f6..2fc97dcccb20512aad35f4827b79036aaa833b93 100644 GIT binary patch delta 20 bcmexq@za7kpO=@5fq{X+hAnL)cb*IYJ(UFS delta 20 bcmexq@za7kpO=@5fq{YH(BIUJ+<7tpM+63I diff --git a/python/ur_simple_control/basics/__pycache__/basics.cpython-310.pyc b/python/ur_simple_control/basics/__pycache__/basics.cpython-310.pyc index 39479797c796ac2cf74a596f87a7c0fc705d6b0a..ff88e439ab199e7fe995968252caea7174bd1d85 100644 GIT binary patch delta 109 zcmaFL(Zb1_&&$ijz`(#@!<LpBzL7VViI1Iufq{*Ifx(%9fuT5HatD(+TMSbzYc1R4 zgG{p+*(b*^YfIna$jMKSPsvO!xy7HBnU|OopIMSxlvt9PpEtRkS(Sr_k&B6ku}F3D N7Um*G)ye8Cb^vbi8|MH3 delta 77 zcmZqSe9FO_&&$ijz`($u@ggzRdLwTx6CW!B0|Ofa1A{XI14FUT<PIitCPs$IN10|Z hvQAE5)}FkKS(Sr>k&B6ku}FFHW#%GA<;iX=b^u>Q5Fh{m diff --git a/python/ur_simple_control/clik/__pycache__/clik_point_to_point.cpython-310.pyc b/python/ur_simple_control/clik/__pycache__/clik_point_to_point.cpython-310.pyc index bd5b467ed659eded72709b979c8c7912649263f4..6f41384a5420130817fc7462a78e18e0eb2c3140 100644 GIT binary patch delta 262 zcmZ3fdS6XDpO=@5fq{X+hAk~sOpAfxF^GeV*%%lY92giFieF6Bo*I!Vk|L7LR8*A8 z)65Vhn#z?b+RPXwmMXSDd?7=WL@Ga+FPX}oDv&CcD%s2&C6&sVDwZmhDw@fV$<WLi zC7mk0KxQFB3{#YBlw1m9Faro{if%l{D#&w-BR)PiF*7edUQ>SZS;0<MkU(ByZfbmd zkqiR^Ly;o`1H&!;l+?7$yj1u6#GHWq%)F8!bC8r4hzJ4^!63p9M1+8d(8<9<YK(T1 ZtAun#IM_LO*%&#%kcUx#Nq~{%2LSikI->vp delta 90 zcmcbwwo+9)pO=@5fq{V`^LuJ)wiW}!V-N=!GchnQI503U6i=I|J(VqmF_=M9WU~Y# it00r6$Yf2SPNpK+$&I|illg`D7<DGg3F|WPumb?^Y!Chb diff --git a/python/ur_simple_control/util/__pycache__/logging_utils.cpython-310.pyc b/python/ur_simple_control/util/__pycache__/logging_utils.cpython-310.pyc index c6c2c90ef4c8ebf132ae34444b0ad309926e8926..a9d82f13280e4f3e31a0b9ed7c941fa52e5621e6 100644 GIT binary patch delta 19 acmcb~b(4!LpO=@5fq{X+hHWF4KPvz&Q3JIA delta 19 acmcb~b(4!LpO=@5fq{V`nrS1KKPvz&_XE%X diff --git a/python/ur_simple_control/util/robotiq_gripper.py b/python/ur_simple_control/util/robotiq_gripper.py index a17ab18..53efd87 100644 --- a/python/ur_simple_control/util/robotiq_gripper.py +++ b/python/ur_simple_control/util/robotiq_gripper.py @@ -27,21 +27,29 @@ class RobotiqGripper: ENCODING = 'UTF-8' # ASCII and UTF-8 both seem to work class GripperStatus(Enum): - """Gripper status reported by the gripper. The integer values have to match what the gripper sends.""" + """ + Gripper status reported by the gripper. The integer values have to + match what the gripper sends. + """ RESET = 0 ACTIVATING = 1 # UNUSED = 2 # This value is currently not used by the gripper firmware ACTIVE = 3 class ObjectStatus(Enum): - """Object status reported by the gripper. The integer values have to match what the gripper sends.""" + """ + Object status reported by the gripper. The integer values have to match + what the gripper sends. + """ MOVING = 0 STOPPED_OUTER_OBJECT = 1 STOPPED_INNER_OBJECT = 2 AT_DEST = 3 def __init__(self): - """Constructor.""" + """ + Constructor. + """ self.socket = None self.command_lock = threading.Lock() self._min_position = 0 @@ -52,7 +60,8 @@ class RobotiqGripper: self._max_force = 255 def connect(self, hostname: str, port: int, socket_timeout: float = 2.0) -> None: - """Connects to a gripper at the given address. + """ + Connects to a gripper at the given address. :param hostname: Hostname or ip. :param port: Port. :param socket_timeout: Timeout for blocking socket operations. @@ -66,10 +75,13 @@ class RobotiqGripper: self.socket.close() def _set_vars(self, var_dict: OrderedDict[str, Union[int, float]]): - """Sends the appropriate command via socket to set the value of n variables, and waits for its 'ack' response. + """ + Sends the appropriate command via socket to set the value of n + variables, and waits for its 'ack' response. :param var_dict: Dictionary of variables to set (variable_name, value). - :return: True on successful reception of ack, false if no ack was received, indicating the set may not - have been effective. + :return: True on successful reception of ack, + false if no ack was received, indicating the set may not + have been effective. """ # construct unique command cmd = "SET" @@ -83,17 +95,22 @@ class RobotiqGripper: return self._is_ack(data) def _set_var(self, variable: str, value: Union[int, float]): - """Sends the appropriate command via socket to set the value of a variable, and waits for its 'ack' response. + """ + Sends the appropriate command via socket to set the value of a + variable, and waits for its 'ack' response. :param variable: Variable to set. :param value: Value to set for the variable. - :return: True on successful reception of ack, false if no ack was received, indicating the set may not - have been effective. + :return: True on successful reception of ack, + false if no ack was received, indicating the set may not + have been effective. """ return self._set_vars(OrderedDict([(variable, value)])) def _get_var(self, variable: str): - """Sends the appropriate command to retrieve the value of a variable from the gripper, blocking until the - response is received or the socket times out. + """ + Sends the appropriate command to retrieve the value of a variable from + the gripper, blocking until the response is received or the socket + times out. :param variable: Name of the variable to retrieve. :return: Value of the variable as integer. """ @@ -103,8 +120,9 @@ class RobotiqGripper: self.socket.sendall(cmd.encode(self.ENCODING)) data = self.socket.recv(1024) - # expect data of the form 'VAR x', where VAR is an echo of the variable name, and X the value - # note some special variables (like FLT) may send 2 bytes, instead of an integer. We assume integer here + # expect data of the form 'VAR x', where VAR is an echo of the variable + # name, and X the value note some special variables (like FLT) may send + # 2 bytes, instead of an integer. We assume integer here var_name, value_str = data.decode(self.ENCODING).split() if var_name != variable: raise ValueError(f"Unexpected response {data} ({data.decode(self.ENCODING)}): does not match '{variable}'") @@ -141,8 +159,11 @@ class RobotiqGripper: def activate(self, auto_calibrate: bool = True): - """Resets the activation flag in the gripper, and sets it back to one, clearing previous fault flags. - :param auto_calibrate: Whether to calibrate the minimum and maximum positions based on actual motion. + """ + Resets the activation flag in the gripper, and sets it back to one, + clearing previous fault flags. + :param auto_calibrate: Whether to calibrate the minimum and maximum + positions based on actual motion. The following code is executed in the corresponding script function def rq_activate(gripper_socket="1"): if (not rq_is_gripper_activated(gripper_socket)): @@ -184,40 +205,58 @@ class RobotiqGripper: self.auto_calibrate() def is_active(self): - """Returns whether the gripper is active.""" + """ + Returns whether the gripper is active. + """ status = self._get_var(self.STA) return RobotiqGripper.GripperStatus(status) == RobotiqGripper.GripperStatus.ACTIVE def get_min_position(self) -> int: - """Returns the minimum position the gripper can reach (open position).""" + """ + Returns the minimum position the gripper can reach (open position). + """ return self._min_position def get_max_position(self) -> int: - """Returns the maximum position the gripper can reach (closed position).""" + """ + Returns the maximum position the gripper can reach (closed position). + """ return self._max_position def get_open_position(self) -> int: - """Returns what is considered the open position for gripper (minimum position value).""" + """ + Returns what is considered the open position for gripper (minimum position value). + """ return self.get_min_position() def get_closed_position(self) -> int: - """Returns what is considered the closed position for gripper (maximum position value).""" + """ + Returns what is considered the closed position for gripper (maximum position value). + """ return self.get_max_position() def is_open(self): - """Returns whether the current position is considered as being fully open.""" + """ + Returns whether the current position is considered as being fully open. + """ return self.get_current_position() <= self.get_open_position() def is_closed(self): - """Returns whether the current position is considered as being fully closed.""" + """ + Returns whether the current position is considered as being fully closed. + """ return self.get_current_position() >= self.get_closed_position() def get_current_position(self) -> int: - """Returns the current position as returned by the physical hardware.""" + """ + Returns the current position as returned by the physical hardware. + """ return self._get_var(self.POS) def auto_calibrate(self, log: bool = True) -> None: - """Attempts to calibrate the open and closed positions, by slowly closing and opening the gripper. + """ + Attempts to calibrate the open and closed positions, by slowly closing + and opening the gripper. :param log: Whether to print the results to log. """ # first try to open in case we are holding an object @@ -243,7 +282,9 @@ class RobotiqGripper: print(f"Gripper auto-calibrated to [{self.get_min_position()}, {self.get_max_position()}]") def move(self, position: int, speed: int, force: int) -> Tuple[bool, int]: - """Sends commands to start moving towards the given position, with the specified speed and force. + """ + Sends commands to start moving towards the given position, with the + specified speed and force. :param position: Position to move to [min_position, max_position] :param speed: Speed to move at [min_speed, max_speed] :param force: Force to use [min_force, max_force] @@ -263,20 +304,24 @@ class RobotiqGripper: return self._set_vars(var_dict), clip_pos def move_and_wait_for_pos(self, position: int, speed: int, force: int) -> Tuple[int, ObjectStatus]: # noqa - """Sends commands to start moving towards the given position, with the specified speed and force, and - then waits for the move to complete. + """ + Sends commands to start moving towards the given position, with the + specified speed and force, and then waits for the move to complete. :param position: Position to move to [min_position, max_position] :param speed: Speed to move at [min_speed, max_speed] :param force: Force to use [min_force, max_force] - :return: A tuple with an integer representing the last position returned by the gripper after it notified - that the move had completed, a status indicating how the move ended (see ObjectStatus enum for details). Note - that it is possible that the position was not reached, if an object was detected during motion. + :return: A tuple with an integer representing the last position + returned by the gripper after it notified that the move had completed, + a status indicating how the move ended (see ObjectStatus enum for + details). Note that it is possible that the position was not reached, + if an object was detected during motion. """ set_ok, cmd_pos = self.move(position, speed, force) if not set_ok: raise RuntimeError("Failed to set variables for move.") - # wait until the gripper acknowledges that it will try to go to the requested position + # wait until the gripper acknowledges that it will try to go to the + # requested position while self._get_var(self.PRE) != cmd_pos: time.sleep(0.001) @@ -288,4 +333,4 @@ class RobotiqGripper: # report the actual position and the object status final_pos = self._get_var(self.POS) final_obj = cur_obj - return final_pos, RobotiqGripper.ObjectStatus(final_obj) \ No newline at end of file + return final_pos, RobotiqGripper.ObjectStatus(final_obj) diff --git a/python/ur_simple_control/visualize/__pycache__/make_run.cpython-310.pyc b/python/ur_simple_control/visualize/__pycache__/make_run.cpython-310.pyc index 607c0fa9684ec739810129676b0ad85f254d1d75..795c1b9cd7d0727feea25ea834e9feb0bd2509bf 100644 GIT binary patch delta 20 bcmZ23x?GeypO=@5fq{X+hAnL)_Z%(&EXM>P delta 20 bcmZ23x?GeypO=@5fq{Wx&i2%e+;g}9Gl&H- diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/InverseKinematics.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/InverseKinematics.cpython-310.pyc index 3fd6e4c1b57dbd18d122b40fa6d9a98e2a34fbde..aa36987a4855762a11f88dfc6cc874e2e01863a6 100644 GIT binary patch delta 20 bcmdn4wq1=opO=@5fq{X+hAnL)w~jCXFth{w delta 20 bcmdn4wq1=opO=@5fq{V`<Z8-BZXIC&HY^0; diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/drawing.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/drawing.cpython-310.pyc index c4ec066dd49fb82dc8ca4b1a060b56e912243739..bf1f237ee59e5a2696fb2e1eff0f58af3fd922f8 100644 GIT binary patch delta 20 bcmZ3?y_lOjpO=@5fq{X+hAnL)_Y775D!K#w delta 20 bcmZ3?y_lOjpO=@5fq{XcAT?zp_Y775E>;AM diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/drawing_for_anim.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/drawing_for_anim.cpython-310.pyc index edfb210d0a6e98b4d5e63a27394a09f5931708f4..386e4348adfe154220854b90c5a300a9b4ce4db5 100644 GIT binary patch delta 20 bcmcc4d7YCxpO=@5fq{X+hAnL)_Zb!dGLZz6 delta 20 bcmcc4d7YCxpO=@5fq{XcAT?zp_Zb!dHZ27t diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/follow_curve.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/follow_curve.cpython-310.pyc index 82f14ea95893dce69a57d1c4cc66d153d88e93c2..ecad6f7a98fc940c8358392551174b8157054704 100644 GIT binary patch delta 20 bcmX>nbWVsnpO=@5fq{X+hAnL)w=*XIF>(YC delta 20 bcmX>nbWVsnpO=@5fq{XcAT?zpw=*XIH4X%z diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/forw_kinm.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/forw_kinm.cpython-310.pyc index 9bf21a63a8d2e7f40aea156cae95fc80c0768c7a..89c05576e0619765fe6e4e9b695158ac2afa3982 100644 GIT binary patch delta 20 bcmdlVxj&LSpO=@5fq{X+hAnL)_ZA%hIynUs delta 20 bcmdlVxj&LSpO=@5fq{Wx;@y;u+*@=2L5v1H diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/inv_kinm.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/inv_kinm.cpython-310.pyc index 019ec0fc3322ff2667d95fd3933437d829cd2882..5b9bd3eda81c325bc8d9dfa41bbea95983485ac7 100644 GIT binary patch delta 20 bcmdmCyu+9~pO=@5fq{X+hAnL)_gYB+Gqwbu delta 20 bcmdmCyu+9~pO=@5fq{XcAT?zp_gYB+H&O*K diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/joint_as_hom_mat.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/joint_as_hom_mat.cpython-310.pyc index 5ba205c8b7b413f27c4deb1fe4e9770e874c7c6e..6e33983b3c586c97d4f0f7eab4fa0b1062a2b9bf 100644 GIT binary patch delta 20 bcmew%^+Sp~pO=@5fq{X+hAnL)cP=jgIVJ?5 delta 20 bcmew%^+Sp~pO=@5fq{XcAT?zpcP=jgJi-Ms diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/utils.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/utils.cpython-310.pyc index 4c46e6f66c03ec78ccfa78f5c4ec2a045d0df4e9..52483807547e9f5e32545dd73487ac395a413263 100644 GIT binary patch delta 20 bcmX@feUh6ypO=@5fq{X+hAnL)_dZqtFscM@ delta 20 bcmX@feUh6ypO=@5fq{XcAT?zp_dZqtG)4sf diff --git a/python/ur_simple_control/visualize/robot_stuff/__pycache__/webots_api_helper_funs.cpython-310.pyc b/python/ur_simple_control/visualize/robot_stuff/__pycache__/webots_api_helper_funs.cpython-310.pyc index d0a69e62d20ea45aceaf28eb99b3149a77c7d3f3..09b6d2de2411f442899e7ae401d866dc1418d567 100644 GIT binary patch delta 20 bcmbQGFiU|upO=@5fq{X+hAnL)H@^S?D^UZM delta 20 bcmbQGFiU|upO=@5fq{XcAT?zpH@^S?F6{&- -- GitLab