diff --git a/examples/graz/technical_report/technical_report.aux b/examples/graz/technical_report/technical_report.aux
new file mode 100644
index 0000000000000000000000000000000000000000..b64012178f9cbc148dca209ceaf227aee4833711
--- /dev/null
+++ b/examples/graz/technical_report/technical_report.aux
@@ -0,0 +1,2 @@
+\relax 
+\gdef \@abspage@last{1}
diff --git a/examples/graz/technical_report/technical_report.log b/examples/graz/technical_report/technical_report.log
new file mode 100644
index 0000000000000000000000000000000000000000..56c5124d367b491769bedf4eff0cbd2b4fd030ef
--- /dev/null
+++ b/examples/graz/technical_report/technical_report.log
@@ -0,0 +1,273 @@
+This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024/Arch Linux) (preloaded format=pdflatex 2025.2.22)  28 FEB 2025 10:58
+entering extended mode
+ \write18 enabled.
+ %&-line parsing enabled.
+**technical_report.tex
+(./technical_report.tex
+LaTeX2e <2023-11-01> patch level 1
+L3 programming layer <2024-02-20>
+(/usr/share/texmf-dist/tex/latex/base/article.cls
+Document Class: article 2023/05/17 v1.4n Standard LaTeX document class
+(/usr/share/texmf-dist/tex/latex/base/size10.clo
+File: size10.clo 2023/05/17 v1.4n Standard LaTeX file (size option)
+)
+\c@part=\count188
+\c@section=\count189
+\c@subsection=\count190
+\c@subsubsection=\count191
+\c@paragraph=\count192
+\c@subparagraph=\count193
+\c@figure=\count194
+\c@table=\count195
+\abovecaptionskip=\skip48
+\belowcaptionskip=\skip49
+\bibindent=\dimen140
+)
+(/usr/share/texmf-dist/tex/latex/amsmath/amsmath.sty
+Package: amsmath 2023/05/13 v2.17o AMS math features
+\@mathmargin=\skip50
+
+For additional information on amsmath, use the `?' option.
+(/usr/share/texmf-dist/tex/latex/amsmath/amstext.sty
+Package: amstext 2021/08/26 v2.01 AMS text
+
+(/usr/share/texmf-dist/tex/latex/amsmath/amsgen.sty
+File: amsgen.sty 1999/11/30 v2.0 generic functions
+\@emptytoks=\toks17
+\ex@=\dimen141
+))
+(/usr/share/texmf-dist/tex/latex/amsmath/amsbsy.sty
+Package: amsbsy 1999/11/29 v1.2d Bold Symbols
+\pmbraise@=\dimen142
+)
+(/usr/share/texmf-dist/tex/latex/amsmath/amsopn.sty
+Package: amsopn 2022/04/08 v2.04 operator names
+)
+\inf@bad=\count196
+LaTeX Info: Redefining \frac on input line 234.
+\uproot@=\count197
+\leftroot@=\count198
+LaTeX Info: Redefining \overline on input line 399.
+LaTeX Info: Redefining \colon on input line 410.
+\classnum@=\count199
+\DOTSCASE@=\count266
+LaTeX Info: Redefining \ldots on input line 496.
+LaTeX Info: Redefining \dots on input line 499.
+LaTeX Info: Redefining \cdots on input line 620.
+\Mathstrutbox@=\box51
+\strutbox@=\box52
+LaTeX Info: Redefining \big on input line 722.
+LaTeX Info: Redefining \Big on input line 723.
+LaTeX Info: Redefining \bigg on input line 724.
+LaTeX Info: Redefining \Bigg on input line 725.
+\big@size=\dimen143
+LaTeX Font Info:    Redeclaring font encoding OML on input line 743.
+LaTeX Font Info:    Redeclaring font encoding OMS on input line 744.
+\macc@depth=\count267
+LaTeX Info: Redefining \bmod on input line 905.
+LaTeX Info: Redefining \pmod on input line 910.
+LaTeX Info: Redefining \smash on input line 940.
+LaTeX Info: Redefining \relbar on input line 970.
+LaTeX Info: Redefining \Relbar on input line 971.
+\c@MaxMatrixCols=\count268
+\dotsspace@=\muskip16
+\c@parentequation=\count269
+\dspbrk@lvl=\count270
+\tag@help=\toks18
+\row@=\count271
+\column@=\count272
+\maxfields@=\count273
+\andhelp@=\toks19
+\eqnshift@=\dimen144
+\alignsep@=\dimen145
+\tagshift@=\dimen146
+\tagwidth@=\dimen147
+\totwidth@=\dimen148
+\lineht@=\dimen149
+\@envbody=\toks20
+\multlinegap=\skip51
+\multlinetaggap=\skip52
+\mathdisplay@stack=\toks21
+LaTeX Info: Redefining \[ on input line 2953.
+LaTeX Info: Redefining \] on input line 2954.
+)
+(/usr/share/texmf-dist/tex/latex/amsfonts/amssymb.sty
+Package: amssymb 2013/01/14 v3.01 AMS font symbols
+
+(/usr/share/texmf-dist/tex/latex/amsfonts/amsfonts.sty
+Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
+\symAMSa=\mathgroup4
+\symAMSb=\mathgroup5
+LaTeX Font Info:    Redeclaring math symbol \hbar on input line 98.
+LaTeX Font Info:    Overwriting math alphabet `\mathfrak' in version `bold'
+(Font)                  U/euf/m/n --> U/euf/b/n on input line 106.
+))
+(/usr/share/texmf-dist/tex/latex/base/fontenc.sty
+Package: fontenc 2021/04/29 v2.0v Standard LaTeX package
+)
+(/usr/share/texmf-dist/tex/latex/tools/bm.sty
+Package: bm 2023/07/08 v1.2f Bold Symbol Support (DPC/FMi)
+\symboldoperators=\mathgroup6
+\symboldletters=\mathgroup7
+\symboldsymbols=\mathgroup8
+Package bm Info: No bold for \OMX/cmex/m/n, using \pmb.
+Package bm Info: No bold for \U/msa/m/n, using \pmb.
+Package bm Info: No bold for \U/msb/m/n, using \pmb.
+LaTeX Font Info:    Redeclaring math alphabet \mathbf on input line 149.
+)
+(/usr/share/texmf-dist/tex/latex/tools/array.sty
+Package: array 2023/10/16 v2.5g Tabular extension package (FMi)
+\col@sep=\dimen150
+\ar@mcellbox=\box53
+\extrarowheight=\dimen151
+\NC@list=\toks22
+\extratabsurround=\skip53
+\backup@length=\skip54
+\ar@cellbox=\box54
+)
+(/usr/share/texmf-dist/tex/latex/graphics/graphicx.sty
+Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
+
+(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty
+Package: keyval 2022/05/29 v1.15 key=value parser (DPC)
+\KV@toks@=\toks23
+)
+(/usr/share/texmf-dist/tex/latex/graphics/graphics.sty
+Package: graphics 2022/03/10 v1.4e Standard LaTeX Graphics (DPC,SPQR)
+
+(/usr/share/texmf-dist/tex/latex/graphics/trig.sty
+Package: trig 2021/08/11 v1.11 sin cos tan (DPC)
+)
+(/usr/share/texmf-dist/tex/latex/graphics-cfg/graphics.cfg
+File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
+)
+Package graphics Info: Driver file: pdftex.def on input line 107.
+
+(/usr/share/texmf-dist/tex/latex/graphics-def/pdftex.def
+File: pdftex.def 2022/09/22 v1.2b Graphics/color driver for pdftex
+))
+\Gin@req@height=\dimen152
+\Gin@req@width=\dimen153
+)
+(/usr/share/texmf-dist/tex/latex/base/inputenc.sty
+Package: inputenc 2021/02/14 v1.3d Input encoding file
+\inpenc@prehook=\toks24
+\inpenc@posthook=\toks25
+)
+(/usr/share/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
+File: l3backend-pdftex.def 2024-02-20 L3 backend support: PDF output (pdfTeX)
+\l__color_backend_stack_int=\count274
+\l__pdf_internal_box=\box55
+)
+(./technical_report.aux)
+\openout1 = `technical_report.aux'.
+
+LaTeX Font Info:    Checking defaults for OML/cmm/m/it on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+LaTeX Font Info:    Checking defaults for OMS/cmsy/m/n on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+LaTeX Font Info:    Checking defaults for OT1/cmr/m/n on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+LaTeX Font Info:    Checking defaults for T1/cmr/m/n on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+LaTeX Font Info:    Checking defaults for TS1/cmr/m/n on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+LaTeX Font Info:    Checking defaults for OMX/cmex/m/n on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+LaTeX Font Info:    Checking defaults for U/cmr/m/n on input line 17.
+LaTeX Font Info:    ... okay on input line 17.
+
+(/usr/share/texmf-dist/tex/context/base/mkii/supp-pdf.mkii
+[Loading MPS to PDF converter (version 2006.09.02).]
+\scratchcounter=\count275
+\scratchdimen=\dimen154
+\scratchbox=\box56
+\nofMPsegments=\count276
+\nofMParguments=\count277
+\everyMPshowfont=\toks26
+\MPscratchCnt=\count278
+\MPscratchDim=\dimen155
+\MPnumerator=\count279
+\makeMPintoPDFobject=\count280
+\everyMPtoPDFconversion=\toks27
+) (/usr/share/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty
+Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf
+
+(/usr/share/texmf-dist/tex/generic/infwarerr/infwarerr.sty
+Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO)
+)
+(/usr/share/texmf-dist/tex/latex/grfext/grfext.sty
+Package: grfext 2019/12/03 v1.3 Manage graphics extensions (HO)
+
+(/usr/share/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty
+Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO)
+))
+(/usr/share/texmf-dist/tex/latex/kvoptions/kvoptions.sty
+Package: kvoptions 2022-06-15 v3.15 Key value format for package options (HO)
+
+(/usr/share/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty
+Package: ltxcmds 2023-12-04 v1.26 LaTeX kernel commands for general use (HO)
+)
+(/usr/share/texmf-dist/tex/latex/kvsetkeys/kvsetkeys.sty
+Package: kvsetkeys 2022-10-05 v1.19 Key value parser (HO)
+))
+(/usr/share/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty
+Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO
+)
+
+(/usr/share/texmf-dist/tex/generic/iftex/iftex.sty
+Package: iftex 2022/02/03 v1.0f TeX engine tests
+)
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode found.
+)
+Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4
+85.
+Package grfext Info: Graphics extension search list:
+(grfext)             [.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPE
+G,.JBIG2,.JB2,.eps]
+(grfext)             \AppendGraphicsExtensions on input line 504.
+
+(/usr/share/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
+File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
+e
+))
+LaTeX Font Info:    Trying to load font information for U+msa on input line 18.
+
+
+(/usr/share/texmf-dist/tex/latex/amsfonts/umsa.fd
+File: umsa.fd 2013/01/14 v3.01 AMS symbols A
+)
+LaTeX Font Info:    Trying to load font information for U+msb on input line 18.
+
+
+(/usr/share/texmf-dist/tex/latex/amsfonts/umsb.fd
+File: umsb.fd 2013/01/14 v3.01 AMS symbols B
+) [1
+
+{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}{/usr/share/texmf-dist/fonts
+/enc/dvips/cm-super/cm-super-t1.enc}] (./technical_report.aux)
+ ***********
+LaTeX2e <2023-11-01> patch level 1
+L3 programming layer <2024-02-20>
+ ***********
+ ) 
+Here is how much of TeX's memory you used:
+ 3515 strings out of 476076
+ 50943 string characters out of 5793775
+ 1929187 words of memory out of 5000000
+ 25570 multiletter control sequences out of 15000+600000
+ 567778 words of font info for 66 fonts, out of 8000000 for 9000
+ 14 hyphenation exceptions out of 8191
+ 61i,6n,69p,244b,221s stack positions out of 10000i,1000n,20000p,200000b,200000s
+</usr/share/texmf-dist/fonts/type1/public/cm-super/sfrm1000.pfb></usr/share/t
+exmf-dist/fonts/type1/public/cm-super/sfrm1200.pfb></usr/share/texmf-dist/fonts
+/type1/public/cm-super/sfrm1728.pfb>
+Output written on technical_report.pdf (1 page, 46823 bytes).
+PDF statistics:
+ 24 PDF objects out of 1000 (max. 8388607)
+ 14 compressed objects within 1 object stream
+ 0 named destinations out of 1000 (max. 500000)
+ 1 words of extra memory for PDF output out of 10000 (max. 10000000)
+
diff --git a/examples/graz/technical_report/technical_report.pdf b/examples/graz/technical_report/technical_report.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..e3cd4f13a9d33bd158dffa5ad2f13a353838e21b
Binary files /dev/null and b/examples/graz/technical_report/technical_report.pdf differ
diff --git a/examples/graz/technical_report/technical_report.synctex.gz b/examples/graz/technical_report/technical_report.synctex.gz
new file mode 100644
index 0000000000000000000000000000000000000000..eb7b464466eb85363698c916c7dff7a2dc70dce3
Binary files /dev/null and b/examples/graz/technical_report/technical_report.synctex.gz differ
diff --git a/examples/graz/technical_report/technical_report.tex b/examples/graz/technical_report/technical_report.tex
new file mode 100644
index 0000000000000000000000000000000000000000..4e851da0cbe98f7045f03570428303872723f46e
--- /dev/null
+++ b/examples/graz/technical_report/technical_report.tex
@@ -0,0 +1,37 @@
+\documentclass{article}
+\usepackage{amsmath}
+\newcommand{\argmin}{\arg\!\min} 
+\newcommand{\argmax}{\arg\!\max} 
+\usepackage{amssymb}
+\usepackage{amsfonts}
+\usepackage[T1]{fontenc}
+\usepackage{bm}
+\usepackage{array}
+\usepackage{graphicx}
+\usepackage[utf8]{inputenc}
+
+\title{Decentralized admitance control client}
+\date{date}
+\author{Marko Guberina}
+
+\begin{document}
+\maketitle
+The other robot, Universal Robots’ UR5e, is a 6-dof collaborative manipulator with a 5kg payload.
+Communication with the robot is achieved with via the Real-Time Data Exchange (RTDE) interface,
+with ur\_rtde for client-side implementation. The highest available communication frequency is 500Hz.
+Wrench sensing is obtained from UR5e’s built-in force-torque sensor via the same interface.
+The Robotiq 2F-85 gripper is connected to the robot’s wrist tool flange, and controlled via RS485 serial communication.
+The client-side communication protocol with the gripper is implemented in Python.
+The CLIK control law is implemented in a custom library written in Python, leveraging Pinocchio’s
+implementation of rigid body algorithms.
+Due to versioning incompatibilities between the library and ROS Melodic,
+communication with the ROS stack was handled by thin translation layer
+between ROS messages and protobuf with negligible overhead.
+
+
+
+
+
+
+
+\end{document}
diff --git a/python/smc/control/controller_templates/point_to_point.py b/python/smc/control/controller_templates/point_to_point.py
index e2b35960c420835447f7353dfa2b207ad566b7bd..8c319c0c47dadc56130a9dd8ccb3dcb6583afc64 100644
--- a/python/smc/control/controller_templates/point_to_point.py
+++ b/python/smc/control/controller_templates/point_to_point.py
@@ -7,7 +7,10 @@ from typing import Any, Callable
 import numpy as np
 from collections import deque
 
-from smc.robots.interfaces.whole_body_interface import SingleArmWholeBodyInterface
+from smc.robots.interfaces.whole_body_interface import (
+    SingleArmWholeBodyInterface,
+    DualArmWholeBodyInterface,
+)
 
 global control_loop_return
 control_loop_return = tuple[bool, dict[str, np.ndarray], dict[str, np.ndarray]]
@@ -115,6 +118,7 @@ def DualEEP2PCtrlLoopTemplate(
     log_item["r_err_norm"] = np.linalg.norm(err_vector_right)
     return breakFlag, save_past_item, log_item
 
+
 def EEAndBaseP2PCtrlLoopTemplate(
     SOLVER: Any,
     T_w_goal: SE3,
@@ -230,7 +234,7 @@ def DualEEAndBaseP2PCtrlLoopTemplate(
 
     if (
         (err_vector_left_norm < robot.args.goal_error)
-        and (err_vector_right_norm< robot.args.goal_error)
+        and (err_vector_right_norm < robot.args.goal_error)
         and (base_err_vector_norm < robot.args.goal_error)
     ):
         breakFlag = True
diff --git a/python/smc/control/optimal_control/croco_mpc_point_to_point.py b/python/smc/control/optimal_control/croco_mpc_point_to_point.py
index 72a34e48219dceda839bab92962094994311eb94..8d4b489135c644568645d468fbe27ca512a1ba1b 100644
--- a/python/smc/control/optimal_control/croco_mpc_point_to_point.py
+++ b/python/smc/control/optimal_control/croco_mpc_point_to_point.py
@@ -4,14 +4,18 @@ from smc.control.controller_templates.point_to_point import (
     EEAndBaseP2PCtrlLoopTemplate,
     EEP2PCtrlLoopTemplate,
 )
-from smc.control.optimal_control.abstract_croco_ocp import CrocoOCP
 from smc.robots.interfaces.single_arm_interface import SingleArmInterface
 from smc.robots.interfaces.dual_arm_interface import DualArmInterface
+from smc.robots.interfaces.whole_body_interface import (
+    SingleArmWholeBodyInterface,
+    DualArmWholeBodyInterface,
+)
+from smc.control.optimal_control.abstract_croco_ocp import CrocoOCP
 from smc.control.optimal_control.point_to_point_croco_ocp import (
     SingleArmIKOCP,
     DualArmIKOCP,
     BaseAndSingleArmIKOCP,
-    BaseAndDualArmIKOCP
+    BaseAndDualArmIKOCP,
 )
 from smc.control.control_loop_manager import ControlLoopManager
 
@@ -21,8 +25,6 @@ from functools import partial
 from collections import deque
 from argparse import Namespace
 
-from smc.robots.interfaces.whole_body_interface import SingleArmWholeBodyInterface
-
 
 def CrocoEEP2PMPCControlLoop(
     ocp: CrocoOCP,
diff --git a/python/smc/control/optimal_control/point_to_point_croco_ocp.py b/python/smc/control/optimal_control/point_to_point_croco_ocp.py
index 707c0a137b5b4744da25a4a82dc072ab53061d1f..d4042997061d0f567150e23d0daa17737740cf5e 100644
--- a/python/smc/control/optimal_control/point_to_point_croco_ocp.py
+++ b/python/smc/control/optimal_control/point_to_point_croco_ocp.py
@@ -1,6 +1,10 @@
 from smc.control.optimal_control.abstract_croco_ocp import CrocoOCP
 from smc.robots.interfaces.single_arm_interface import SingleArmInterface
 from smc.robots.interfaces.dual_arm_interface import DualArmInterface
+from smc.robots.interfaces.whole_body_interface import (
+    SingleArmWholeBodyInterface,
+    DualArmWholeBodyInterface,
+)
 
 import numpy as np
 import pinocchio as pin
@@ -147,7 +151,7 @@ class BaseAndSingleArmIKOCP(SingleArmIKOCP):
     def __init__(
         self,
         args: Namespace,
-        robot: SingleArmInterface,
+        robot: SingleArmWholeBodyInterface,
         x0: np.ndarray,
         goal,
         #        T_w_eegoal: pin.SE3,
@@ -197,6 +201,7 @@ class BaseAndSingleArmIKOCP(SingleArmIKOCP):
             "base_translation" + str(self.args.n_knots)
         ].cost.residual.reference = p_basegoal
 
+
 class BaseAndDualArmIKOCP(DualArmIKOCP):
     def __init__(
         self,
@@ -214,7 +219,7 @@ class BaseAndDualArmIKOCP(DualArmIKOCP):
         # self, T_w_eegoal: pin.SE3, p_basegoal: np.ndarray
         self,
         goal,
-    )-> None:
+    ) -> None:
         T_w_lgoal, T_w_rgoal, p_basegoal = goal
         super().constructTaskObjectiveFunction((T_w_lgoal, T_w_rgoal))
         for i in range(self.args.n_knots):
diff --git a/python/smc/robots/interfaces/whole_body_interface.py b/python/smc/robots/interfaces/whole_body_interface.py
index 752fdff47f290a5b069ee8aec89fd726f1798926..e88c1d9ad9e0ddbd5821870d0e14f31ac507f7f8 100644
--- a/python/smc/robots/interfaces/whole_body_interface.py
+++ b/python/smc/robots/interfaces/whole_body_interface.py
@@ -1,5 +1,6 @@
 from smc.robots.interfaces.mobile_base_interface import MobileBaseInterface
 from smc.robots.interfaces.single_arm_interface import SingleArmInterface
+from smc.robots.interfaces.dual_arm_interface import DualArmInterface
 
 import pinocchio as pin
 from argparse import Namespace
@@ -135,3 +136,7 @@ class SingleArmWholeBodyInterface(SingleArmInterface, MobileBaseInterface):
         assert len(v) == self.model.nv
         v = np.clip(v, -1 * self._max_v, self._max_v)
         self.sendVelocityCommandToReal(v)
+
+
+class DualArmWholeBodyInterface(DualArmInterface, MobileBaseInterface):
+    pass