From 1390dac8b83f8d2f8fa05b9f4343db3e2db1bd8a Mon Sep 17 00:00:00 2001
From: m-guberina <gubi.guberina@gmail.com>
Date: Fri, 22 Mar 2024 16:51:49 +0100
Subject: [PATCH] some light viz work, nothing yet, just need to get something
 from main

---
 python/examples/drawing_from_input_drawing.py |  12 +-
 .../planar_dragging_via_top_contact_force.py  |  10 +-
 python/examples/point_impedance_control.py    |   1 -
 python/examples/test_gripper.py               |   1 -
 .../__pycache__/__init__.cpython-311.pyc      | Bin 443 -> 443 bytes
 .../__pycache__/managers.cpython-311.pyc      | Bin 17146 -> 17667 bytes
 .../clik/__pycache__/__init__.cpython-311.pyc | Bin 219 -> 219 bytes
 .../clik/clik_point_to_point.py               |   7 +-
 .../dmp/__pycache__/__init__.cpython-311.pyc  | Bin 218 -> 218 bytes
 python/ur_simple_control/managers.py          | 170 +++++------
 .../__pycache__/__init__.cpython-311.pyc      | Bin 233 -> 233 bytes
 .../urdf/__pycache__/__init__.cpython-311.pyc | Bin 238 -> 238 bytes
 .../util/__pycache__/__init__.cpython-311.pyc | Bin 219 -> 219 bytes
 .../__pycache__/get_model.cpython-311.pyc     | Bin 4008 -> 4184 bytes
 .../robotiq_gripper.cpython-311.pyc           | Bin 19662 -> 19662 bytes
 python/ur_simple_control/util/default_args.py | 129 +-------
 python/ur_simple_control/util/draw_path.py    |  34 ++-
 python/ur_simple_control/util/get_model.py    |   7 +-
 .../ur_simple_control/util/logging_utils.py   |   6 +-
 .../__pycache__/__init__.cpython-311.pyc      | Bin 224 -> 224 bytes
 .../pin_to_vedo_plot_util.cpython-311.pyc     | Bin 0 -> 5748 bytes
 .../__pycache__/visualize.cpython-311.pyc     | Bin 1726 -> 1726 bytes
 .../visualize/pin_to_vedo_plot_util.py        |   3 +-
 .../visualize/vedo_manipulator.py             | 285 +++++-------------
 24 files changed, 200 insertions(+), 465 deletions(-)
 create mode 100644 python/ur_simple_control/visualize/__pycache__/pin_to_vedo_plot_util.cpython-311.pyc

diff --git a/python/examples/drawing_from_input_drawing.py b/python/examples/drawing_from_input_drawing.py
index 35e0e69..a0b8d64 100644
--- a/python/examples/drawing_from_input_drawing.py
+++ b/python/examples/drawing_from_input_drawing.py
@@ -15,7 +15,6 @@ 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.dmp.dmp import DMP, NoTC,TCVelAccConstrained 
@@ -295,7 +294,7 @@ def controller():
 # to find option 3)
 
 # control loop to be passed to ControlLoopManager
-def controlLoopWriting(wrench_offset, dmp, tc, controller, robot, i, past_data):
+def controlLoopWriting(dmp, tc, controller, robot, i, past_data):
     breakFlag = False
     # TODO rename this into something less confusing
     save_past_dict = {}
@@ -325,7 +324,6 @@ def controlLoopWriting(wrench_offset, dmp, tc, controller, robot, i, past_data):
 
     #Z = np.diag(np.array([1.0, 0.6, 1.0, 0.5, 0.5, 0.5]))
     wrench = robot.getWrench()
-    wrench = wrench - wrench_offset
     # deepcopy for good coding practise (and correctness here)
     save_past_dict['wrench'] = copy.deepcopy(wrench)
     # rolling average
@@ -387,8 +385,8 @@ if __name__ == "__main__":
     robot = RobotManager(args)
 
     # calibrate FT first
-    wrench_offset = robot.calibrateFT()
-    robot.wrench_offset = wrench_offset
+    # it's done by default now because it's basically always necessary
+
     #######################################################################
     #          drawing a path, making a joint trajectory for it           #
     #######################################################################
@@ -396,7 +394,7 @@ if __name__ == "__main__":
     
     # draw the path on the screen
     if args.draw_new:
-        pixel_path = drawPath()
+        pixel_path = drawPath(args)
         # make it 3D
     else:
         pixel_path_file_path = './path_in_pixels.csv'
@@ -523,7 +521,7 @@ if __name__ == "__main__":
             'dqs' : np.zeros((args.max_iterations, 6)),
             'dmp_vels' : np.zeros((args.max_iterations, 6)),
         }
-    controlLoop = partial(controlLoopWriting, wrench_offset, dmp, tc, controller, robot)
+    controlLoop = partial(controlLoopWriting, dmp, tc, controller, robot)
     loop_manager = ControlLoopManager(robot, controlLoop, args, save_past_dict, log_dict)
     #######################################################################
     #                           physical setup                            #
diff --git a/python/examples/planar_dragging_via_top_contact_force.py b/python/examples/planar_dragging_via_top_contact_force.py
index 653485e..171b444 100644
--- a/python/examples/planar_dragging_via_top_contact_force.py
+++ b/python/examples/planar_dragging_via_top_contact_force.py
@@ -5,7 +5,6 @@ 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.dmp.dmp import DMP, NoTC,TCVelAccConstrained 
@@ -153,7 +152,7 @@ def controller():
 
 
 # control loop to be passed to ControlLoopManager
-def controlLoopPlanarDragging(wrench_offset, dmp, tc, controller, robot, i, past_data):
+def controlLoopPlanarDragging(dmp, tc, controller, robot, i, past_data):
     breakFlag = False
     # TODO rename this into something less confusing
     save_past_dict = {}
