From 0b4cb89b1c01736a6945a8c17d5081922fe08040 Mon Sep 17 00:00:00 2001
From: m-guberina <gubi.guberina@gmail.com>
Date: Mon, 20 Nov 2023 19:35:05 +0100
Subject: [PATCH] almost done with the dmp, just need to fix the calibration
 script and add marker pick-up

---
 README.md                                     |  25 +-
 .../{ => UR}/ClientInterfaces_Primary.pdf     | Bin
 .../{ => UR}/ClientInterfaces_Realtime.pdf    | Bin
 .../{ => UR}/Client_Interfaces_1.1.3.xlsx     | Bin
 ...-E_Manual_UniversalRobots_PDF_20220114.pdf | Bin
 .../{ => UR}/scriptManual_SW5.11.pdf          | Bin
 .../.drawing_from_input_drawing.py.swp        | Bin 36864 -> 45056 bytes
 python/examples/drawing_from_input_drawing.py | 101 ++++--
 python/examples/path_in_pixels.csv            | 293 ++++++++----------
 .../__pycache__/managers.cpython-310.pyc      | Bin 6514 -> 6516 bytes
 python/ur_simple_control/managers.py          |   2 +-
 .../util/.calib_board_hacks.py.swp            | Bin 0 -> 32768 bytes
 .../calib_board_hacks.cpython-310.pyc         | Bin 5604 -> 6463 bytes
 .../__pycache__/freedrive.cpython-310.pyc     | Bin 717 -> 1273 bytes
 .../__pycache__/get_model.cpython-310.pyc     | Bin 1996 -> 1996 bytes
 .../util/calib_board_hacks.py                 | 138 ++++++---
 python/ur_simple_control/util/freedrive.py    |  33 +-
 17 files changed, 355 insertions(+), 237 deletions(-)
 rename docs/hardware_docs/{ => UR}/ClientInterfaces_Primary.pdf (100%)
 rename docs/hardware_docs/{ => UR}/ClientInterfaces_Realtime.pdf (100%)
 rename docs/hardware_docs/{ => UR}/Client_Interfaces_1.1.3.xlsx (100%)
 rename docs/hardware_docs/{ => UR}/Hand-E_Manual_UniversalRobots_PDF_20220114.pdf (100%)
 rename docs/hardware_docs/{ => UR}/scriptManual_SW5.11.pdf (100%)
 create mode 100644 python/ur_simple_control/util/.calib_board_hacks.py.swp

diff --git a/README.md b/README.md
index cfc8215..c72d8e0 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,11 @@
 # do this everytime you use this repo
+-------------
 - do git stash
 - and then git pull
 
 
 # general info
+-------------
 - all of the code has been used and tested on Ubuntu 22 LTS
 - both Python and C++ implementations are available, there's examples of both (both for the libraries
   used and for their combination)
@@ -12,12 +14,14 @@
   and so c++ implementations can be looked at to analyse python functionality as well
 - matrix operations are done with Eigen in C++, and NumPy in Python
 # libraries used and their purpose
+-------------
 - ur_rtde for the client-side real-time interface for ur robots (we have a UR5e)
 - pinocchio for dynamics intergration, and other robotics-related math on the client side
 - gepetto for visualization (has nice integration with pinocchio)
 - Dockerized ur simulator as a simulator (it's a bad simulator, but it uses the same robot-communication API 
   as the real robot, making coding and testing easier)
 # contents of this repository
+-------------
 - basic documentation can be found in the docs directory: official UR documentation on the robot's capabilities
   and its interface, short instructions on installing Ubuntu, ur_rtde, pinocchio, gepetto and the simulator
 - basic closed-loop inverse kinematics control is implemented in both C++ and python. the C++ version
@@ -29,6 +33,7 @@
 - some basic tests will be here as well, while full projects built on this repo will be in separate repos
 
 # installation and operating instructions
+-------------
 For all of the listed items, consult their specific documentation in the docs folder, and do your own googling.
 Note that for most items you can install through the ubuntu package manager apt, or through the python
 package manager pip. Likewise, you can compile the libraries and install from local files. Both options
@@ -61,6 +66,14 @@ Here is a checklist of what to do together with the key remarks.
   skip using it when simulating.
 
 #TODO re-organization of the repo
+-------------
+- RIGHT NOW: get rid of all ur-specific calls outside of the manager.
+  make all other functions depend only on pinocchio.
+  this is the only way you actually get transferability.
+  this includes the tucking of all rtde_control/rtde_receive calls 
+  behind RobotManager wrappers (because other robot don't have rtde_control lel).
+  i'm also pretty sure there is not a single instant in which i call robot_manager.getQ() without
+  calling pin.forwardKinematics immediatelly afterward. so think about doing that in robot_manager.getQ().
 - long term: write all code in c++, make python bindings with pybind. have common documentation 
   and examples
 - short term: the long term goal is too big of a time sink right now both lack of experience
@@ -73,15 +86,25 @@ Here is a checklist of what to do together with the key remarks.
 - the pyproject.toml actually brakes local install so i'm just keeping it out for now. sweet jesus
   what a mess
 
+#TODO: write instruction for extending the library to new robots
+-------------
+- make sure the base frame of the robot aligns with base frame of the pinocchio model
+  you get from the urdf. even better if you make sure the urdf is correct (change it to
+  be correct), because then it will be transferable to simulators etc
+- todo the rest (will probably happen while i make this work on panda let's be real)
+
 #TODO for current students
+-------------
 - explain hom transf mat
 - make this documentation prettier
 
 # TODO for profit
+-------------
 - writing documentation, making text and video tutorials to the point where this can be used as teaching material
 - do the documentation with doxygen so that you get webpages from markdown as well
 
-#TODO for fun. general point: get a collection of control algorithms for the arm
+#TODO for fun and profict. general point: get a collection of control algorithms for the arm
+-------------
 - implement and test other inverse kinematics algorithms
 - rewrite finalized dmp (and other) code into C++
 - learn pybind, create python bindings for that code
diff --git a/docs/hardware_docs/ClientInterfaces_Primary.pdf b/docs/hardware_docs/UR/ClientInterfaces_Primary.pdf
similarity index 100%
rename from docs/hardware_docs/ClientInterfaces_Primary.pdf
rename to docs/hardware_docs/UR/ClientInterfaces_Primary.pdf
diff --git a/docs/hardware_docs/ClientInterfaces_Realtime.pdf b/docs/hardware_docs/UR/ClientInterfaces_Realtime.pdf
similarity index 100%
rename from docs/hardware_docs/ClientInterfaces_Realtime.pdf
rename to docs/hardware_docs/UR/ClientInterfaces_Realtime.pdf
diff --git a/docs/hardware_docs/Client_Interfaces_1.1.3.xlsx b/docs/hardware_docs/UR/Client_Interfaces_1.1.3.xlsx
similarity index 100%
rename from docs/hardware_docs/Client_Interfaces_1.1.3.xlsx
rename to docs/hardware_docs/UR/Client_Interfaces_1.1.3.xlsx
diff --git a/docs/hardware_docs/Hand-E_Manual_UniversalRobots_PDF_20220114.pdf b/docs/hardware_docs/UR/Hand-E_Manual_UniversalRobots_PDF_20220114.pdf
similarity index 100%
rename from docs/hardware_docs/Hand-E_Manual_UniversalRobots_PDF_20220114.pdf
rename to docs/hardware_docs/UR/Hand-E_Manual_UniversalRobots_PDF_20220114.pdf
diff --git a/docs/hardware_docs/scriptManual_SW5.11.pdf b/docs/hardware_docs/UR/scriptManual_SW5.11.pdf
similarity index 100%
rename from docs/hardware_docs/scriptManual_SW5.11.pdf
rename to docs/hardware_docs/UR/scriptManual_SW5.11.pdf
diff --git a/python/examples/.drawing_from_input_drawing.py.swp b/python/examples/.drawing_from_input_drawing.py.swp
index 6cf925d12f431010f4c30a9c95291912b3547236..f16debe88377c08adde32dd68a6a0aafb6b8ad24 100644
GIT binary patch
delta 5471
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
FX#k#~9?$>)

delta 1969
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

diff --git a/python/examples/drawing_from_input_drawing.py b/python/examples/drawing_from_input_drawing.py
index ac6c1b2..bfa0b35 100644
--- a/python/examples/drawing_from_input_drawing.py
+++ b/python/examples/drawing_from_input_drawing.py
@@ -25,7 +25,7 @@ from ur_simple_control.dmp.dmp import DMP, NoTC,TCVelAccConstrained
 from ur_simple_control.clik.clik_point_to_point import getClikController
 from ur_simple_control.clik.clik_trajectory_following import map2DPathTo3DPlane, clikCartesianPathIntoJointPath
 from ur_simple_control.managers import ControlLoopManager, RobotManager
-from ur_simple_control.util.calib_board_hacks import calibratePlane
+from ur_simple_control.util.calib_board_hacks import calibratePlane, getSpeedInDirectionOfN
 from ur_simple_control.visualize.visualize import plotFromDict
 
 #######################################################################
@@ -118,14 +118,23 @@ def getArgs():
     # TODO measure this for the new board
     parser.add_argument('--board-width', type=float, \
             help="width of the board (in meters) the robot will write on", \
-            default=0.3)
+            default=0.2)
     parser.add_argument('--board-height', type=float, \
             help="height of the board (in meters) the robot will write on", \
-            default=0.3)
+            default=0.2)
     parser.add_argument('--calibration', action=argparse.BooleanOptionalAction, \
             help="whether you want to do calibration", default=True)
     parser.add_argument('--draw-new', action=argparse.BooleanOptionalAction, \
             help="whether draw a new picture, or use the saved path path_in_pixels.csv", default=True)
