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