@@ -166,7 +165,6 @@ def controlLoopPlanarDragging(wrench_offset, dmp, tc, controller, robot, i, past
     Z = np.diag(np.ones(6))
 
     wrench = robot.getWrench()
-    wrench = wrench - wrench_offset
     wrench = np.average(np.array(past_data['wrench']), axis=0)
 
     # first-order low pass filtering 
@@ -175,7 +173,7 @@ def controlLoopPlanarDragging(wrench_offset, dmp, tc, controller, robot, i, past
     #wrench = beta * wrench + (1 - beta) * past_data['wrench'][-1]
 
     wrench = robot.getMtool().toDualActionMatrix().T @ wrench
-    wrench = Z @ robot.getWrench()
+    wrench = Z @ wrench
     # deepcopy for good coding practise (and correctness here)
     save_past_dict['wrench'] = copy.deepcopy(wrench)
     # rolling average
@@ -214,8 +212,6 @@ if __name__ == "__main__":
     robot = RobotManager(args)
 
     # calibrate FT first
-    wrench_offset = robot.calibrateFT()
-
     speed_down = np.array([0,0,-1,0,0,0])
     moveUntilContact(args, robot, speed_down)
     m_goal_up = robot.getMtool()
@@ -230,7 +226,7 @@ if __name__ == "__main__":
 #    log_dict = {
 #            'wrench': np.zeros((args.max_iterations, 6)),
 #        }
-#    controlLoop = partial(controlLoopPlanarDragging, wrench_offset, dmp, tc, controller, robot)
+#    controlLoop = partial(controlLoopPlanarDragging, dmp, tc, controller, robot)
 #    loop_manager = ControlLoopManager(robot, controlLoop, args, save_past_dict, log_dict)
 #    #######################################################################
 #    #                           physical setup                            #
diff --git a/python/examples/point_impedance_control.py b/python/examples/point_impedance_control.py
index 78ad110..d1d06e4 100644
--- a/python/examples/point_impedance_control.py
+++ b/python/examples/point_impedance_control.py
@@ -5,7 +5,6 @@ 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.dmp.dmp import DMP, NoTC,TCVelAccConstrained 
diff --git a/python/examples/test_gripper.py b/python/examples/test_gripper.py
index 366a6a5..6613fdd 100644
--- a/python/examples/test_gripper.py
+++ b/python/examples/test_gripper.py
@@ -6,7 +6,6 @@ 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
diff --git a/python/ur_simple_control/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/__pycache__/__init__.cpython-311.pyc
index 6730f1e95d99f25500f6b1680857af2968134e4f..e6536f859f51b8b8a17c0032e2d11854161023ad 100644
GIT binary patch
delta 20
bcmdnZyqlSOIWI340|Ntto5`Pz+#47HH0A|1

delta 20
ccmdnZyqlSOIWI340|NuYx?9m3xi>HZ062XGqW}N^

diff --git a/python/ur_simple_control/__pycache__/managers.cpython-311.pyc b/python/ur_simple_control/__pycache__/managers.cpython-311.pyc
index 26120b0cff823e6d4bc7f91a37548db23576a5ab..89732ed96ef8a84e5f69a8c8ee92ef71e3c71bee 100644
GIT binary patch
delta 4669
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
Ru#+Fb;$OfdrW$Z@1OTdxJ#hd4

delta 4431
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
OSo{l^#8d<BjsgG&%^&yx

diff --git a/python/ur_simple_control/clik/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/clik/__pycache__/__init__.cpython-311.pyc
index 46c82e11fbe0ff3bb421e7f1e4c8aec6e35c9363..47dfd580761c955ca39175dd03a865d137c0bcb2 100644
GIT binary patch
delta 19
acmcc3c$<-XIWI340|Ntto5`Pv+!p{dtOaoZ

delta 19
acmcc3c$<-XIWI340|Ns?#ES5V+!p{d$OTdW

diff --git a/python/ur_simple_control/clik/clik_point_to_point.py b/python/ur_simple_control/clik/clik_point_to_point.py
index c101839..b20bdc6 100644
--- a/python/ur_simple_control/clik/clik_point_to_point.py
+++ b/python/ur_simple_control/clik/clik_point_to_point.py
@@ -182,10 +182,9 @@ def moveUntilContactControlLoop(speed, robot, clik_controller, i, past_data):
     pin.forwardKinematics(robot.model, robot.data, q)
     # break if wrench is nonzero basically
     wrench = robot.getWrench()
-    # TODO: move this to the robot class
-    wrench = wrench - robot.wrench_offset
-    # TODO: remove magick number
-    # it is empirical bla bla, but make it an argument at least
+    # NOTE: this 4.2 is a magic number
+    # it is a 100% empirical, with the goal being that it's just above noise.
+    # so far it's worked fine, and it's pretty soft too.
     if np.linalg.norm(wrench) > 4.2:
         print("hit with", np.linalg.norm(wrench))
         breakFlag = True
diff --git a/python/ur_simple_control/dmp/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/dmp/__pycache__/__init__.cpython-311.pyc
index 6d20d4dc491caffb2381d4d29f6e5fa47875ecf5..94aa9adee31a8c24a5d1149f612b7a8a46762036 100644
GIT binary patch
delta 19
acmcb`c#DyHIWI340|Ntto5`Pv+~)x^hXrl`

delta 19
acmcb`c#DyHIWI340|Ns?%!=@d+~)x^y9HAK

diff --git a/python/ur_simple_control/managers.py b/python/ur_simple_control/managers.py
index 4fba119..689d5b2 100644
--- a/python/ur_simple_control/managers.py
+++ b/python/ur_simple_control/managers.py
@@ -1,14 +1,13 @@
-# TODO clear out unnecessary imports
 # TODO rename all private variables to start with '_'
 # TODO: just read the q and update everything every timestep, don't deepcopy,
+# TODO: rewrite all getSomething functions to updateSomething functions,
+#       and then make the getSomething function just be return self.something.copy()
 # --> just create a RobotManager.step() function, update everything there
 # don't do forwardKinematics 2 extra times for no good reason. make that the libraries
 # responsibility, not the users
 import pinocchio as pin
 import numpy as np
 import time
-from pinocchio.visualize import GepettoVisualizer
-#import gepetto.corbaserver
 from rtde_control import RTDEControlInterface
 from rtde_receive import RTDEReceiveInterface
 from rtde_io import RTDEIOInterface
@@ -102,8 +101,6 @@ class ControlLoopManager:
     def __init__(self, robot_manager, controlLoop, args, save_past_dict, log_dict):
         signal.signal(signal.SIGINT, self.stopHandler)
         self.max_iterations = args.max_iterations
-        # NOTE the robot manager is all over the place, 
-        # there might be a better design approach to that
         self.robot_manager = robot_manager
         self.controlLoop = controlLoop
         self.args = args
@@ -115,8 +112,8 @@ class ControlLoopManager:
             self.past_data[key] = deque()
             # immediatelly populate every deque with initial values
             for i in range(args.past_window_size):
-                # deepcopy just in case, better safe than sorry. 
-                # and we can be slow with initialization.
+                # deepcopy just in case, better safe than sorry plus it's during initialization,
+                # not real time
                 self.past_data[key].append(copy.deepcopy(save_past_dict[key]))
 
         # similar story for log_dict as for past_data,
@@ -145,7 +142,7 @@ class ControlLoopManager:
             # TODO: write an assert assuring the keys are what's been promised
             # (ideally this is done only once, not every time, so think whether/how that can be avoided)
             for key in latest_to_save_dict:
-                # remove oldes entry
+                # remove oldest entry
                 self.past_data[key].popleft()
                 # add new entry
                 self.past_data[key].append(latest_to_save_dict[key])
@@ -159,9 +156,6 @@ class ControlLoopManager:
                     #self.robot_manager.stopHandler(None, None)
                 self.log_dict[key][i] = log_entry_dict[key]
             
-            #for key in log_entry_dict:
-            #    self.log_dict[key][i] = log_entry_dict[key]
-
             # break if done
             if breakFlag:
                 break
@@ -174,27 +168,24 @@ class ControlLoopManager:
             else:
                 time.sleep(self.robot_manager.dt - diff)
             self.final_iteration = i
-# TODO: provide a debug flag for this
-#        if i < self.max_iterations -1:
-#            print("success in", i, "iterations!")
-#        else:
-#            print("FAIL: did not succed in", max_iterations, "iterations")
-# TODO: reintroduce maybe
-#        if not self.args.pinocchio_only:
-#            self.robot_manager.stopHandler(None, None)
+        if args.debug_prints:
+            if i < self.max_iterations -1:
+                print("success in", i, "iterations!")
+            else:
+                print("FAIL: did not succed in", max_iterations, "iterations")
 
         return self.log_dict, self.final_iteration
 
     """
     stopHandler
     -----------
-    TODO: make ifs for simulation too
-    can have self as first argument apparently.
     upon receiving SIGINT it sends zeros for speed commands to
-    stop the robot
+    stop the robot.
+    NOTE: apparently this isn't enough,
+          nor does stopJ do anything, so it goes to freedriveMode
+          and exists, which actually stops it.
     """
     def stopHandler(self, signum, frame):
-        #plotFromDict(signum, frame)
         print('sending 300 speedjs full of zeros and exiting')
         for i in range(300):
             vel_cmd = np.zeros(6)
@@ -207,11 +198,12 @@ class ControlLoopManager:
         self.robot_manager.rtde_control.freedriveMode()
         plotFromDict(self.log_dict, self.final_iteration, self.args)
         self.robot_manager.rtde_control.endFreedriveMode()
-        #exit()
 
 """
 robotmanager:
 ---------------
+- design goal: rely on pinocchio as much as possible while
+               concealing obvious bookkeeping
 - right now it is assumed you're running this on UR5e so some
   magic numbers are just put to it.
   this will be extended once there's a need for it.
@@ -225,25 +217,14 @@ robotmanager:
   actually run at 500Hz and not more.
 - this is probably not the most new-user friendly solution,
   but it's designed for fastest idea to implementation rate.
-- NOTE and TODO: rely on pinocchio as much as possible.
-  do NOT copy data that's already present in pin.model and pin.data,
-  it's just confusing. this lib already heavily relies on pinocchio,
-  let's just lean into that all the way and not invent hot water.
-- TODO: write out default arguments needed
+- if this was a real programming language, all of these would be private variables.
+- TODO: write out default arguments needed here as well
 """
 class RobotManager:
     # just pass all of the arguments here and store them as is
     # so as to minimize the amount of lines.
     # might be changed later if that seems more appropriate
-    # TODO: put the end to all modes not compatible with control
-    #       like freedrive or forcemode or whatever.
-    #       you shouldn't care about previous states
     def __init__(self, args):
-        # if you just stop it the program with Ctrl-C, it will continue running
-        # the last speedj lmao.
-        # there's also an actual stop command, but sending 0s works so i'm not changing it
-        #signal.signal(signal.SIGINT, self.stopHandler)
-
         self.args = args
         self.pinocchio_only = args.pinocchio_only
         self.simulation = args.simulation
@@ -253,58 +234,61 @@ class RobotManager:
         self.model, self.collision_model, self.visual_model, self.data = \
              get_model(args.visualize)
         # TODO: fix this
+        # ---> TODO: write your own vedo 3D visualzier,
+        #            connect it with the real-time matplotlib line plots,
+        #            and add some basic gui control (show/don't show stuff,
+        #            define a goal point, choose controller etc)
         if args.visualize:
             raise NotImplementedError('Paths in the urdf or something else need to \
                     be fixed to use this first. Sorry. Coming soon.')
             pass
-            # run visualizer from code (not working atm)
-            #gepetto.corbaserver.start_server()
-            #time.sleep(3)
-            #viz = GepettoVisualizer(model, collision_model, visual_model)
-            #viz.initViewer()
-            #viz.loadViewerModel()
-            #viz.display(q0)
+
         # TODO: make general
         if self.gripper_flag and not self.pinocchio_only:
             self.gripper = RobotiqGripper()
             self.gripper.connect("192.168.1.102", 63352)
             self.gripper.activate()
-        # TODO: this is obviously at least a partial redundancy w.r.t. the pinocchio data object
-        #        however i have no time to investigate what i get or don't get there
-        #        so i'll just leave this be. but fix this!!!! we don't want to duplicate information!!
+
         # also TODO: figure out how to best solve the gripper_velocity problem
-        #self.q = np.zeros(6)
-        #self.qd = np.zeros(6)
-        #self.qdd = np.zeros(6)
-        #self.gripper_pos = 0.0
-        #self.gripper_past_pos = 0.0
-        # set q,qd,qdd,griper_pos, gripper_past_pos, gripper_vel to dummy values
+        # NOTE: you need to initialize differently for other types of joints
+        self.q = np.zeros(self.model.nq)
+        # v_q is the generalization of qd for every type of joint.
+        # for revolute joints it's qd, but for ex. the planar joint it's the body velocity.
+        self.v_q = np.zeros(self.model.nv)
+        # same note as v_q, but it's a_q. 
+        self.a_q = np.zeros(self.model.nv)
         # initialize and connect the interfaces
         self.simulation = args.simulation
-        if self.pinocchio_only:
-            self.q = pin.neutral(self.model)
-        elif not args.simulation:
-            # NOTE: you can't connect twice, dw 'bout that
+        if (not args.simulation) and (not args.pinocchio_only) :
+            # NOTE: you can't connect twice, so you can't have more than one RobotManager.
+            # if this produces errors like "already in use", and it's not already in use,
+            # try just running your new program again. it could be that the socket wasn't given
+            # back to the os even though you've shut off the previous program.
             print("CONNECTING TO UR5e!")
             self.rtde_control = RTDEControlInterface("192.168.1.102")
             self.rtde_receive = RTDEReceiveInterface("192.168.1.102")
             self.rtde_io = RTDEIOInterface("192.168.1.102")
-            if args.gripper:
+            # NOTE: the force/torque sensor just has large offsets for no reason,
+            # and you need to minus them to have usable readings.
+            # we provide this with calibrateFT
+            self.wrench_offset = self.calibrateFT()
+            if self.gripper_flag:
                 self.gripper.connect("192.168.1.102", 63352)
                 # this is a blocking call
                 # this isn't actually needed and it's annoying
                 # TODO: test after rebooting the robot
 #                self.gripper.activate()
-        else:
+        elif not args.pinocchio_only:
             self.rtde_control = RTDEControlInterface("127.0.0.1")
             self.rtde_receive = RTDEReceiveInterface("127.0.0.1")
             self.rtde_io = RTDEIOInterface("127.0.0.1")
 
         # ur specific magic numbers 
+        # NOTE: all of this is ur-specific, and needs to be if-ed if other robots are added.
         # TODO: this is 8 in pinocchio and that's what you actually use 
         # if we're being real lmao
         # the TODO here is make this consistent obviously
-        self.n_joints = 6
+        self.n_arm_joints = 6
         # last joint because pinocchio adds base frame as 0th joint.
         # and since this is unintuitive, we add the other variable too
         # so that the control designer doesn't need to think about such bs
@@ -314,28 +298,23 @@ class RobotManager:
         # you better not give me crazy stuff
         # and i'm not clipping it, you're fixing it
         assert args.acceleration <= 1.7 and args.acceleration > 0.0
-        # we're not saying it's qdd because it isn't directly (apparently)
-        # TODO: check that again
+        # this is the number passed to speedj
         self.acceleration = args.acceleration
+        # NOTE: this is evil and everything only works if it's set to 1
+        # you really should control the acceleration via the acceleration argument.
         assert args.speed_slider <= 1.0 and args.acceleration > 0.0
         self.speed_slider = args.speed_slider
         if not args.pinocchio_only:
             self.rtde_io.setSpeedSlider(args.speed_slider)
-        self.max_iterations = args.max_iterations
         # TODO: these are almost certainly higher
         # NOTE and TODO: speed slider is evil, put it to 1, handle the rest yourself.
-        # maybe you want to have them high and cap the rest with speed slider?
-        # idk really, but it's better to have this low and burried for safety and robot longevity reasons
-        self.max_qdd = 1.7 * args.speed_slider
-        # NOTE: i had this thing at 2 in other code
+        # NOTE: i have no idea what's the relationship between max_qdd and speed slider
+        #self.max_qdd = 1.7 * args.speed_slider
+        # NOTE: this is an additional kinda evil speed limitation (by this code, not UR).
+        # we're clipping joint velocities with this.
+        # if your controllers are not what you expect, you might be commanding a very high velocity,
+        # which is clipped, resulting in unexpected movement.
         self.max_qd = 0.5 * args.speed_slider
-        # error limit 
-        # TODO this is clik specific, put it in a better place
-        self.goal_error = args.goal_error
-        # this is probably the right place to manage this
-        self.wrench_offset = np.zeros(6)
-
-
 
     """
     calibrateFT
@@ -354,10 +333,7 @@ class RobotManager:
         print("Use this as offset.")
         for i in range(2000):
             start = time.time()
-            q = self.rtde_receive.getActualQ()
             ft = self.rtde_receive.getActualTCPForce()
-            tau = self.rtde_control.getJointTorques()
-            current = self.rtde_receive.getActualCurrent()
             ft_readings.append(ft)
             end = time.time()
             diff = end - start
@@ -365,10 +341,9 @@ class RobotManager:
                 time.sleep(self.dt - diff)
 
         ft_readings = np.array(ft_readings)
-        avg = np.average(ft_readings, axis=0)
-        self.wrench_offset = avg
-        print("average ft time", avg)
-        return avg
+        self.wrench_offset = np.average(ft_readings, axis=0)
+        print(self.wrench_offset)
+        return self.wrench_offset.copy()
 
     """
     step
@@ -395,9 +370,14 @@ class RobotManager:
     def step(self):
         self.getQ()
         self.getQd()
-        self.wrench = np.array(self.rtde_receive.getActualTCPForce())
-        pin.forwardKinematics(self.model, self.data, self.q)
-        self.Mtool = self.data.oMi[self.JOINT_ID]
+        self.getWrench()
+        # certainly not necessary btw
+        # but if it runs on time, does it matter? it makes everything available...
+        pin.computeAllTerms(self.model, self.data, self.q, self.v_q)
+        self.T_w_e = self.data.oMi[self.JOINT_ID].copy()
+        # this isn't real because we're on a velocity-controlled robot, 
+        # so this is actually None (no tau, no a_q, as expected)
+        self.a_q = self.data.ddq
 
     """
     setSpeedSlider
@@ -488,8 +468,8 @@ class RobotManager:
         self.q = q
         pin.forwardKinematics(self.model, self.data, q)
         # TODO probably remove deepcopy
-        self.Mtool = self.data.oMi[self.JOINT_ID]
-        return copy.deepcopy(self.Mtool)
+        self.T_w_e = self.data.oMi[self.JOINT_ID]
+        return self.T_w_e.copy()
 
     """
     getQd
@@ -522,11 +502,8 @@ class RobotManager:
         # let's just have both options for getting q, it's just a 8d float list
         # readability is a somewhat subjective quality after all
             qd = np.array(qd)
-            self.qd = qd
-        # TODO make sure this makes sense
-        else:
-            return self.qd
-        return qd
+            self.v_q = qd
+        return self.v_q.copy()
 
     """
     getWrench
@@ -536,14 +513,17 @@ class RobotManager:
     here because this things depend on the arguments which are manager here (hence the 
     class name RobotManager)
     """
-    def getWrench(self):
+    def getWrenchRaw(self):
         if not self.pinocchio_only:
             wrench = np.array(self.rtde_receive.getActualTCPForce())
         else:
             raise NotImplementedError("Don't have time to implement this right now.")
-
         return wrench
 
+    def getWrench(self):
+        self.wrench = np.array(self.rtde_receive.getActualTCPForce()) - self.wrench_offset
+        return self.wrench.copy()
+
     """
     sendQd
     -----
@@ -584,7 +564,7 @@ class RobotManager:
         q = self.getQ()
         # define goal
         pin.forwardKinematics(self.model, self.data, np.array(q))
-        Mtool = self.data.oMi[self.JOINT_ID]
+        T_w_e = self.data.oMi[self.JOINT_ID]
         if not self.args.visualize:
             print("You can only specify the translation right now.")
             if not self.pinocchio_only:
@@ -596,7 +576,7 @@ class RobotManager:
             # remain with the current orientation
             # TODO: add something, probably rpy for orientation because it's the least number
             # of numbers you need to type in
-            Mgoal = copy.deepcopy(Mtool)
+            Mgoal = T_w_e.copy()
             # this is a reasonable way to do it too, maybe implement it later
             #Mgoal.translation = Mgoal.translation + np.array([0.0, 0.0, -0.1])
             # do a while loop until this is parsed correctly
diff --git a/python/ur_simple_control/robot_descriptions/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/robot_descriptions/__pycache__/__init__.cpython-311.pyc
index 0b438269c81061782619270835f25ca18b5845e3..310d0f3ccd9af60dab2a7927182652fe8b3decea 100644
GIT binary patch
delta 19
acmaFK_>z%(IWI340|Ntto5`Pv-1h)AvIUy}

delta 19
bcmaFK_>z%(IWI340|NuY%N5}hx$gl0IWz_h

diff --git a/python/ur_simple_control/robot_descriptions/urdf/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/robot_descriptions/urdf/__pycache__/__init__.cpython-311.pyc
index d70d22745d75183a65543fa1b8c7a0c8298cd164..87cf9af8fa0a9f776b63d90be581eb2a06f08dde 100644
GIT binary patch
delta 19
acmaFI_>Pf#IWI340|Ntto5`Pv+>Ze^YXzzR

delta 19
bcmaFI_>Pf#IWI340|NuYjdkG@xgP@nIi&^>

diff --git a/python/ur_simple_control/util/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/util/__pycache__/__init__.cpython-311.pyc
index cc7e2ef70b43104b84abbcf2d7964c31e18b8618..73ad86e2073753e1f862d0c21f332c78f73adcef 100644
GIT binary patch
delta 19
acmcc3c$<-XIWI340|Ntto5`Pv+!p{dtOaoZ

delta 19
acmcc3c$<-XIWI340|Ns?(u(kj+!p{e1O;3G

diff --git a/python/ur_simple_control/util/__pycache__/get_model.cpython-311.pyc b/python/ur_simple_control/util/__pycache__/get_model.cpython-311.pyc
index 4f5e2990e6644b46ae0420a9cac8ef5da6c2e1ed..386fce4af890b63f03d87eb47a3d28d507c0012d 100644
GIT binary patch
delta 310
zcmZ1>e?x(HIWI340|Ns?s`;PPBNKTg>uneq7^X9%Fhnt=Fs3l&Fh((fY33*vFwGjp
z3Z~hj*isl%m~+^3Iiffi8B$nU7@{~+n1UHJS*xaU733EeXC~#ODrDvs6y=wt=BDPA
zSSfHRC@3hTr<N#`WTYx2C+1`(6(yEr=I1G-W#*(R<fnneqZEqrlk!Ux$}>wc@=Hq;
zit>xW+7k0pK+<^%1*IhlnI#GtsYR)JV40GP)Z$cy+{E<EWQDxa+@#c^Vui$_RE50!
z5`{#C^!)r3g`E8SY(1`xDQVn{{F_g6i!gI>-C~cAPsvY?kDvU2FGkUUfq{XMfq|ho
kje&vT12ZEd;|C^IMwSl@AcBX1QDSl+zZE0L<Q{$*0AiU}761SM

delta 133
zcmcbiutJ`9IWI340|Ns?h*VOl-$Y(XI|~K|hUp9`3@MB`3{i|=nkkAIOtVC>fN9n!
z))a;mrX03h_9%8nh7{%&hA55{#$X0bmW}_@xEZ-Nr}2m|GjdLD;g1ouXJBApWME(@
bj$&Y7_`uA_$asT6d@`ee6(iSV8vz*rC9oP+

diff --git a/python/ur_simple_control/util/__pycache__/robotiq_gripper.cpython-311.pyc b/python/ur_simple_control/util/__pycache__/robotiq_gripper.cpython-311.pyc
index fd1cbb042ac4e18c03f4548f12b5ef3c475a0fd8..480d94bcf9e5d9e5d77bb06fefa9fe15d9971f79 100644
GIT binary patch
delta 22
ecmX>%lkwb4M(*Xjyj%<n3=D22e>QR-_5lD<od)Ot

delta 22
ecmX>%lkwb4M(*Xjyj%<n3=BQ`OE+>K_5lD<wg%Dw

diff --git a/python/ur_simple_control/util/default_args.py b/python/ur_simple_control/util/default_args.py
index aea31ea..218de85 100644
--- a/python/ur_simple_control/util/default_args.py
+++ b/python/ur_simple_control/util/default_args.py
@@ -4,130 +4,11 @@ import argparse
 
 
 """
-preferably you copy-paste these parameters and add/remove
-arguments to suit your specific arguments.
-the generic arguments are pretty much always used.
-TODO: think about setting the generic arguments somewhere else,
-not parsing there, but returning the parses and then only adding 
-stuff you want.
-that way it's a bit cleanear, and you also can't delete the obligatory ones
+TODO: have 2 versions:
+    1. only the minimal set of argumets (those needed to load robot 
+       and run anything)
+    2. every single one you have os far
 """
 def getDefaultArgs():
-    #######################################################################
-    #                          generic arguments                          #
-    #######################################################################
-    parser = argparse.ArgumentParser(description='Make a drawing on screen,\
-            watch the robot do it on the whiteboard.',
-            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
-    # TODO this one won't really work but let's leave it here for the future
-    parser.add_argument('--simulation', action=argparse.BooleanOptionalAction, 
-            help="whether you are running the UR simulator. \
-                    NOTE: doesn't actually work because it's not a physics simulator", \
-                    default=False)
-    parser.add_argument('--pinocchio-only', action=argparse.BooleanOptionalAction, 
-            help="whether you want to just integrate with pinocchio.\
-                    NOTE: doesn't actually work because it's not a physics simulator", \
-                    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=False)
-    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, 1.0 by default because for dmp. \
-                    BE CAREFUL WITH THIS.", default=1.0)
-    parser.add_argument('--max-iterations', type=int, \
-            help="maximum allowable iteration number (it runs at 500Hz)", default=50000)
-    #######################################################################
-    #                 your controller specific arguments                  #
-    #######################################################################
-    # not applicable here, but leaving it in the case it becomes applicable
-    # it's also in the robot manager even though it shouldn't be
-    parser.add_argument('--past-window-size', type=int, \
-            help="how many timesteps of past data you want to save", default=5)
-    parser.add_argument('--goal-error', type=float, \
-            help="the final position error you are happy with. NOTE: not used here", \
-            default=1e-3)
-    # TODO: test the interaction of this and the overall demo
-    parser.add_argument('--tikhonov-damp', type=float, \
-            help="damping scalar in tiknohov regularization.\
-            This is used when generating the joint trajectory from the drawing.", \
-            default=1e-2)
-    # 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')
-    #############################
-    #  dmp  specific arguments  #
-    #############################
-    parser.add_argument('--temporal-coupling', action=argparse.BooleanOptionalAction, \
-            help="whether you want to use temporal coupling", default=True)
-    parser.add_argument('--kp', type=float, \
-            help="proportial control constant for position errors", \
-            default=1.0)
-    parser.add_argument('--tau0', type=float, \
-            help="total time needed for trajectory. if you use temporal coupling,\
-                  you can still follow the path even if it's too fast", \
-            default=5)
-    parser.add_argument('--gamma-nominal', type=float, \
-            help="positive constant for tuning temporal coupling: the higher,\
-            the fast the return rate to nominal tau", \
-            default=1.0)
-    parser.add_argument('--gamma-a', type=float, \
-            help="positive constant for tuning temporal coupling, potential term", \
-            default=0.5)
-    parser.add_argument('--eps-tc', type=float, \
-            help="temporal coupling term, should be small", \
-            default=0.001)
-    parser.add_argument('--alpha', type=float, \
-            help="force feedback proportional coefficient", \
-            default=0.007)
-    # TODO add low pass filtering and make it's parameters arguments too
-    #######################################################################
-    #                       task specific arguments                       #
-    #######################################################################
-    # 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.5)
-    parser.add_argument('--board-height', type=float, \
-            help="height of the board (in meters) the robot will write on", \
-            default=0.35)
-    parser.add_argument('--calibration', action=argparse.BooleanOptionalAction, \
-            help="whether you want to do calibration", default=False)
-    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=False)
-    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, \
-            help="the clik error you are happy with", default=1e-2)
-    parser.add_argument('--max-init-clik-iterations', type=int, \
-            help="number of max clik iterations to get to the first point", default=10000)
-    parser.add_argument('--max-running-clik-iterations', type=int, \
-            help="number of max clik iterations between path points", default=1000)
-
-    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
+    raise NotImplementedError("sorry, this hasn't been implemented yet")
 
diff --git a/python/ur_simple_control/util/draw_path.py b/python/ur_simple_control/util/draw_path.py
index 0fa950d..4a54dca 100644
--- a/python/ur_simple_control/util/draw_path.py
+++ b/python/ur_simple_control/util/draw_path.py
@@ -1,10 +1,14 @@
-# TODO: possible improvement:
-# - draw multiple lines
-# - then you would just generate multiple dmps for each trajectory
-#   and do movel's + movej's to provide the connections
-# TODO: possible improvement: make it all bezier curves
-#   https://matplotlib.org/stable/users/explain/artists/paths.html
-#   look at the example for path handling if that's what you'll need
+"""
+possible improvement:
+- draw multiple lines
+- then you would just generate multiple dmps for each trajectory
+  and do movel's + movej's to provide the connections
+possible improvement: make it all bezier curves
+  https://matplotlib.org/stable/users/explain/artists/paths.html
+  look at the example for path handling if that's what you'll need
+    - not really needed, especially because we want hard edges to test our controllers
+      (but if that was a parameter that would be ok i guess)
+"""
 
 import numpy as np
 import matplotlib.pyplot as plt
@@ -21,9 +25,10 @@ from matplotlib.widgets import LassoSelector
 #from matplotlib.path import Path
 
 class DrawPathManager:
-    def __init__(self, ax):
+    def __init__(self, args, ax):
         self.canvas = ax.figure.canvas
         self.lasso = LassoSelector(ax, onselect=self.onselect)
+        self.args = args
 
     def onselect(self, verts):
         # verts is a list of tuples
@@ -40,16 +45,15 @@ class DrawPathManager:
     # made to save and exit
     def accept(self, event):
         if event.key == "enter":
-            print("pixel path:")
-            print(self.path)
+            if args.debug_prints:
+                print("pixel path:")
+                print(self.path)
             self.disconnect()
-            # TODO: ensure this runs fine after packaging
             np.savetxt("./path_in_pixels.csv", self.path, delimiter=',', fmt='%.5f')
-            print("TODO: run clik on the pixel path to make it a trajectory")
             # plt.close over exit so that we can call this from elsewhere and not kill the program
             plt.close()
 
-def drawPath():
+def drawPath(args):
     # normalize both x and y to 0-1 range
     # we can multiply however we want later
     # idk about the number of points, but it's large enough to draw
@@ -59,7 +63,7 @@ def drawPath():
     subplot_kw = dict(xlim=(0, 1), ylim=(0, 1), autoscale_on=False)
     fig, ax = plt.subplots(subplot_kw=subplot_kw)
 
-    selector = DrawPathManager(ax)
+    selector = DrawPathManager(args, ax)
 
     # map key press to our function
     # thankfully it didn't mind have self as the first argument
@@ -70,4 +74,4 @@ def drawPath():
 
 
 if __name__ == '__main__':
-    drawPath()
+    drawPath(args)
diff --git a/python/ur_simple_control/util/get_model.py b/python/ur_simple_control/util/get_model.py
index 4a32e98..3059057 100644
--- a/python/ur_simple_control/util/get_model.py
+++ b/python/ur_simple_control/util/get_model.py
@@ -1,3 +1,9 @@
+"""
+possible improvement: 
+    get the calibration file of the robot without ros
+    and then put it here.
+    these magic numbers are not a good look.
+"""
 import pinocchio as pin
 import numpy as np
 import sys
@@ -6,7 +12,6 @@ from importlib.resources import files
 
 # can't get the urdf reading with these functions to save my life, idk what or why
 
-# TODO fix paths via python packaging
 def get_model(visualize):
     
     #urdf_path_relative = "../robot_descriptions/urdf/ur5e_with_robotiq_hande.urdf"
diff --git a/python/ur_simple_control/util/logging_utils.py b/python/ur_simple_control/util/logging_utils.py
index 730ff2c..c8f0c5d 100644
--- a/python/ur_simple_control/util/logging_utils.py
+++ b/python/ur_simple_control/util/logging_utils.py
@@ -6,8 +6,10 @@ def saveLog(log_dict, final_iteration, args):
     # shave off the zeros, noone needs 'em
     for key in log_dict:
         log_dict[key] = log_dict[key][:final_iteration]
-    # TODO make generic
-    # preferably name files after arguments
+    # TODO make generic:
+    #  - generate name based on args + add index
+    #  - you need to run shell ls to get the index,
+    #    there's at least one chalmers project with code for that
     run_file_path = "./data/clik_run_001.pickle"
     args_file_path = "./data/clik_run_001_args.pickle"
     # save the logged data
diff --git a/python/ur_simple_control/visualize/__pycache__/__init__.cpython-311.pyc b/python/ur_simple_control/visualize/__pycache__/__init__.cpython-311.pyc
index aba675302559b05bdf8aa8c563b486bbf526fd1f..ac4eb3273e2b46597521f26cb6adac319d37d244 100644
GIT binary patch
delta 19
acmaFB_<)gnIWI340|Ntto5`Pv+*biKWd(o$

delta 19
acmaFB_<)gnIWI340|Ns?R!_u4?yCSaWd&FO

diff --git a/python/ur_simple_control/visualize/__pycache__/pin_to_vedo_plot_util.cpython-311.pyc b/python/ur_simple_control/visualize/__pycache__/pin_to_vedo_plot_util.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d3f8454db4cce95335a702b67ae9e76fa717ce46
GIT binary patch
literal 5748
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
VFbabb4w$inWe*pafs+776#zdam-_$!

literal 0
HcmV?d00001

diff --git a/python/ur_simple_control/visualize/__pycache__/visualize.cpython-311.pyc b/python/ur_simple_control/visualize/__pycache__/visualize.cpython-311.pyc
index 1b8fab368fc8d0086e4066c6ee5f220f2bd77329..44f507b6f1ebdeda62574ea70174ab2afce3bc34 100644
GIT binary patch
delta 20
bcmdnTyN{Q9IWI340|Ntto5`Pz+?&||Hp>NA

delta 20
ccmdnTyN{Q9IWI340|Ntt{o7v~xi_-`06OLd2mk;8

diff --git a/python/ur_simple_control/visualize/pin_to_vedo_plot_util.py b/python/ur_simple_control/visualize/pin_to_vedo_plot_util.py
index d400cf7..a891387 100644
--- a/python/ur_simple_control/visualize/pin_to_vedo_plot_util.py
+++ b/python/ur_simple_control/visualize/pin_to_vedo_plot_util.py
@@ -36,13 +36,12 @@ def updateFrameArrowsFromSE3(arrows : list[vedo.Arrow], frame : pin.SE3):
         arrows[i].top = np.array([x,y,z])
 
 def drawSE3AsFrame(frame : pin.SE3, 
-        text : str) -> vedo.Arrows:
+                   text : str, scaling=0.1) -> vedo.Arrows:
     #print(text)
     #print(frame)
     colors = ['r', 'g', 'b']
     arrows = []
     #print(frame.rotation)
-    scaling = 0.02
     for i in range(0,3):
         x = frame.translation[0] + frame.rotation[0,i] * scaling 
         y = frame.translation[1] + frame.rotation[1,i] * scaling
diff --git a/python/ur_simple_control/visualize/vedo_manipulator.py b/python/ur_simple_control/visualize/vedo_manipulator.py
index 5c3972b..cf03cc8 100644
--- a/python/ur_simple_control/visualize/vedo_manipulator.py
+++ b/python/ur_simple_control/visualize/vedo_manipulator.py
@@ -15,222 +15,95 @@ import vedo
 import pinocchio as pin
 import time
 from ur_simple_control.visualize.pin_to_vedo_plot_util import *
-from friction import ReducedFrictionModel
-from multiprocessing import Process
-from scipy.integrate import solve_ivp
-
-
+from ur_simple_control.managers import RobotManager
+import argparse
+
+
+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=True)
+    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=False)
+    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')
+    parser.add_argument('--debug-prints', action=argparse.BooleanOptionalAction, \
+            help="print some debug info", default=False)
+
+    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
 #######################################################################
 #                       IMPLEMENT THIS ACTUALLY                       #
 #######################################################################
 
 
-if __name__ == "__main__":
-    args = getArgs()
-    # change this after you add the manipulator
-    box_dimensions = [args.box_length, args.box_width, args.box_height]
-
-    ###########################################
-    #  vedo instantiation, frame definitions  #
-    ###########################################
-    vedo.settings.use_depth_peeling = True
-
-    # need to manually seed lmao
-    #pin.seed(int(time.time()))
-    T_w_J = pin.SE3()
-    # TODO: check how friction behaves when we're perpendicular to gravity
-    T_w_J.setIdentity()
-    T_w_J.translation = np.array([1,2,3])
-    T_w_J.setRandom()
-    #T_w_J.rotation = pin.rpy.rpyToMatrix(0,np.pi/2,0)
-
-
-    model, data, OBJECT_JOINT_ID = getPlanarJointModel(args, T_w_J, box_dimensions)
-    q_init = pin.randomConfiguration(model)
-    #theta = np.random.random() * 2 * np.pi
-    theta = 0.345321
-    q_init[0] = 0.1
-    q_init[1] = 0.1
-    q_init[2] = np.cos(theta)
-    q_init[3] = np.sin(theta)
-
-    v_b_se2 = np.array([0.1, 0.0, 0.5])
-    v_b_se3 = pin.Motion(np.array([v_b_se2[0], v_b_se2[1], 0]), np.array([0,0,v_b_se2[2]]))
-    print("v_b_se2", v_b_se2)
-    #print("pin.exp3(v)", pin.exp3(v))
-    #exit()
-    #tau = np.ones((model.nv)) * 0.1
-    #a = pin.aba(model, data, q, v, tau)
-    # tau_q_control does not exist in reality, those are the actuators
-    # of the planar joint
-    #tau_q_control = np.zeros((model.nv)) 
-
-    pin.forwardKinematics(model, data, q_init)
-    T_w_b_init  = data.oMi[1].copy()
-
-    q_pin = pin.integrate(model, q_init, v_b_se2)
-    print("q_pin:", q_pin)
-    pin.forwardKinematics(model, data, q_pin)
-    pin.updateFramePlacements(model, data)
-#    for vvv in data.v:
-#        print(vvv)
-#    for fr in data.oMf:
-#        print(fr)
-    T_w_b_pin = data.oMi[1].copy()
-
-    q_3 = np.zeros(3)
-    q_3[0] = q_init[0]
-    q_3[1] = q_init[1]
-    q_3[2] = theta
-    print("q_3", q_3)
-
-    in_SE3 = False
-
-########################################################
-## JUST USE THE EXP FOR THE LOVE OF GOD
-#############################################3333333
-#    omega = v[2]
-#    cv = np.cos(omega)
-#    sv = np.sin(omega)
-#    R_omega = np.array([[cv, -1*sv], [sv, cv]])
-#    vcross = np.array([-1*v[1], v[0]])
-#    vcross -= -v[:2]*R_omega[:,0] + v[:2]*R_omega[:,1]
-#    vcross /= omega
-#    t = vcross.copy()
-#    T_next = np.hstack((R_omega, t.reshape((2,1))))
-#    T_next = np.vstack((T_next, np.array([0,0,1]).reshape((1,3))))
-#    # let's try inverse
-#    #T_next = np.hstack((R_omega.T, -1*R_omega.T @ t.reshape((2,1))))
-#    #T_next = np.vstack((T_next, np.array([0,0,1]).reshape((1,3))))
-#    print("T_next", T_next)
-
-#    c_theta = np.cos(theta)
-#    s_theta = np.sin(theta)
-#    R_theta = np.array([[c_theta, -1*s_theta], [s_theta, c_theta]])
-#    T_J_b_se2 = np.hstack((R_theta, np.array([q_3[0],q_3[1]]).reshape((2,1))))
-#    T_J_b_se2 = np.vstack((T_J_b_se2, np.array([0,0,1]).reshape((1,3))))
-
-#    print("T_J_b_se2", T_J_b_se2)
-#    T_J_b_se2 = T_next @ T_J_b_se2
-#    print("T_J_b_se2", T_J_b_se2)
-
-#    T_next_SE3 = pin.exp(v_b_se3)
-#    T_next_SE2 = np.hstack((T_next_SE3.rotation[:2,:2], T_next_SE3.translation[:2].reshape((2,1))))
-#    T_next_SE2 = np.vstack((T_next_SE2, np.array([0,0,1]).reshape((1,3))))
-    
-    # wrogn notation last term lel
-#    T_J_b_SE2 = T_next_SE2 @ T_J_b_se2
-#    q_3[0] = T_J_b_SE2[0,2]
-#    q_3[1] = T_J_b_SE2[1,2]
-#    # not good but w/3
-#    q_3[2] = np.arccos(T_J_b_SE2[0,0])
-
-    # this changes the no rotation problem
-    #q_3[2] = omega
+def drawStateAnim(self):
+    toBase = [np.array([[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]])]
+    drawOrientation(self.ax, toBase[-1][0:3,0:3], np.zeros((3,)), self.avg_link_lenth * 2)
+    for j in range(len(self.joints)):
+        toBase.append(toBase[-1] @ self.joints[j].HomMat)
+        drawOrientationAnim(self.ax, toBase[-1][0:3,0:3], self.lines[j][:-1], toBase[-1][0:3,3], self.avg_link_lenth)
+        drawVectorAnim(self.ax, -1* ( toBase[-2][0:3,3] - toBase[-1][0:3,3] ), self.lines[j][-1], toBase[-2][0:3,3],self.color_link)
+
+
+if __name__ == "__main__": 
+    pin.seed(int(time.time()))
+    args = get_args()
+    robot = RobotManager(args)
+    q = pin.randomConfiguration(robot.model)
+    q = np.zeros(8)
+    pin.forwardKinematics(robot.model, robot.data, q)
+    print(type(robot.data))
+    #pin.computeAllTerms(robot.model, robot.data, q, np.zeros(8))
+    # no need to use AnimationPlayer, we can update stuff on Plotter as we please.
+    # so the comm logic + updating will be implemented here (ideal circumstance)
+    plt = vedo.Plotter(axes=1)
+    plt.camera = vedo.utils.oriented_camera(center=(0, 0, 0),
+                                up_vector=(0, 1, 0),
+                                backoff_vector=(0, 1, 0),
+                                backoff=1.0)
 
-    #print("q_3 + v_b_se2", q_3)
-#################
-#    q_euler = np.zeros(4)
-#    q_euler[0] = q_3[0] #+ np.cos(v[2]) 
-#    q_euler[1] = q_3[1] #+ np.exp(v[2]) 
-#    q_euler[2] = np.cos(q_3[2])
-#    q_euler[3] = np.sin(q_3[2])
-#    print("q_euler:", q_euler)
-#    pin.forwardKinematics(model, data, q_euler)
-    #T_w_b_euler = data.oMi[1].copy()
-    #T_w_b_euler = pin.exp6(v_b_se3).act(T_w_J)
-    #T_w_b_euler = pin.exp6(v_twist).act(T_w_b_init)
-#    T_J_b = T_w_J.actInv(T_w_b_init)
-    #print(T_J_b)
-    #T_w_b_euler = pin.exp6(T_J_b.act(v_twist)).act(T_w_b_init)
-    # THIS IS THE ONE!!!!!!!!!!!!!!!!!!!
-    if in_SE3:
-        print("SE3 version")
-        v_w_se3 = T_w_b_init.act(v_b_se3)
-        print(v_w_se3)
-        T_w_next_SE3 = pin.exp6(v_w_se3)
-        print(T_w_next_SE3)
-        T_w_b_euler = T_w_next_SE3.act(T_w_b_init)
-    #T_w_b_euler = pin.exp6(v_twist).act(T_w_b_init)
-    #T_J_b_next_euler = pin.exp6(v_twist).act(T_J_b)
-    #T_w_b_euler = T_w_J.act(T_J_b_next_euler)
-    # let's try to get this within J and SE(2)
-    # get v_b to v_J
-    else:
-        print("SE2 version")
-        c_theta = np.cos(theta)
-        s_theta = np.sin(theta)
-        R_theta = np.array([[c_theta, -1*s_theta], [s_theta, c_theta]])
-        # needed later
-        T_J_b_SE2 = np.zeros((3,3))
-        T_J_b_SE2[:2,:2] = R_theta
-        T_J_b_SE2[0,2] = q_3[0]
-        T_J_b_SE2[1,2] = q_3[1]
-        T_J_b_SE2[2,2] = 1
-        Ad_T_J_b_SE2 = np.zeros((3,3))
-        Ad_T_J_b_SE2[:2,:2] = R_theta
-        Ad_T_J_b_SE2[0,2] = q_init[1]
-        Ad_T_J_b_SE2[1,2] = -q_init[0]
-        Ad_T_J_b_SE2[2,2] = 1
-        v_J_se2 = Ad_T_J_b_SE2 @ v_b_se2
-        print("v_J_se2", v_J_se2)
-        # get v_J_se2 to T_next_SE2
-        omega = v_J_se2[2]
-        c_omega = np.cos(omega)
-        s_omega = np.sin(omega)
-        # note that this is the same as exp(omega)
-        R_omega = np.array([[c_omega, -1*s_omega], [s_omega, c_omega]])
-        omega_abs = np.abs(omega)
-        t = np.zeros(2)
-        if omega_abs > 1e-14:
-            V = np.array([[s_omega, -1*(1 -c_omega)], [1- c_omega, s_omega]])
-            V /= omega
-            t = V @ np.array([v_J_se2[0], v_J_se2[1]])#.reshape((2,1))
-        else:
-            t = np.zeros(2)
-            t[0] = v_J_se2[0]
-            t[1] = v_J_se2[1]
-        T_next_SE2 = np.hstack((R_omega, t.reshape((2,1))))
-        T_next_SE2 = np.vstack((T_next_SE2, np.array([0,0,1]).reshape((1,3))))
-        print("T_next_SE2", T_next_SE2)
-        T_J_b_SE2 = T_next_SE2 @ T_J_b_SE2
-        q_euler = np.zeros(4)
-        q_euler[0] = T_J_b_SE2[0,2]
-        q_euler[1] = T_J_b_SE2[1,2]
-        q_euler[2] = T_J_b_SE2[0,0]
-        q_euler[3] = T_J_b_SE2[1,0]
-        #q_euler[0] = q_3[0] 
-        #q_euler[1] = q_3[1] 
-        #q_euler[2] = np.cos(q_3[2])
-        #q_euler[3] = np.sin(q_3[2])
-        print("q3 + v_J", q_3 + v_J_se2)
-        print("q_euler:", q_euler)
-        pin.forwardKinematics(model, data, q_euler)
-        T_w_b_euler = data.oMi[OBJECT_JOINT_ID]
+    for i in range(robot.model.nq):
+        plt += drawSE3AsFrame(robot.data.oMi[i], "",scaling=0.02)
+        if i+1 < robot.model.nq:
+            #            plt += vedo.Arrow(robot.data.oMi[i].translation, 
+            #                    robot.data.oMi[i+1].translation - robot.data.oMi[i].translation)
+            #plt += vedo.Arrow(robot.data.oMi[i].translation, 
+            #        -1 * (robot.data.oMi[i].translation - robot.data.oMi[i+1].translation))
+            plt += vedo.Arrow(robot.data.oMi[i].translation, 
+                    robot.data.oMi[i].act(robot.data.liMi[i+1]).translation)
 
 
 
-    joint_arrows, joint_text = drawSE3AsFrame(T_w_J, "J")
-    b_init_arrows, b_init_text = drawSE3AsFrame(T_w_b_init, "b_init")
-    # pin
-    objectt = drawBoxFromSE3(T_w_b_pin, box_dimensions)
-    b_arrows_pin, b_text_pin = drawSE3AsFrame(T_w_b_pin, "b_pin")
-    # euler
-    objectt = drawBoxFromSE3(T_w_b_pin, box_dimensions)
-    b_arrows_euler, b_text_euler = drawSE3AsFrame(T_w_b_euler, "b_euler")
 
 
-    plt = vedo.Plotter(axes=1)
-    plt.camera = vedo.utils.oriented_camera(center=(0, 0, 0),
-                                up_vector=(0, 1, 0),
-                                backoff_vector=(0, 1, 0),
-                                backoff=1.0)
-    
-    plt.add(objectt)
-    plt.add(b_init_arrows, b_init_text)
-    plt.add(b_arrows_pin, b_text_pin)
-    plt.add(b_arrows_euler, b_text_euler)
-    plt.add(joint_arrows, joint_text)
     plt.render()
     plt.show()
-    plt.close()
-- 
GitLab