+    parser.add_argument('--pick_up_marker', action=argparse.BooleanOptionalAction, \
+            help="""
+    whether the robot should pick up the marker.
+    NOTE: THIS IS FROM A PREDEFINED LOCATION.
+    """, default=True)
+    parser.add_argument('--find-marker-offset', action=argparse.BooleanOptionalAction, \
+            help="""
+    whether you want to do find marker offset (recalculate TCP
+    based on the marker""", default=True)
     parser.add_argument('--n-calibration-tests', type=int, \
             help="number of calibration tests you want to run", default=10)
     parser.add_argument('--clik-goal-error', type=float, \
@@ -141,6 +150,50 @@ def getArgs():
                 the simulation yet, sorry :/ . You can have only 1 these flags right now')
     return args
 
+
+# go and pick up the marker
+def getMarker(q_init):
+    pass
+
+"""
+getMarkerOffset
+---------------
+This relies on having the correct orientation of the plane 
+and the correct translation vector for top-left corner.
+Idea is you pick up the marker, go to the top corner,
+touch it, and see the difference between that and the translation vector.
+Obviously it's just a hacked solution, but it works so who cares.
+"""
+def getMarkerOffset(rotation_matrix, translation_vector, q_init):
+    # put this in a correct place
+    old_speed_slider = robot.speed_slider
+    robot.setSpeedSlider(0.3)
+    # TODO: this isn't gonna work because it's not going 
+    # orthogonaly to the board
+    # so TODO: calculate TCP speed based on the rotation matrix
+    # and then go
+    z_of_rot = rotation_matrix[:,2]
+    # it's going out of the board, and we want to go into the board, right????
+    # TODO test this
+    #z_of_rot = z_of_rot 
+    print("z i'm following:", z_of_rot)
+    speed = getSpeedInDirectionOfN(rotation_matrix)
+    robot.rtde_control.moveUntilContact(speed)
+    # we use the pin coordinate system because that's what's 
+    # the correct thing long term accross different robots etc
+    q = robot.getQ()
+    pin.forwardKinematics(robot.model, robot.data, np.array(q))
+    current_translation = robot.data.oMi[6].translation
+    # i only care about the z because i'm fixing the path atm
+    # but, let's account for the possible milimiter offset 'cos why not
+    print("translation_vector", translation_vector)
+    print("current_translation", current_translation)
+    print("translation_vector - current_translation", \
+            translation_vector - current_translation)
+    marker_offset = np.linalg.norm(translation_vector - current_translation)
+    robot.setSpeedSlider(old_speed_slider)
+    return marker_offset
+
 #######################################################################
 #                            control loop                             #
 #######################################################################
@@ -234,6 +287,7 @@ if __name__ == "__main__":
     #######################################################################
     #          drawing a path, making a joint trajectory for it           #
     #######################################################################
+    # TODO make these ifs make more sense
     
     # draw the path on the screen
     if args.draw_new:
@@ -244,7 +298,9 @@ if __name__ == "__main__":
         pixel_path = np.genfromtxt(pixel_path_file_path, delimiter=',')
     # do calibration if specified
     if args.calibration:
-        rotation_matrix, translation_vector, q_init = calibratePlane(robot, args.n_calibration_tests)
+        rotation_matrix, translation_vector, q_init = \
+            calibratePlane(robot, args.board_width, args.board_height, \
+                           args.n_calibration_tests)
     else:
         # TODO: save this somewhere obviously
         # also make it prettier if possible
@@ -255,29 +311,32 @@ if __name__ == "__main__":
             [ 0.        , -0.83234077,  0.55411201],
             [ 0.        , -0.55411201, -0.83234077]])
 
+    # make the path 3D
+    path = map2DPathTo3DPlane(pixel_path, args.board_width, args.board_height)
+    # TODO: fix and trust z axis in 2D to 3D path
+    # TODO: add an offset of the marker (this is of course approximate)
+    # TODO: make this an argument once the rest is OK
+    # ---> just go to the board while you have the marker ready to find this
+    # ---> do that right here
+    if args.pick_up_marker:
+        # pick up the marker
+        #TODO
+        pass
+    if args.find_marker_offset:
+        # find the marker offset
+        marker_offset = getMarkerOffset(rotation_matrix, translation_vector, q_init)
+        print('marker_offset', marker_offset)
+        path = path + np.array([0.0, 0.0, -1 * marker_offset])
+    else:
+        path = path + np.array([0.0, 0.0, -0.0938])
+
+    exit()
     # and if you don't want to draw new nor calibrate, but you want the same path
     # with a different clik, i'm sorry, i can't put that if here.
     # atm running the same joint trajectory on the same thing makes for easier testing
     # of the final system.
     if args.draw_new or args.calibration:
-        # make the path 3D
-        path = map2DPathTo3DPlane(pixel_path, args.board_width, args.board_height)
-        # TODO: fix and trust z axis in 2D to 3D path
-        # TODO: add an offset of the marker (this is of course approximate)
-        # TODO: make this an argument once the rest is OK
-        # ---> just go to the board while you have the marker ready to find this
-        # ---> do that right here
-        # put this in a correct place
-        #old_speed_slider = robot.speed_slider
-        #robot.setSpeedSlider(0.3)
-        #speed = [0, 0, -0.1, 0, 0, 0]
-        #robot.rtde_control.moveUntilContact(speed)
-        #current_pose = np.array(robot.rtde_receive.getActualTCPPose())
-        ## i only care about the z because i'm fixing the path atm
-        #marker_offset = translation_vector[2] - current_pose[2]
-        #robot.setSpeedSlider(old_speed_slider)
         
-        # TODO: change magic -0.0938 with market_offset (you first need to check that it works)
         path = path + np.array([0.0, 0.0, -0.0938])
         # create a joint space trajectory based on the 3D path
         joint_trajectory = clikCartesianPathIntoJointPath(path, args, robot, \
diff --git a/python/examples/path_in_pixels.csv b/python/examples/path_in_pixels.csv
index 9f8bdff..7714927 100644
--- a/python/examples/path_in_pixels.csv
+++ b/python/examples/path_in_pixels.csv
@@ -1,169 +1,124 @@
-0.40276,0.80752
-0.41318,0.81052
-0.45336,0.82404
-0.51140,0.83305
-0.52777,0.83605
-0.53522,0.83605
-0.57540,0.83605
-0.58879,0.83605
-0.59772,0.83605
-0.63493,0.83154
-0.64535,0.83154
-0.65874,0.82854
-0.69297,0.81653
-0.70190,0.81353
-0.70637,0.81203
-0.73613,0.80152
-0.74208,0.79551
-0.74804,0.78951
-0.77334,0.77449
-0.77780,0.76849
-0.78376,0.76248
-0.79566,0.75497
-0.80757,0.74597
-0.80906,0.74146
-0.81650,0.73546
-0.83733,0.71444
-0.85222,0.68891
-0.85817,0.68291
-0.86115,0.67690
-0.86710,0.66639
-0.87007,0.65888
-0.88049,0.63336
-0.88198,0.63186
-0.88198,0.62285
-0.88347,0.62135
-0.88347,0.61985
-0.88347,0.61835
-0.88347,0.61685
-0.88347,0.61534
-0.88198,0.61384
-0.88049,0.61234
-0.86710,0.59883
-0.86115,0.59432
-0.85668,0.59132
-0.83882,0.57481
-0.83287,0.56880
-0.82543,0.56580
-0.80608,0.55078
-0.79566,0.54328
-0.77631,0.52977
-0.76738,0.52676
-0.76143,0.52076
-0.75101,0.51775
-0.74357,0.51475
-0.72125,0.50274
-0.71678,0.49974
-0.70785,0.49673
-0.68404,0.48172
-0.67362,0.47872
-0.67214,0.47722
-0.66172,0.47421
-0.65725,0.47121
-0.64832,0.47121
-0.64684,0.46971
-0.64237,0.46971
-0.64088,0.46971
-0.63642,0.46971
-0.63493,0.46971
-0.61856,0.46971
-0.61707,0.46971
-0.61261,0.46971
-0.60814,0.47271
-0.59475,0.47271
-0.58731,0.47421
-0.58284,0.47421
-0.55159,0.48022
-0.54415,0.48022
-0.51140,0.48472
-0.50099,0.48923
-0.49950,0.48923
-0.48313,0.49373
-0.48164,0.49523
-0.47717,0.49523
-0.47420,0.49673
-0.46824,0.49824
-0.46676,0.50124
-0.46527,0.50124
-0.45634,0.50724
-0.45336,0.50875
-0.45336,0.51025
-0.45187,0.51175
-0.44741,0.51775
-0.44592,0.51926
-0.44443,0.52076
-0.44146,0.52526
-0.43848,0.53127
-0.43699,0.53277
-0.43550,0.53727
-0.43253,0.54178
-0.43104,0.54328
-0.42955,0.54478
-0.42211,0.55529
-0.42062,0.55829
-0.41318,0.56880
-0.41020,0.57331
-0.40871,0.57631
-0.40574,0.58382
-0.40425,0.58682
-0.40276,0.58682
-0.40276,0.58832
-0.39532,0.60033
-0.39532,0.60183
-0.39234,0.60634
-0.38937,0.61384
-0.38937,0.61534
-0.38788,0.61985
-0.38788,0.62886
-0.38639,0.63036
-0.38639,0.63486
-0.38341,0.64387
-0.38341,0.64537
-0.38341,0.64687
-0.38193,0.64837
-0.38193,0.65288
-0.38193,0.65888
-0.37895,0.66789
-0.37895,0.66939
-0.37895,0.67240
-0.37895,0.68291
-0.37895,0.68741
-0.37597,0.69192
-0.37597,0.69642
-0.37597,0.70393
-0.37597,0.70843
-0.37597,0.70993
-0.37597,0.72044
-0.37597,0.72344
-0.37597,0.72495
-0.37597,0.73546
-0.37597,0.73996
-0.37597,0.74146
-0.38044,0.75798
-0.38044,0.76698
-0.38044,0.77149
-0.38193,0.77299
-0.38193,0.77749
-0.38193,0.77900
-0.38490,0.78951
-0.38490,0.79101
-0.38788,0.79551
-0.38937,0.80002
-0.38937,0.80302
-0.38937,0.80452
-0.39234,0.80902
-0.39383,0.81353
-0.39383,0.81503
-0.39830,0.82404
-0.39978,0.83004
-0.39978,0.83154
-0.40574,0.83605
-0.40723,0.83755
-0.40871,0.83905
-0.41020,0.83905
-0.41169,0.84205
-0.41318,0.84205
-0.41467,0.84205
-0.41616,0.84205
-0.41764,0.84205
-0.41764,0.84205
+0.27578,0.76759
+0.27727,0.76608
+0.28025,0.76458
+0.31307,0.73749
+0.33843,0.71793
+0.36976,0.69686
+0.38169,0.68933
+0.39064,0.68332
+0.41749,0.66676
+0.42346,0.66074
+0.42793,0.65623
+0.45478,0.63967
+0.45926,0.63817
+0.46522,0.63215
+0.49208,0.61560
+0.49655,0.61259
+0.50401,0.60657
+0.52191,0.59754
+0.52638,0.59603
+0.52788,0.59453
+0.53533,0.59152
+0.55920,0.58249
+0.56368,0.57948
+0.59053,0.56293
+0.59948,0.55992
+0.60992,0.55691
+0.62782,0.54938
+0.63826,0.54637
+0.63975,0.54487
+0.64572,0.53885
+0.66213,0.52982
+0.66362,0.52982
+0.66810,0.52681
+0.67257,0.52380
+0.67406,0.52229
+0.67555,0.52229
+0.68003,0.51628
+0.68152,0.51477
+0.68301,0.51327
+0.68749,0.50725
+0.68749,0.50574
+0.68898,0.50424
+0.68898,0.50273
+0.68898,0.50123
+0.68749,0.50123
+0.68301,0.49822
+0.65616,0.48919
+0.64721,0.48919
+0.61290,0.47865
+0.60544,0.47564
+0.59649,0.47564
+0.56219,0.46511
+0.52489,0.45909
+0.48313,0.45909
+0.47417,0.45608
+0.45777,0.45608
+0.44882,0.45307
+0.41152,0.44856
+0.39511,0.44856
+0.38169,0.44856
+0.34738,0.44254
+0.33694,0.44254
+0.32053,0.44254
+0.29219,0.44254
+0.27578,0.44254
+0.26534,0.44254
+0.21611,0.44254
+0.20567,0.44254
+0.19821,0.44254
+0.16390,0.44856
+0.16241,0.44856
+0.15943,0.45006
+0.14898,0.45006
+0.14749,0.45006
+0.14600,0.45157
+0.14451,0.45157
+0.14451,0.45307
+0.14451,0.45458
+0.14451,0.45608
+0.15048,0.45608
+0.15197,0.45759
+0.15793,0.46360
+0.16241,0.46511
+0.17434,0.47263
+0.18180,0.47564
+0.20269,0.48919
+0.21313,0.49220
+0.22208,0.49521
+0.26832,0.52229
+0.27876,0.52530
+0.28771,0.52831
+0.29965,0.53584
+0.32202,0.54637
+0.32948,0.54788
+0.33694,0.55390
+0.34589,0.55691
+0.37125,0.57196
+0.37572,0.57497
+0.38467,0.57647
+0.41003,0.59302
+0.41451,0.59453
+0.42495,0.60205
+0.44136,0.60958
+0.45180,0.61710
+0.45627,0.62011
+0.46522,0.62162
+0.49208,0.63817
+0.49804,0.64118
+0.50998,0.64870
+0.55025,0.67278
+0.56815,0.68181
+0.57710,0.68482
+0.61290,0.70137
+0.61738,0.70739
+0.62633,0.71040
+0.65318,0.72696
+0.66064,0.72846
+0.66511,0.73147
+0.67555,0.73448
+0.67705,0.73599
+0.67854,0.73599
+0.67854,0.73749
+0.68003,0.73749
+0.68003,0.73749
diff --git a/python/ur_simple_control/__pycache__/managers.cpython-310.pyc b/python/ur_simple_control/__pycache__/managers.cpython-310.pyc
index c10725690a79e90b18d13c2a9bb6da1853d04ae0..ccb51da838093a6f4a35c6013d4b2b91b781502e 100644
GIT binary patch
delta 66
zcmexl^u>rbpO=@5fq{YHT3~dl>PFrzyz(^+3=B04Sq#P2H4Isd3z!x%)H2pEWHD#4
W6sgxRWNp63%f!gYv-u(4L@oeXArcM%

delta 64
zcmexj^vQ@fpO=@5fq{WxX-8D5!baXLys}jc3=B04Sq#NiH4Isd3z!x%)H2pEWHD#4
U6seVLe!$Db$jG(%G2cWk05=8^m;e9(

diff --git a/python/ur_simple_control/managers.py b/python/ur_simple_control/managers.py
index b786893..0e39dc8 100644
--- a/python/ur_simple_control/managers.py
+++ b/python/ur_simple_control/managers.py
@@ -306,7 +306,7 @@ class RobotManager:
                 # TODO: make it work or remove it
                 #self.gripper_past_pos = self.gripper_pos
                 # this is pointless by itself
-                self.gripper_pos = gripper.get_current_position()
+                self.gripper_pos = self.gripper.get_current_position()
                 # the /255 is to get it dimensionless.
                 # the gap is 5cm,
                 # thus half the gap is 0.025m (and we only do si units here).
diff --git a/python/ur_simple_control/util/.calib_board_hacks.py.swp b/python/ur_simple_control/util/.calib_board_hacks.py.swp
new file mode 100644
index 0000000000000000000000000000000000000000..0c65b52814ff442ca7d522cc8b831f8b20b5c347
GIT binary patch
literal 32768
zcmYc?2=nw+u+TGNU|?VnU|=}2Bs#Syw1(lX7z0CkesMv5N@5X63Lnl*EY8l%!>0lw
zR|hjtKO;Xk)kq)C%_+@G(Jv@UtjH|ZFD;5M&de>yNsUj=&nqd)&(SZaEXl~v!y-{y
zl9{8QoS2iD6rYrzSd<c<k(iuatXEJ8v2K(c4S~@RfQ3M5Nt&(&FN3j>p#expSxHer
zSSS?49L1v{Fd71*Aut*OqaiRF0;3@?8UmvsFd70QBm_zd*cj>=7#NtK{?&)ljA%3)
zly3>8b)Ym%9Sf8n4yBW!G)$fq$`69lyPz~oo*l~Pgwldg2`I(D3>7zq(!x*)C<PTA
zrA9+wGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nu!TTk3IoGKb_Rx>9FX~c
zSpWYxKLf)eeg=kx{0t18{0t0b{0t0P{0t0n{0t0Q{0t1A`4|}X^D!{2<6~f0%g4a5
zl8=F5As++7R6YiVI6ejjJw678N4yLS3waqBGI$vnoOu}-e(^9ceB)tY_{zh;@R5gs
z;UNzL!v!7&hOImd3^_au46-~742(Ps42QTG7@D{l80xqg7~;4Y7_7J%805Ga7%p)!
zFf?*8FgS8CFnr-;U^v9dz_6Z^fuV<!fgzQXfkBQF;tx$u28R0_3=GFP7#LP@Ffh#J
zU|^WT!N4$sgMp!vgMlH8gMmSfgMr}%I|IW$b_RwXb_NC;b_NCub_RyOYzz$V*%%m3
zvN13$V`E_GWMg3PWn*BFVPjyp&C0;Al$C*@g_VIJj+KGIf|Y?moRxv$8w&%&1r`Q|
zc`OVJaV!iBhAa#WUzr&g)-W?L)G#wJR5LR$L@+Zj*fTRQ7%?+27&0?3=rS`f2s1M<
zd}U%_SkA=2P{hQ*5YNQGpvA<%@Pv_p;Q=E9!!AY!hBb%*4h0Y>D9X$$(NI!SVn|6%
zQ^-inOUX$MElw>8$@c)WL!1Kw@{3b7it>~4OEj$*Kq^i26pB)FQWJ|)6-qKv71D}Q
zQ&WmE%Tg5*^HM+}c?!iPiA5y}DfyXs=^z0G@S=*M#FEVXJcWXy{N&W)Vg_S9h0@|w
zh2s3&RE6x+O7Mych0MHy(h`N}Nd3H6g~VcoM1`cB{N!wqG0BNJIXVnRdQh|BmNF<P
zl;kTU<(FhA<mHzrBo(D5W-F9rWagz8gWZ#uQ=G4mm|Rktn3GefP+XdvoSK@#V5p~1
zlA4nPc3f$3YLP;DMq&xbpp<-t^30M91#q|&>nP+U=BDOUDwJoW7NvsZLCyntIyEmv
zH#IFSHMu0eh(Q-0V89uu;J{=6#X?bPNoi4@LJ*h(wpv3gNJpVKwZK+gCnir_6G=k7
zD8ED@7vkEy)N+NiqQu-(D|Jl<u$mwRTZOy=y~LzqjUY`0EfBjnGd)iuC_XbUvm`Sy
zCqA{fBr`X$Bo$(&vO;-AW^#r?d8$HsYKcNxQGPBsP@t+6V5$`~AnKA6^C002iu=S8
zh5WQMm_d2@<qD~J#id253W?C51zBCJkO&I8j8p{(uLKm*mHDL#<%xMEI>?UBC@x7%
z&eqTf(ov|2&r2=WD@rZSNGwRz&@k39)YR03SOoPUOmPJkl{yNQSVW=vl@%%#GK&?`
z^Yc>_)RXgz6*5Z{$`gwf@{>vuGxJhYAn~85kX)2sTnu)eGT1fIMzM&ng^7TISl19)
zl_7>I!&r#Jp~e_sC@_F20J|E+9+(KSJrFTudtf4%s*o*%sDfLjke`#Hker{A3d&KH
z#R}jQUYb{unWK=FSpf>7f};Gg)I3nCFV8Q^hIkT`TA>(}+p|iGOBB-bi;`0jc?_Op
zf<Rg`63akICAByeYJje;okC_xYN8b+`)8)-6+@C8D9I(}C<MXN98^Pyzl*<>LRw~C
zibA47QEFmweqLfy4yfeFDFv4(CHbHXUkpxPpyDMdCp8zU7vjFm3UHc+q`%CRWUwSS
zI3O_!j%p2XN`fXmNQ{9+AW9O8iV`a|q7C&7bQBDr1T@;fX#u1PT!bd)=M|R}l_r<C
zf%2tWQGTvpeo<~>P8hhTz>*Jj6!M_uYJQPIc~NFbszOSBd7eUfMx_EMo22CDsh23^
zrKYBUQmRI#dago7eqL&ENlqm=Cl-S<TuH8uLQ-i7NJ(a~LJl~8g8~j5m!JYGEit)7
z0iO53;gVQfT$&4x9EA!6&|*1;l8nq^P|WA2DJ18Y78R!|B<F+H&VlSoEK15ODM~D=
z)KMtTXDClqz-|UedqHARVopwK4kRmqY%c;;AL_+0d%%HInp~og2r0f45{vRnA(e+h
z8km&_4m5=_aH!!gV8Mki1K3EM;f_(%=7G}yC?!LRTP0;Ac3y#APG(+WPP$%ZUYSNg
zesLx!ofYeaC^#sDD>x{?MKqOkKqV}ZiZvOKErA<?X{?eC!U{}ToW`JP!=VgW5vr1K
zB^`xuNWu>XCFcUYl+46*4Nz@Tl$e*Es$r<3kdvB+2oFsKZ3RPksj6)V%I=VwA6$hR
zDrgu$D&~~@)M8K~&P~itRVYr)D~2=`GK&>JBE<^f3dNau>7_Y|MG)(i6*LlaO7ct7
zGeGG%IlnX~MZY)$L@6YtDx`u6rQCc_HIrVHT3ifjc@z}oCnYB3RKoNp6)TjdW~OJ9
z6zf3JX-Pg*09+D)>P=`H0b)>Iib76iUTR_yIQc>i1J@CdILm_s2sEN|ic5+M5#az%
z1E4Iaff_uTItoR}`FSa}e))N+n$ZTa49W_5`FXk!m!+mCfZ9+c3dMz`iA9jo5uPR>
z)<Fs#xS%GufJw_NK`BuX(va4fE~tP7<+;4n^3)=Qg8a<95=b4KnWq3Q1;AcT&MzuT
zg%k;S;Hm(kP>}&t=0F2GC0`*C8f>5@SbiEP@QPDmW@hGr_$a<8W&kz962bAA11df8
zN<iff*lZmJP>lgDf|4^p391;Z9keVLu0}y4H@~<<A-yQGpdhsf;_O678xh<TPyn@i
zGEx;%^HOveK;@ei$g1R2P)Vr{N)e#eURq`a$hn{}$S=xF%`1U4JR#19nGI@Qg1nlZ
zufvd>lUQ7wnT+Zag|y5PJ&clv0WJ6;1q-NE90YE|6)OZOB&8-Nf||A<uc{Y=o0jUu
z;1WDF1(ZkNMHSfp8K4$dQDR<knjWZGr^k?~m#PPrK`8@48bLlP$Vtpg)nf?BD1`)H
zep*^_DyXfUS`4lZauZ8RQj2sz4Z8e1P!$2HI6xW`^U`xtVS!eXT3iBd9)mKV0=NnR
zt4Yc)1GfiCQgc)DN<f(bmS~{qMGqW_pnxj@xd5qhD#?e|(RrXoA;?V{AZ3vHKVKmm
z)I7{AQOL|wNK7e9%u7zy)MJRuF9nAS$a6>~N1{SWet|+xYFddxa(+=>YLP;InnGrY
z4udPS?W&Nd01gL*q)Jc`0*dY2(wvga0z{fChEzV8C3*_Tk;ssqnwMIXm;;Ho%-n+f
zq7sFYjH1-Ul+3(z24zsA1RO~zsfp0~3*OaGFILFRO9M4iQbDceoK%IJ{QLq2aGM!p
znYkWlHMt&KuL9I6xBxC~xrup+>7b+!)er=#Iej653{bJ;{DMjtyCgF=6~@jh%`K<|
zCG5Ncm{37xUVd_NMrJ-pxB#@OUKtc(si1;2CqF+MT*iSS1r+@ysYSV<dJj}DKr$CN
zd4OxkVugaD)RL0S)FK6qqSRbaI*9@41GOM^z)1<z(_#Si|2x?k7z&~Nf7tx`Lw*K^
zUHl9Tv-ueqYWNu#V)+>u?D!cN6!{q#82A|&p7Aj-oaJL+*uuxaFq@Bop@fftL6?t#
z;Ri1R!y#S<hB>?p47t1v3^}|E4B@;C4C1^D45xV*7$);DFihfMV2I*jU{K~^VBq3m
zV7SQ5z_5&)fuWt7fgypLfx(-bfkBs>f#C-i1H)%728O*{3=EUF7#PC27#K{s7#K{r
z7#JkE7#RL>GBDibWMDYM$-uCmlYt?JlYzmIlYv1J+W()z0r6J>$ZyyNKSsqyLtr!n
zMnhmU1V%$(Gz91q0-$a?Y<M{}0Ms~!j8*F><i&$pxy7(9p#n7qtwFXaE9in+iI83i
z(IeL|osecOq8SJgCu<NJqE(lgBiRrmA#FeK2njS06>Jp@4Zs4*3LsfX8?pp6T$Grn
zkXV#n3hFO_6@Z6&6l@ic8?G9f44G*P@$sP1^!RuMTU!OC`1st!%)Iz`B`e6lHEal6
zN1+7N8Oj0o*>n^N!Q<9ogTc*E4Rug6QwQ8XLQ)7FC{oBQwo*qi0TTOQH|Z6pmIN21
zrlthvWTvDRY2@dm#2173@x@>Ph*D(**bqNhP5~mPkd&C54eF(2mVg_=WtsV<#R_GK
zIi-+}JCXyH%0WFRu=>&h9fjh=GElD%6jFttHaMvJkeQgHP^bj455$izRIpV5HR|<J
zQd0{+42?pFEJy<4`1I70Kn;i>M4+f71-_?M57Zv_(a1|Jk1xnCh7Rq+c#r{QustBj
zXroxLYhltDRwtJh6{Y5tAen?LqF}3lWPed=a%yH-s$P0(i6eN91vXy<aj7!6V*u*;
zrRPI}u(SYdxw1lj5vVT@9RbMzbtg(PQgam&%Mvre6EUFv2yzmFY6B%cEAUiBQDzFL
zTL_wJ0Qo)#Hquj>Us|L98bB>BDNRe$fut@-+EGf+FF{UT&{U(NkXfQ$Y^8)H;UFh5
z^eBP^LrP*vqF%mlW;BHB<?rbi67T5}tB0f&5*P)Ud3tI2MdgV_Dc+fRskw<InaRbF
z!b&eUKP5Fs2O6><Bf(=zknx{F=nxx5S^x(L#9EBR5DFT|cg_b7zi5C{GQ<&Jrh+Xf
z1i^X1GtVUxG!B%RpXZ<Erx65E1r4rD^_(2|XgsbgmzQ4-P0Gp&Y57Hvq4@Gt@bnHS
z$E4>gq=2o+sZ_|!1CQ0GDu8GE!0uO80F76Hl1OEKDQE}>)D^D;Y0OPcgbz$01tv7o
zKqCVnhv!s+jlmHNIP-)lXcnfZpb|YdM4P}Q3{kU5v@uM=03uOTP^n-G8eR{`%qtEG
zh}0-5fDS)GWI)kfR8Xmxn^;nmSrL*SR8R>EUS-HoeVzhn91>}W3hWbDz9f)sqrnqE
zh+K{CT=2{fLK^C5Wd&G9ghoVhVs5HJaY23w*ltoo5j-V^u*4`9-2Vqv{1u>iW&s8U
z*!uld{0s~M{0t0g{0s~a`4|{hL+AB5_!t;=@-i??;ALQN=Vf3J;bmaB$HTyIm4|`h
zC=UZeF%JWS2M+^-5f1~yb8ZHP!`uuEo46Sm=5sSJ6mc^!#Beh(2yrtoT!Z%OS938i
z%;jQWu;F50Q0Id5>lwHh7*=pHFtl<qFw}4|Fl2EuFlcZxFnr@+VA#aLz%ZGEfgzrQ
zfx(1>fq|EUf#EJY1H)l<28NaF3=E0Tx%}^J3=AvS7#M=t7#LL87#P^t7#LXD7#Lo&
zGBBKAWnehY%D^y(m4U&Mm4QKqm4QK;m4V?q3j@O=76yigEDQ`=Sr`~*vM?~rU}0eB
zU}0d$Wno~@Vqsu-%FMuUhnaz4BQpa-88ZVzGBX2%88ZXJEhYwr156AI>zEiA7BDd|
z*hA;?K^rUnGcqvTXJlYl&&a?44rc}i24#gr$WRWXeNhe@EC-L=7b}z&ftoDE3ZM)M
zD(pbHG%sBbqzyEv1*y(6!Sl))kdg^JT@D@e12=Ut^2<T$K?Sgan`eYVh=*seLa4h>
zq=JW|v$rA`KnhzdsVFrs#SOMhz&Af76<U*lnj0Vt8UxPED}~ghAOR4D7DC|}i6yCJ
zsYRe6UWJm%0?<5I9%y7TFEz6yBeh6DJyKmEFTY4ZJx^Uv!5uUk0I5Mh3A>~y5i|>+
zkerd4nWhLWr$C0M<`kz|fzv#Q2g2Z$11KUTnYpQY#W|^|1sX<>auK8sgrQDz2AvfF
zUDlA8lwS(2xWEyhr{Dpa_XO8Pp!t7=e8^aNQf9hBQEG}pF=&7@skEddKM&PanQ01%
zdBvcCds|xt^-6VcJ&6#AR7Z7mYDH!VT3ABe7LoxPq|DDr1<i=27bWH@lxKoU^9s<2
zsC#~XN>XJivel>-=b>Bd2env92^xrwMc_eq(1dIXxVQ%U8?n+OFCFA`&}@K4UcN$Z
zYGPio0?4(R_K@Wr;E?uINX%6LPeX!+a6!Yx;2Ih-zz<(v0UBlmH3wj+5!8y&Q;5j}
z8v%+AScpNEkAPRRfP~94GILTDLW)XLp>0fft2-Vt;;WaHpP2^@K4k?EM<F>QGY7PY
z1yl<uXcU(u=A|SSr6?2>B_@|-f?8H!OF_{W51NN60W~V2CV<zjXeb4M=A;x{^GZ^S
zK(!c1sh*ym5_EkAh7-WS1~ma)Qo$B6G_4l`9;DVNNi0fFEwP0wg$TQq<|TvXD0M(>
z@nTy@t3n5y%pmU6fi@zP6@tNQbKv?xftv_gX_8o!SOS_12KgM4k3mj{=tgmfYguX@
zEYT?|I2WaY^d*Ar0?*BrKy-s*0ECfpk%69pfhpFUR0wK)X@RF2LG$c|ntI>~VGR?g
zvq1)dFf?(O7MY@IKq_)@H%W0B3NjdkwXjv$5R*YoGH@%;ELN{5A2OkY%Q&bT3o`S-
zZp1VIsWAihrj9}kIAwv{0m2YNF!Z7Y9)&GRkVPO|sFzq!keZjGVW4M#Y6Bh_0v!QZ
zX9Z+FBqM^#0z{J1%PfvBPA$>UL=<Qc-=Z{S;mH)K(f}<~gNvgkf6R0bHC`Dq3k;dA
z0#8Y0mVj5hK)eg-)LKERL2$1YJlRnRn(9bNP0P$fUgefw1g;Ok^T#?0nJLMTMNE*s
zPD#E(QE47%b_F!im6s2$p&+FVtTa#n%`1X}MH#FNG&2ZV5SLg~37IV~$yWfo5bj4%
zw=ppfG4}+Tb%NN5l((QY6uf-KQVbzh>gj>gS^%iRLN9Bf?Ltufgf;;OuFN3QZlH<W
zT+o6XP_c~EfQ6U~F8e?QI@||(3SbK%i5fIn3i3V-56;RT<~n$QQW7Gd${3uwA(b$w
zx04F4AmAaS0O|qiDd39|a1g?rg&CBoIjB`QIc*2HXCV{xkmX^ZX>8EccnY`$23jTt
ziDr<e$}@1ZFr2|N{NO$#Y;*{e{&jWp@^#_Eb)Xgk0bil|31_ne6fEeifS}YwNXrDp
zzPx+|)CLKxeFSTmK-)KvG7Hjp0GSRCn(&O&Ja9;)WP(;?>44@%i;F?6P#ute3c%IB
zdY(GSyPyUSB(Ojk1$oUVbVVt+EnZw&0BX{Jr=62h^<wfMxdjxyL?jx8V$kxp#1gQZ
zK+7|86Z0U8T?<Mfy*gL~6obY~Kn^J=$_KXyK@F~=#5}l-Ai2EK+$6|^JE(9e2Af)3
zkeZyCmYJHOpplsd76C2k1eNEB<scS#WkqJO4yc(88YattG~_`ZK=m`I1qvDu01eM*
zfc+lg9H3C8P>^4hSpsUgLq-ZR^Yb*pBS$6qrO6rKL<BBv!D$7u4mA_9t^({BaKjd~
zdKI){I8PzJv;;JS2cDJ(m*uedhp#?PDJ@EcL`!LLY6_@$1^FD*j|Gj)!PhT>y_Kqf
zRKDpzV#XJ|jtR8x4x|rB9@H&?uTZRn4N*WWNGyS5{-jihA&@1-ph1tE9MG~R$ZF~0
z#7t206SRC8-oynLyx;&R#!*5*SH++gQNjMcuHhbzAqtL8{$Z~0*ar=gL)-xGTY+Zr
z!C_gHm<JxYfkb>sKD<E>Y8s|OS6$?TRwrgAXMlBpLq7?$Xc4r40yO_G#mK-=#{^mb
z58I!AmY;!P5<de&IX?q~BR>NJ6F&pP3qA&hi+l_WYxo!#rtmQ^<nS>tMDZ~&MDj5(
zSn)A1sPHi`+~s9p*v`wq(96rfP|3@{ki^Tt5Xj5G5Wvg8;K|Ftz{bnK@BzB!e<lwD
zLo#$7zyoduhK1Y=429eb4EEd%45Hi&4BxpRYyMY)#sjz*7?Qad7_7M%7_7J$7*x3!
z7~VtI|HpGOFvM{(FxYW2FtBqnFkIkZU^vggz_5pdfnh!e149l614A$e0|P$?1H(CX
z28L#K1_mQ`1_ncR28LH`3=HSl7#RB47#O127#O747#J?FGBB)UWnf5$uJQlH!oYBr
zg@K`&g@M6>g@J*Sg@NHUbPS*$x~^Z2nStRi69dB?CI*JJObiSYm>^*)#l*lM$;80$
zjgf)jD<cEL9!3U+iHr;k4WRKB21v^rF~|cQZG{af(Q2p{oG+m@5@>x)aYkwiY}^pk
z4hVwven15&aU+l*m7ta0@U>EI#4M);=>p-*G=)qBI|Tzo+frGfI6JcdT$H3`78RE$
z<mW*ODUfmy2A8yYD2-3hurm4pB1kC+!-6y#eIOAe3Bqs%=mUx%Nf3rBKp$8HNrEt}
zQ3_pCUy_kpoT^Y%P^k`CHmLwvNC~RU%2P9oQWQ#xGSd}uK?@@D(m^fD(gH~17GxF(
z7vUVR1j&LhL<P295U%Y5AYCA=3>pYUE-ArD0we>%<c2NA5T}AJXt`}sVqQvqt{#Na
z04;h4w@TwPz$-pcY=#Fi#&D>DHa?@uGgC@3P)t$=4Vi%#M}sDy6cY0kO4D;HAq420
zP&CD$VKU_Y1gNr1N-R#*MXoJUQbE10RM<8MP*8y|iNOU)C$PQ?D3O2@Zm~jfPJTIP
zDPT!PY9(l7y*v>#P?N8amRJmF7=SDTVR$HEj^~1;VHjc&vai5HHwB=92T*{(+8NMx
zP$p;rVF`Se2Q7eL<ItrA3L0QzKm|ofet|By*O6JQkdc|50a~S)nU@S&nv0s2VJ;@3
zM1#4W>`5$;0pJ3~1~#RvplgUIS>Wq$VV!8u{2gK<4-%Qk;|ECHe@*D95XcH>`APku
z4Jr(4K;1_EkOrtsp=9n06hIjBUm!sch6FK2(T!^g3_J!78ukK@jcY(>xS<0D@Yqza
zRfvv-*Qco^3WYifDfyrQbkGEzLN<H`Pe%dN^n|7^1yFl72-3JBRMCNFwz2KVO3w$m
z4%D;+nN|gzKFiF{gE$AXEXK$MkPv|<ItUjrH3=WV0_RC+$(C49oS#!#0^04Ckys4s
zy?`2Zkojm((?2mg5j;n&3$Kz>Q^5L3j9XkY+hDVB=4(*n9BD=x&c)$%aALqS5(o)N
z$l?MVMnERqA;k`82p`|RNU+->p^Uc3z(CIgVg&kX1NiV6IGI3~Ab`zLhA$vD&@%z`
zC_pIzyp|i@wMYduU%=y6P#u{HkfE()P<IT{Ljs!%TfPA5>4657bii8(U>zdV^)ir3
z6kPM^KpOhc8WpjW#)<(}2Nb0i<RpT2edXjRfT|nh%m!V04eqvpdV1jFw?XSez-u}f
zV6&gaC8>!i3Pt(J*$NQfLB~}=tKf?=lT#t<+d-99W{CoHM?z96XbuWAV_X97hJ*J<
zfd=E@OUWUN??DUMOA9hnKy4-+24zt92fR%b<lG!^_YxdLSs)Writ-D<yB3Q}z*<U+
zz+)efh0P%2aC-(c76y)b-Nf{~{Nj?#WJQn{Q$ds6sYQ9vd9=LZ%;J*Nyb?u7GXmUc
z0yiYUE36^iRM1|$-24>KJ{XXDK}`rqI)$!{0Xr8Q;b4}6tpbGBN36}s%S=vH01ZBX
z>VB+B5qq0J+Y6AF20#~vL(DAB1ud)q&D?<Z6M#1{pqK|AtB<aV&rgdl$}fpFhz0GQ
zgK`X!IYzNM3ZRX1ItsAuhcHbFwhBSfRyszp;DnhDU7>@qDgioy0}Y7MqWGc$$h<$O
z{D*L(!A(2_TUWsdG@($C33hg7ngT+~4zz_2QiDSTF^YhK%)DZd9gw`M46Xl)3M!R!
zK*<TV6Q=?;_YYSO$|2x=czNU{ZwAPE2<oM724w|s;szBWq$lqDA|1$juf&`ZP+|rR
z(&SWvYeJBLuo*dU&5@a(rvsk<U%<w|umE%bp8x{`?0i4azW)|}28I%T1_m#F1_o<>
z1_oJv28PRg3=F&Z7#Qa9F)&QzV_=xT$H36T$H0)w$H3sl$G{-P$G~uhmw{muF9SmZ
zF9U-CF9U-PFJ!;}V;%;Ey*vyIvv?R7YIztK9C;WR1b7%2&T}&`%;aWZsNiN`2;yd7
z(BWoa;O1svc*VuQa0I&cKM30Af62+fuz-_+p@5TtA)k|h!H1K9!I+bQL5-7vL6wt%
zK@mCz@REapVKxT?LmIU2FUP^aaD$zJ;R-tg!#Z}Te?bc$M)7C}jE2By2#kinXb23#
z5CFB8psktFGhaX_k(A_vy7k}<>)>!1J@W-Na-TYS<_lyEE~u-MRIC9$=OfxE7Bt{I
zdgjaMnJ?v_LmI%{R``e*QIk}OC8?ulzT~D3f-_%|Q}Rnd=b<P#DC9wU`k=Al0?_Cy
zd>j}uOaQJLG?X&ICtxU~<>%z&mxCrO(m{(BK!a;VpwminD!~(s;5GGm;B^$BttASe
z)00wDpzBJ&Cy6NNgC?J#r-^{aVW9RaL!@;Tpl3=!I^Uq9fD&^RGQkHtK-LL>M~o8F
z6EpMd!Q&gClSM$s3}se9rZr(h7I{iK3R-!vqr{*GiGeL4`ivXo18?A`(c~5AVLR~z
z-2ZRqV_-PW2buqeoxgvTpMjyDpMfEfpMfEPpMk-apMk-KpMimypMl{9O#L8iFO52B
zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtt2k0BD$ea4(|<xe&5cgV13PAeA6Y
c`f_UMNELX10b~LQgT@Zf&cH;RgsRB^09k)~C;$Ke

literal 0
HcmV?d00001

diff --git a/python/ur_simple_control/util/__pycache__/calib_board_hacks.cpython-310.pyc b/python/ur_simple_control/util/__pycache__/calib_board_hacks.cpython-310.pyc
index 984653c2a30827fec2c4c0d25253583930002d57..18ef112aef1717a31bc5af78a2f9a5da0aa64059 100644
GIT binary patch
delta 2889
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
BmskJ*

delta 2007
zcmdmQ^hBF4pO=@5fq{V`u{A1njpjr?8OEN8+SzKU{3$%yOhqoK?9B{O0x7&vf~kC|
z0;z({OpFXEjKN^6$v5$gK|M1A0|Ofa1A{XI14D5f0|P?|!ve+{hJ}o^3?&R%Oj*n|
zAQ6@l)*6Op#)XV23@MDg%qdKg47H3kj35;Y*lHLTGD<VlGM2EXFgG(YGSo1*FvN1!
zGL^8Wu+%WsFbXh$tSwZoVGL%_WcAZzyv16SoS&Cc#K^!fc^0Fa7soB8yn<V-iA6<;
zmABY(GV>C1(r>Zm6qghi-eSqmOD(>|oRgY&izP3=DEAg?K~ZL2i6-+c&Vu~n%#zIf
zyy9DodAAq~Rx%U`PPSock(2{@g^z)Ofs0XrQGk_$k%Liyk%h5Hc=Bzg&AcKE3=En~
zFG2o($vAm7b1)<C<oC={jQo?iSY)^b85kIfz=Y6bLl$LO6OdU#3=9k`jC_ndj8eQJ
zj3Ue&One~olr|T#B(ta}2BjvZR4SC@D<mi8WF{3QmZU1=7b&DxWR}<~L`Ul9#TM~z
z=HpaiW)zuh$TOdjck)G^0u+mUcx4zHCuj107f#7nsLU@_C{N5Q0T~D~V{$QHodhof
z1H&!W%)Elql3Oew(IOj=Lv1H>@*4zcgCqq~^HSW3Qd3ikGRsnZ^HWkaS&QsI5^RZi
z#pS6*MUEg1_8<{~G?=>hl8mC%#1x2!A-)DFkeuAlE6Er>c`3iIhCc%XLoyR6i9xXd
z0|NsGEWxZ{VqmCY$YQ8vntV!7zMi>;A&YGR`$C3VmJ;R#EHx|(8EaY78B&-QG1juB
zFxN8HFf3qQ$WY5(!m)s}h9Qfqh9Qf)hJ7J3BLi4HLl$=yPYpvBuOvej-$KS(j&z1v
z&Jz9_#%4wrhS-<2AoT(Z1Z&t9f|FSm+X5kwX*KK%gi}}+GS)LPz?h5-$X1kyED)_>
zU&siyNGydloe^Yl7EcPBBtw??0*Ms%g^Y_BOE|J57f2z=@GWG7$pta=F)%Weh^26(
zGlETndK5)PJp&^{4Oa?hHdE0e4F8BPWUS?`;anh$kbzjgkP++~t{TP^E(wNgh6#*C
zitupc0juT#g<}m%3b!Of4QmRw4Jgb77D(5yf_1W_a7r?ih-AssFOXTtkisLvAP!Q-
zX~R&%lEMX%0?Y7<Fi3!8xKIs%`kP}RV=ZrqSPEYaFDSp(@Pdp@VaaBhz*xiy<#CsY
zWXXa};Y|UV4^~sdn!<0xP{W&2&jofLJD3A;s{oo+ay6XIjJ13v@--Yae9cU?{DqDr
z`IR9H<Zl+Rzd;2R6NptJmLgcg-OL1vfBqWo8s;?SU<OSgzw}u%LExsnCL5@%VE_|Q
z!JYfTJOuF)RE`#bN{1p1P*za~5t<-E3q&x22r&?$#=yXkZVU#O?V+Zfv@fz?VBlsb
z5@lduc*)AZz%coPsB=9i^W0)d&M&CE#gUSlS^#FTq^Fhy7U_YEvIY@`Ai@Yl7=s8<
ziBn_>%7z?X{+@mz@t!V4Rv<2GQDR<tY7r#2=jNBChUS%I<~Zl)l_VyY6zPNX8h{8;
zX<oz*V%dO-jUqD;(;P%tfCx*lSs?vBx7dmj^HTD2Z!r~Q772qSl|Y4~0Jz|o%pz`4
ze~Y!a092+pfFxx>1gKoS#h3{;^%hTZX;D#XUP*jGesL-&1Q?3=L5dVX1h_l_6QJ_*
z79YHH49H2$OI-&lSkpk24>K1d2O}RN7ZVpF2MY@$2bU0|7!wN<4<ip_Jr^SgN-#<>
zN-=W$S7PE|5o45M;scBFF!L~h#CaHbn7A1E7{wTQz?yg%IT(4s#(|9BVdP>4nNgGq
z@;66(d~RZ9UVMB}0LZ68w>S$j^YW9EGcxmwK=E*kHLo<cpt1-YhBgc=3=Bmfld~jz
z0^C48f(KC%C}QCz<|XE)#>ayLttb|x4(w?J0rozJO>TZlX-=vgC?OSVOcsz76J=%M
X<=|wJ;^5>6=LlqDWMSfCXZZ#Ihu+FD

diff --git a/python/ur_simple_control/util/__pycache__/freedrive.cpython-310.pyc b/python/ur_simple_control/util/__pycache__/freedrive.cpython-310.pyc
index c2ca7a5fb770db91952c5fc6e1ccd4911a035ba4..cee8b4de6ae0da7de2eac77dc079fcd1ff3c6da2 100644
GIT binary patch
literal 1273
zcmd1j<>g{vU|`VgicbB(!octt#6iX^3=9ko3=9m#Z43+yDGVu$ISf&ZV45k48BDW8
zv4CmTDAp8)6s8=uT=pn-Mvz+O9FAPhC{9L(6qXd$7KSLU6t)!h7KSM9RGt)$Y^EZ|
zRL*9GDBe`|RNiLBD85wI1+1y8S^TM73z--hQn^$4ni&}xQn^wXQy80>7#UI+gTYvn
z^CifIewvK8c!Khi@=JUZ^Agiji!>Q;aiph~#3vS|7bi1;lt3|v4Z_YKf5<Q}FqAN4
zF)m<Q$iT=@!koegvZaKjnE~YHU<OSlzbc88{Jd0!^30M9g|wp7)RdykvQ!;~<jO=%
z)?2JaAS-Y26qTf;#wX|Jl@#UY+!9F5OL2p#^vzF6y~SEkl$lp@izT%pvqY2W7F%&<
zdR}SnE!MQ6#N5=C3`N`w3=F^0^fU5vQ}xsHiwp8o5{tk*BLp|6G%rQJpeV5-vsk~h
zD84u|w;%^@r+z_YNk)Di7Kzf5%p85VyY&hxZ?R`2=B4DM7V&}tfQ^BHfs2uYk&6+`
zPiBOM5{LqY5<3F}1307(F)%RHFk~?-U<8E}CqoSbD9maZOPCk1)G%bR)-YtTm9Q`1
zs9{{lxR9BVp@b78lEsz6B*_2{Q_d9TbVh_&7WV?46qbdIix^9ovv?QqA<6JBWQ55D
zG4z4rg)@aUoe^w0Lzch-!G#Q1RIou+Fk;9FEf7v&U&zSFP{^jq;TQ4}<mW1ug3LUt
zm!Je)#Zp>iYE{KlXq8?qvd;ZsRf)Z(ND(Uo1H&y|c))?9ktIE~B=8n<L1x}9!L<CM
z^2DMP@65c^+{BX1<l<Ybx%nxnIk#9+5=#<qG36E9VofY6N~|mb1>r5`eBaDl+$BYc
zdBr)2C7JnoprlipmvW1_sG#x|cWz=yQD#L*eo#T>Esmo65{ME=vMNeVPR%S!y(N&I
zTH=^oQks|(;v5i=Uz~c2r6e;q^%iS!PHJj_CQ}i}Gq)HE!Kn#C@PItQ3HO8$D8?ng
zG0w!q!6?Bfz$nEi#mMnriAjc$i;?L^kupdFM|^y4VrE`^yr#e{&VtOm{N&_}%={vd
z?pv&RrMU%_MPdvL3`Ghc#o)A@m~%@CBTee%LULkp5hx+u(!x}boRgWY2O{DN@-y>F
z;!E-&j3Q=`@u2hxcTiqpZfbn|Ef!FAhIo`M*wfw9F9hOIPzHjqz+UFC$<0qG%}KQb
jCFf!}1_lNW1`b9L<YDAt<zVJu<=|yw<Y43jW0v0lWhYng

delta 524
zcmey#d6rc>pO=@5fq{XcE+Q&5nwf#&F^GeVnHU%t92giFiajQ3%hfaGu;#Kwu`x2F
zFsHDzFhsGZa-^_kGZiVNvNbbAai+32GcYowFb0FMCfiGpNq(A)w|Ii`lk!V^6Y~<&
zQ;U)rLBdcBGM}A+fx#JMhaUq2Lk&X~!ve;I42%q%AU4wi=7kKkj5Ul4SW=kk7cw$3
zK$sv_3F`v38ip+P8ip*663zu&HH-@x7cw(4lyEQLNnr-5C}h)Q@e4_Z+QpDwEwax2
zVO5E}ChsktqLP%<_~iV&lA`>aTfAvSsi`SNnPsWI`6;PT$)eQc)XcKfTU_a>C637@
zrHNcQfw$Na3kp*6QYNc18_3>bDap)Dy~SFblbTwf$#jdg2;|LMjD;&1ii9RtG3JDF
z!p&s^c~F3Xfq{#WiHVC51SJ@`*qFW*i7+rQ+~SCj&rQtCi;vgjy2V+LnU|lOoROJd
z!~v3H%`43<s4U`PU|=ZXV_;yIY|WzR3)hyHn420OUj#C`NC>0^K?s9%bJ*nOr<CTT
d+JS<-7$nKTz`@AD$iv9N#KF(T$i>L=4*-6$dS3tl

diff --git a/python/ur_simple_control/util/__pycache__/get_model.cpython-310.pyc b/python/ur_simple_control/util/__pycache__/get_model.cpython-310.pyc
index 184950c3ec3f73f88e80199f281657e18a3678c9..565cc85c74e5580a485052c17069fe777cd20f1a 100644
GIT binary patch
delta 20
bcmX@Ze}<nspO=@5fq{WRFfMu{_d#|5GGGLw

delta 20
bcmX@Ze}<nspO=@5fq{YH?3VD2+y~hKIdlcF

diff --git a/python/ur_simple_control/util/calib_board_hacks.py b/python/ur_simple_control/util/calib_board_hacks.py
index 286ed50..c1db22c 100644
--- a/python/ur_simple_control/util/calib_board_hacks.py
+++ b/python/ur_simple_control/util/calib_board_hacks.py
@@ -25,11 +25,27 @@ Returns R because that's what's needed to construct the hom transf. mat.
 """
 fitNormalVector
 ----------------
-classic least squares fit
+classic least squares fit.
+TODO: since you're also fixing the orientation of the gripper as you go,
+and that changes the contact point (most grippers are a some shape at the end,
+not a single contact point,
+you should do a weighting of these points in the least squares
+---> the newer points are in fact more correct than old points!
 """
 def fitNormalVector(positions):
     positions = np.array(positions)
-    n = np.linalg.lstsq(positions, np.ones(len(positions)), rcond=None)[0]
+# non-weighted least square
+#    n = np.linalg.lstsq(positions, np.ones(len(positions)), rcond=None)[0]
+    # bs weights, just to weight the new things more and linear is probably good
+    # (altough it could/should be even more agressive probably)
+    # +1 to start with 1 (0 both doesn't make sense and is makes W singular)
+    W = np.diag(np.arange(1, len(positions) + 1))
+#    print("W", W)
+#    print("positions", positions)
+#    print("positions.T", positions.T)
+#    print("positions.T @ W @ positions", positions.T @ W @ positions)
+#    print("np.linalg.inv(positions.T @ W @ positions)", np.linalg.inv(positions.T @ W @ positions))
+    n = np.linalg.inv(positions.T @ W @ positions) @ positions.T @ W @ np.ones(len(positions))
     #print("n", *n, sep=',')
     # normalize
     # TODO why am i not doing this again?
@@ -100,7 +116,7 @@ def handleUserToHandleTCPPose(robot):
     When you did it, press 'Y', or press 'n' to exit.
     """)
     while True:
-        answer = input("Ready to calibrate or exit? [Y/n]")
+        answer = input("Ready to calibrate or no (no means exit program)? [Y/n]")
         if answer == 'n' or answer == 'N':
             print("""
     The whole program will exit. Change the argument to --no-calibrate or 
@@ -156,7 +172,7 @@ def handleUserToHandleTCPPose(robot):
     while True:
         answer = input("""
     I am assuming you got the end-effector in the correct pose. \n
-    Are you ready to start calibrating or do you want to exit? [Y/n]
+    Are you ready to start calibrating or not (no means exit)? [Y/n]
     """)
         if answer == 'n' or answer == 'N':
             print("The whole program will exit. Goodbye!")
@@ -170,8 +186,39 @@ def handleUserToHandleTCPPose(robot):
             continue
     robot.rtde_control.endFreedriveMode()
 
+# TODO FIX THIS UGLY HACK!!!!!!
+# as in make it mathematically correct somehow.
+# a good start would be ranges ur uses for it's thing.
+# or, TODO alternatively, do the correct solution,
+# drop the stupid ur code, and use your own implementation
+# of both movel and speedj
+# --> then you don't even need to use the stupid rpy,
+# but instead rock only rotation matrices the way it should be
+def fixPinsRPY(pins_rpy):
+    #print("rpy", rpy)
+    ur_rpy = copy.deepcopy(pins_rpy)
+    if ur_rpy[0] > 0.0:
+        ur_rpy[0] = ur_rpy[0] - 2*np.pi
+    return ur_rpy
 
-def calibratePlane(robot, n_tests):
+def getSpeedInDirectionOfN(R):
+    z_of_rot = R[:,2]
+    speed = np.array([z_of_rot[0], z_of_rot[1], z_of_rot[2], 0, 0, 0])
+    # make speed small no matter what
+    speed = speed / np.linalg.norm(speed)
+    # nice 'n' slow
+    speed = speed / 10
+    return speed
+
+# TODO
+# be internally consistent! this will also make this code modular,
+# and robot-agnostic!
+# drop all stupid ur code, and use your own implementation
+# of both movel and speedj.
+# --> then you don't even need to use the stupid rpy,
+# but instead rock only rotation matrices the way it should be.
+# TODO: replace all moveUntilContacts with your own implementation
+def calibratePlane(robot, plane_width, plane_height, n_tests):
     # i don't care which speed slider you have,
     # because 0.4 is the only reasonable one here
     old_speed_slider = robot.speed_slider
@@ -179,43 +226,27 @@ def calibratePlane(robot, n_tests):
     handleUserToHandleTCPPose(robot)
     q_init = copy.deepcopy(robot.getQ())
 
-    init_pose = robot.rtde_receive.getActualTCPPose()
+    init_pose = copy.deepcopy(robot.rtde_receive.getActualTCPPose())
     new_pose = copy.deepcopy(init_pose)
 
-    # TODO change this, i just shoved the pen through the board
-    # the point is go up, but the frame is the TCP frame
-    speed = [0, 0, -0.1, 0, 0, 0]
-    n_tests = 10
-    # TODO: for the love of god please actually read this when you begin
-    # instead of having this horror here
-    # NOTE: old code remains here until fix is tested
-    #R = np.array([[1.,         0.,         0.03236534],
-    #[ 0.,         -0.82404727,  0.56559577],
-    #[ 0. ,        -0.56559577, -0.82404727]])
-    # get q, do forward kinematics, get current TCP R 
-    # NOTE: this is supposed to be run only after the initial TCP has been set
-    # TODO: move [above_sentence_code] into this function to ensure that's the case
     q = robot.getQ()
     pin.forwardKinematics(robot.model, robot.data, q)
     # this apsolutely has to be deepcopied aka copy-constructed
     R_initial_estimate = copy.deepcopy(robot.data.oMi[robot.JOINT_ID].rotation)
 
+    # go in the TCP z direction
+    speed = getSpeedInDirectionOfN(R_initial_estimate)
+    # get q, do forward kinematics, get current TCP R 
+
     positions = []
     for i in range(n_tests):
         robot.rtde_control.moveUntilContact(speed)
-        q = robot.rtde_receive.getActualQ()
-        q.append(0.0)
-        q.append(0.0)
+        q = robot.getQ()
         pin.forwardKinematics(robot.model, robot.data, np.array(q))
         print("pin:", *robot.data.oMi[6].translation.round(4), \
                 *pin.rpy.matrixToRpy(robot.data.oMi[6].rotation).round(4))
         print("ur5:", *np.array(robot.rtde_receive.getActualTCPPose()).round(4))
 
-        # the first contact point is the translation vector 
-        # --> this is how the whole program is set up
-        if i == 0:
-            translation = copy.deepcopy(robot.data.oMi[robot.JOINT_ID].translation)
-
         positions.append(copy.deepcopy(robot.data.oMi[6].translation))
         if i < n_tests -1:
             current_pose = robot.rtde_receive.getActualTCPPose()
@@ -225,27 +256,64 @@ def calibratePlane(robot, n_tests):
             new_pose[2] = init_pose[2]
             # TODO make these moveLs slower, they're way too fast
             robot.rtde_control.moveL(new_pose)
-            new_pose[0] = init_pose[0] + np.random.random() * 0.3
-            new_pose[1] = init_pose[1] - np.random.random() * 0.2
+            # TODO: make this not base-orientation dependent,
+            # this is also an ugly ugly hack
+            new_pose[0] = init_pose[0] + np.random.random() * plane_width
+            new_pose[1] = init_pose[1] - np.random.random() * plane_height
             robot.rtde_control.moveL(new_pose)
             # fix orientation
             rpy = pin.rpy.matrixToRpy(R_initial_estimate)
-            print("rpy", rpy)
-            if rpy[0] > 0.0:
-                rpy[0] = rpy[0] - 2*np.pi
+            rpy = fixPinsRPY(rpy)
             # TODO: ensure these rpy's make sense (no weird trig messing it up)
             new_pose[3] = rpy[0]
             new_pose[4] = rpy[1]
             new_pose[5] = rpy[2]
             robot.rtde_control.moveL(new_pose)
-        n = fitNormalVector(positions)
-        R = constructFrameFromNormalVector(R_initial_estimate, n)
+        # skip the first one
+        if i > 0:
+            n = fitNormalVector(positions)
+            R = constructFrameFromNormalVector(R_initial_estimate, n)
+            speed = getSpeedInDirectionOfN(R)
+
+    print("finished estimating R")
 
     current_pose = robot.rtde_receive.getActualTCPPose()
     new_pose = copy.deepcopy(current_pose)
+    # go back up
+    new_pose[2] = init_pose[2]
+    robot.rtde_control.moveL(new_pose)
+    # go back to the same spot
+    new_pose[0] = init_pose[0]
+    new_pose[1] = init_pose[1]
     new_pose[2] = init_pose[2]
+    # but in new orientation
+    rpy = pin.rpy.matrixToRpy(R)
+    rpy = fixPinsRPY(rpy)
+    new_pose[3] = rpy[0]
+    new_pose[4] = rpy[1]
+    new_pose[5] = rpy[2]
     robot.rtde_control.moveL(new_pose)
-    robot.rtde_control.moveL(init_pose)
+    # --> now you're ready to measure the translation vector correctly
+    # for this we want to go directly into the board
+    print("i'll estimate the translation vector now")
+    speed = getSpeedInDirectionOfN(R)
+    robot.rtde_control.moveUntilContact(speed)
+
+    q = robot.getQ()
+    pin.forwardKinematics(robot.model, robot.data, np.array(q))
+    translation = copy.deepcopy(robot.data.oMi[robot.JOINT_ID].translation)
+    print("got translation vector, it's:", translation)
+
+    # TODO: get rid of all movels, just your own stuff,
+    # or at least shove them avait to the RobotManager
+    # and now go back up
+    current_pose = robot.rtde_receive.getActualTCPPose()
+    new_pose = copy.deepcopy(current_pose)
+    new_pose[2] = init_pose[2]
+    robot.rtde_control.moveL(new_pose)
+    q = robot.getQ()
+    init_q = copy.deepcopy(q)
+    print("went back up, saved this q as initial q")
     
     # put the speed slider back to its previous value
     robot.setSpeedSlider(old_speed_slider)
diff --git a/python/ur_simple_control/util/freedrive.py b/python/ur_simple_control/util/freedrive.py
index 552333a..e5a55d8 100644
--- a/python/ur_simple_control/util/freedrive.py
+++ b/python/ur_simple_control/util/freedrive.py
@@ -1,25 +1,38 @@
 import pinocchio as pin
 import numpy as np
 import time
+import signal
 from ur_simple_control.managers import RobotManager
+# TODO: put sane default arguments needed just for managers 
+# into a separate file, call it default arguments.
+# ideally you also only need to add your additional ones
+# to this list.
+from ur_simple_control.clik.clik_point_to_point import get_args
+
+
+def handler(signum, frame):
+    robot.rtde_control.endFreedriveMode()
+    print("done with freedrive, cya")
+    exit()
 
 def freedrive(robot):
     robot.rtde_control.freedriveMode()
 
     while True:
-        q = robot.rtde_receive.getActualQ()
-        q.append(0.0)
-        q.append(0.0)
+        q = robot.getQ()
         pin.forwardKinematics(robot.model, robot.data, np.array(q))
-    #    print(robot.data.oMi[6])
-    #    print("pin:", *robot.data.oMi[6].translation.round(4), \
-    #            *pin.rpy.matrixToRpy(robot.data.oMi[6].rotation).round(4))
-    #    print("ur5:", *np.array(robot.rtde_receive.getActualTCPPose()).round(4))
-    #    print("q:", *np.array(q).round(4))
+        print(robot.data.oMi[6])
+        print("pin:", *robot.data.oMi[6].translation.round(4), \
+                *pin.rpy.matrixToRpy(robot.data.oMi[6].rotation).round(4))
+        print("ur5:", *np.array(robot.rtde_receive.getActualTCPPose()).round(4))
+        print("q:", *np.array(q).round(4))
         time.sleep(0.005)
 
 if __name__ == "__main__":
-    robot = RobotManager()
-    freedrive()
+    args = get_args()
+    robot = RobotManager(args)
+    signal.signal(signal.SIGINT, handler)
+    freedrive(robot)
+    handler(None, None)
     # TODO possibly you want to end freedrive here as well.
     # or end everything imaginable in the signal handler 
-- 
GitLab