diff --git a/c++/CMakeLists.txt b/c++/CMakeLists.txt
index 2cfe3a63f828b10e83f7d86ecdcf341ab389a577..37cd050b08162f4bb4eb5495e7c62d60cdb7350e 100644
--- a/c++/CMakeLists.txt
+++ b/c++/CMakeLists.txt
@@ -14,7 +14,7 @@ find_package (broccoli 3.0.0 COMPONENTS eigen REQUIRED)
 find_package(RL COMPONENTS MDL REQUIRED)
 
 # dependencies for gpm function
-add_library(my_funcs SHARED src/gpm.cpp src/loadKinematicModel.cpp src/pointer_example.cpp)
+add_library(my_funcs SHARED src/yumi.cpp)
 target_link_libraries (
     my_funcs 
     ${RL_LIBRARIES}
@@ -32,7 +32,7 @@ target_link_libraries(
     eat::broccoli
 )
 
-add_executable(myMain src/main.cpp src/gpm.cpp src/loadKinematicModel.cpp src/pointer_example.cpp)
+add_executable(myMain src/main.cpp src/yumi.cpp)
 target_link_libraries(
     myMain
     eat::broccoli
diff --git a/c++/include/gpm.hpp b/c++/include/gpm.hpp
deleted file mode 100644
index 4d367ee8fe7bd37f4b59e8723fc6fa5305cabd32..0000000000000000000000000000000000000000
--- a/c++/include/gpm.hpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <Eigen/Eigen>
-#include <rl/mdl/Kinematic.h>
-
-
-std::pair<Eigen::Matrix<double, 7, 1>, Eigen::Matrix<double, 6, 1>> gpm(Eigen::Matrix<double, 6, 1> &desPose, Eigen::Matrix<double, 6, 1> &desVelocity, 
-Eigen::Matrix<double, 7, 1> &jointAngles, Eigen::Matrix<double, 7, 1> &jointVelocity, std::shared_ptr<rl::mdl::Model> model);
diff --git a/c++/include/loadKinematicModel.hpp b/c++/include/loadKinematicModel.hpp
deleted file mode 100644
index b6be6d077a34fe2110592ffb0dfc54b6c7bcbf6e..0000000000000000000000000000000000000000
--- a/c++/include/loadKinematicModel.hpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <rl/mdl/Kinematic.h>
-
-class Arm {
-    public:
-    Arm(std::string path);
-
-    std::shared_ptr<rl::mdl::Model> get_pointer2arm();
-
-    private:
-    //rl::mdl::Kinematic kin_model;
-    std::shared_ptr<rl::mdl::Model> model;
- };
diff --git a/c++/include/pointer_example.hpp b/c++/include/pointer_example.hpp
deleted file mode 100644
index 2f2ad00d9db55c8615b9f48a049dbf06324cc780..0000000000000000000000000000000000000000
--- a/c++/include/pointer_example.hpp
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-void * get_pointer();
-
-void set_pointer(void * pointer);
\ No newline at end of file
diff --git a/c++/include/yumi.hpp b/c++/include/yumi.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..28f8410505583b81a2857dc6049cdcae9b905077
--- /dev/null
+++ b/c++/include/yumi.hpp
@@ -0,0 +1,67 @@
+#include <iostream>
+
+#include <Eigen/Eigen>
+
+#include <broccoli/control/kinematics/ComfortPoseGradient.hpp>
+#include <broccoli/core/math.hpp>
+
+#include <rl/math/Transform.h>
+#include <rl/mdl/Kinematic.h>
+#include <rl/mdl/Model.h>
+#include <rl/mdl/UrdfFactory.h>
+
+class Yumi {
+    public:
+
+    //functions
+    Yumi(std::string path);
+
+    void set_jointValues(Eigen::Matrix<double, 7, 1> &jointAngles, Eigen::Matrix<double, 7, 1> &jointVelocity);
+    void set_desPoseVel(Eigen::Matrix<double, 6, 1> &desPose, Eigen::Matrix<double, 6, 1> &desVelocity);
+    void set_driftCompGain(double gain);
+    void set_sampleTime(double sampleTime);
+
+    void process();
+
+    Eigen::Matrix<double, 7, 1> get_newJointValues();
+    Eigen::Matrix<double, 6, 1> get_newPose();
+
+    // for debugging
+    void print_pose();
+
+    private:
+    // vars for rl library
+    rl::mdl::Kinematic* m_kinematic;
+    rl::mdl::Kinematic m_kin_model;
+
+    // vars for tuning
+    double m_driftCompGain = 1.0;
+    double m_sampleTime = 0.0125;
+    double m_activationFactorTaskSpace = 1.0;
+
+    // vars to store configuration
+    rl::math::Vector3 m_desPosition = rl::math::Vector3::Zero();
+    rl::math::Vector3 m_desPositionDot = rl::math::Vector3::Zero();
+	rl::math::Vector3 m_desOrientation = rl::math::Vector3::Zero();
+    rl::math::Vector3 m_desOrientationDot = rl::math::Vector3::Zero();
+
+    Eigen::Matrix<double, 7, 1> m_jointAngles = Eigen::Matrix<double, 7, 1>::Zero();
+    Eigen::Matrix<double, 7, 1> m_jointVelocity = Eigen::Matrix<double, 7, 1>::Zero();
+
+    rl::math::Vector3 m_position = rl::math::Vector3::Zero();
+	rl::math::Vector3 m_orientation = rl::math::Vector3::Zero(); //Euler ZYX convention
+
+    Eigen::Matrix<double, 6, 1> m_effectiveTaskSpaceInput = Eigen::Matrix<double, 6, 1>::Zero();
+
+    Eigen::Matrix<double, 7, 7>  m_inverseWeighing = Eigen::Matrix<double, 7, 7> ::Identity();
+    Eigen::Matrix<double, 7, 1> m_nullSpaceGradient = Eigen::Matrix<double, 7, 1>::Zero();
+
+    Eigen::Matrix<double, 7, 1> m_jointAnglesDelta;
+
+    // private functions
+    void doForwardKinematics(rl::mdl::Kinematic* kinematic);
+    Eigen::Matrix3d euler2rotMatrix(rl::math::Vector3 orientation);
+    void compTaskSpaceInput();
+
+    
+ };
\ No newline at end of file
diff --git a/c++/src/gpm.cpp b/c++/src/gpm.cpp
deleted file mode 100644
index 4aac2751893a816ed9a4080254fb81f40a179063..0000000000000000000000000000000000000000
--- a/c++/src/gpm.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <iostream>
-#include <string>
-
-#include <broccoli/control/kinematics/ComfortPoseGradient.hpp>
-#include <broccoli/core/math.hpp>
-
-#include <rl/math/Transform.h>
-#include <rl/mdl/Kinematic.h>
-#include <rl/mdl/Model.h>
-#include <rl/mdl/UrdfFactory.h>
-
-
-std::pair<Eigen::Matrix<double, 7, 1>, Eigen::Matrix<double, 6, 1>> gpm(Eigen::Matrix<double, 6, 1> &desPose, Eigen::Matrix<double, 6, 1> &desVelocity, 
-Eigen::Matrix<double, 7, 1> &jointAngles, Eigen::Matrix<double, 7, 1> &jointVelocity, std::shared_ptr<rl::mdl::Model> model) {
-
-	rl::mdl::Kinematic* kinematic = dynamic_cast<rl::mdl::Kinematic*>(model.get());
-
-	// FORWARD KINEMATICS
-	
-
-	//std::cout << "pointer in gpm" << kinematic_ptr << std::endl;
-	//rl::mdl::Kinematic* kinematic = kinematicPtr;
-
-	kinematic->setPosition(jointAngles);
-	kinematic->forwardPosition();
-	kinematic->calculateJacobian();
-
-	Eigen::Matrix<double, 6, 7> J;
-	// copy entries from RL jacobian to Eigen::jacobian in order to use it in brocolli function
-	for (int i = 0; i < 7; i++){
-		for (int j = 0; j < 6; j++){
-			J(j, i) = kinematic->getJacobian()(j, i);
-		}
-	}
-
-
-	// check if matrices are the same
-	//std::cout << "RLJacobian \n" << kinematic->getJacobian() << std::endl;
-	//std::cout << "myJacobian \n" << J << std::endl;
-	//std::cout << "Manipulability meassure \n" << kinematic->calculateManipulabilityMeasure() << std::endl;
-	
-	// extract orientation and position for the right arm
-	rl::math::Transform t = kinematic->getOperationalPosition(0);
-	rl::math::Vector3 position = t.translation();
-	rl::math::Vector3 orientation = t.rotation().eulerAngles(2, 1, 0).reverse();
-	//std::cout << "Joint configuration in degrees: " << jointAngles.transpose() * rl::math::RAD2DEG << std::endl;
-	//std::cout << "FK end-effector position: [m] " << position.transpose() << " orientation [deg] " << orientation.transpose() * rl::math::RAD2DEG << std::endl;
-	
-	// INVERSE KINEMATICS
-	// compute translation and orientation error
-	Eigen::Matrix3d desOrientation;
-	// go from Euler ZYX to rotation matrix
-	desOrientation = Eigen::AngleAxisd(desPose(5), Eigen::Vector3d::UnitZ())
-					*Eigen::AngleAxisd(desPose(4), Eigen::Vector3d::UnitY())
-					*Eigen::AngleAxisd(desPose(3), Eigen::Vector3d::UnitX());
-					
-	//std::cout << "reverse euler angles" << desOrientation.eulerAngles(2, 1, 0).reverse();
-
-	//  check if these two rotation matrices match!
-	//std::cout << "desOrientation \n" << desOrientation << std::endl;
-	//std::cout << "RL Orientation \n" << t.rotation() << std::endl;
-
-	//Eigen::Vector3d einheitsvektor;
-	//einheitsvektor << 1.0, 0.0, 0.0;
-	//std::cout << "desOrientation x einheitsvektor \n" << desOrientation* einheitsvektor << std::endl;
-	//std::cout << "RL Orientation x einheitsvektor\n" << t.rotation()*einheitsvektor << std::endl;
-
-
-	// define Quaternion with coefficients in the order [x, y, z, w] 
-	Eigen::Vector3d desiredTranslation = desPose.head(3);
-	//std::cout << "desiredTranslation" << desiredTranslation << std::endl;
-	Eigen::Quaterniond desiredOrientation(desOrientation);
-
-	// set the current positions
-	Eigen::Matrix<double, 3, 1> currentTranslation;
-	currentTranslation << position.x(), position.y(), position.z();
-	Eigen::Quaterniond currentOrientation(t.rotation());
-	
-	// chose the correct quaternion such that the distance between desired and current
-	// quaternion is the shortest
-	if (desiredOrientation.dot(currentOrientation) < 0.0) {
-		currentOrientation.coeffs() *= -1.0;
-	}
-	// calculate delta between quaternions
-	Eigen::Quaterniond errorQuaternion = currentOrientation.inverse() * desiredOrientation;
-	Eigen::Vector3d errorRotationInWorldFrame = currentOrientation * errorQuaternion.vec();
-
-	// compute task space velocity with drift compensation
-	const double gainDriftCompensation = 0.1;
-	const double dt = 0.0125; // refers to 80 Hz
-    Eigen::Matrix<double, 6, 1> effectiveTaskSpaceInput = Eigen::Matrix<double, 6, 1>::Zero();
-	effectiveTaskSpaceInput.head(3) = gainDriftCompensation/dt * (desiredTranslation - currentTranslation)
-										+ desVelocity.head(3);
-	effectiveTaskSpaceInput.tail(3) = gainDriftCompensation/dt * errorRotationInWorldFrame + desVelocity.tail(3);
-	//std::cout << "effectiveTaskSpaceInput: " << effectiveTaskSpaceInput << std::endl;
-
-
-
-
-	// COMPUTE CPG GRADIENT
-	// define min and max values for the joints of Yumi
-	Eigen::Matrix< double, 7, 1> q_min;
-	Eigen::Matrix< double, 7, 1> q_max;
-	q_min << -168.5, -143.5, -168.5, -123.5, -290, -88, -229;
-	q_min *= rl::math::DEG2RAD;
-	q_max << 168.5, 43.5, 168.5, 80, 290, 138, 229;
-	q_max *= rl::math::DEG2RAD;
-	// create CompfortPoseGradient object
-	broccoli::control::ComfortPoseGradient<7> cpg;
-	// compute CPG gradient
-	cpg.useRangeBasedScaling(q_min, q_max);
-	//cpg.setWeight() by default it is 1
-
-	Eigen::Matrix<double, 7, 1> cpgGradient = Eigen::Matrix<double, 7, 1>::Zero();
-	cpgGradient = cpg.process(jointAngles, jointVelocity);	// if gradient is zero then the ASC is just a resolved motion ik method
-
-	// COMPUTE MANIPULABILTY GRADIENT
-	// compute Jacobian derivative - code snippet from Jonas Wittmann
-	std::array<Eigen::Matrix<double, 6, 7>, 7> dJ; // NOLINT
-    for (auto& matrix : dJ) {
-        matrix = Eigen::Matrix<double, 6, 7>::Zero();
-    }
-    Eigen::Matrix<double, 3, 7> transJ = Eigen::Matrix<double, 3, 7>::Zero();
-    transJ = J.block<3, 7>(0, 0);
-    Eigen::Matrix<double, 3, 7> rotJ = Eigen::Matrix<double, 3, 7>::Zero();
-    rotJ = J.block<3, 7>(3, 0);
-    const int numOfJoints = 7;
-    for (int jj = 0; jj < numOfJoints; ++jj) {
-        for (int ii = jj; ii < numOfJoints; ++ii) {
-            dJ.at(jj).block<3, 1>(0, ii) = rotJ.col(jj).cross(transJ.col(ii));
-            dJ.at(jj).block<3, 1>(3, ii) = rotJ.col(jj).cross(rotJ.col(ii));
-            if (ii != jj) {
-                dJ.at(ii).block<3, 1>(0, jj) = dJ.at(jj).block<3, 1>(0, ii);
-            }
-        }
-    }
-
-	Eigen::Matrix<double, 7, 1> manipGradient = Eigen::Matrix<double, 7, 1>::Zero();
-    double cost = sqrt((J * J.transpose()).determinant());
-    // Compute the manipulability gradient.
-    for (int jj = 0; jj < 7; ++jj) {
-        manipGradient[jj] = cost * ((J * J.transpose()).inverse() * dJ.at(jj) * J.transpose()).trace();
-    }
-	// add both gradients
-	Eigen::Matrix<double, 7, 1> nullSpaceGradient = Eigen::Matrix<double, 7, 1>::Zero();
-	nullSpaceGradient = 0*manipGradient + 0*cpgGradient;
-
-
-
-	// ASC desired effective velocity does not work -> implement myself
-	Eigen::Matrix<double, 7, 7>  m_inverseWeighing = Eigen::Matrix<double, 7, 7> ::Identity();
-	double m_activationFactorTaskSpace = 1.0;
-	Eigen::Matrix<double, 7, 1> nullSpaceVelocity = -m_inverseWeighing * nullSpaceGradient;
-	Eigen::Matrix<double, 7, 1> jointVelocities;
-	jointVelocities = broccoli::core::math::solvePseudoInverseEquation(J, m_inverseWeighing, effectiveTaskSpaceInput, nullSpaceVelocity, m_activationFactorTaskSpace);
-	//std::cout << "resulting jointVelocities: \n" << jointVelocities << std::endl;
-
-	// perform integration over one timestep to obtain positions that can be send to robot
-	Eigen::Matrix<double, 7, 1> jointAnglesDelta;
-	jointAnglesDelta << jointVelocities * dt;
-
-
-	//std::cout << "current qs in DEG \n" << jointAngles* rl::math::RAD2DEG << std::endl;
-	//std::cout << "delta qs in DEG \n" << jointAnglesDelta * rl::math::RAD2DEG << std::endl;
-	//std::cout << "next qs in DEG \n" << (jointAngles+jointAnglesDelta)* rl::math::RAD2DEG << std::endl;
-
-	// forward kinematics with the new joints values from IK
-	kinematic->setPosition(jointAngles+jointAnglesDelta);
-	kinematic->forwardPosition();
-
-	rl::math::Transform dest = kinematic->getOperationalPosition(0);
-	rl::math::Vector3 dposition = dest.translation();
-	rl::math::Vector3 dorientation = dest.rotation().eulerAngles(2, 1, 0).reverse();
-	//std::cout << "IK joint configuration in degrees: " << (jointAngles+jointAnglesDelta).transpose() * rl::math::RAD2DEG << std::endl;
-	//std::cout << "IK end-effector position: [m] " << dposition.transpose() << " orientation [deg] " << dorientation.transpose() * rl::math::RAD2DEG << std::endl;
-	
-	Eigen::Matrix<double, 6, 1> resPose;
-	resPose << dposition.transpose()(0), dposition.transpose()(1), dposition.transpose()(2), dorientation.transpose()(0), dorientation.transpose()(1), dorientation.transpose()(2);
-
-	// return desired joint angles for the next step and pose for computing the IK accuracy
-	return std::make_pair((jointAngles+jointAnglesDelta), resPose);
-}
-
diff --git a/c++/src/loadKinematicModel.cpp b/c++/src/loadKinematicModel.cpp
deleted file mode 100644
index 856f00af1bae7364f73f7ce67541035008e3e00e..0000000000000000000000000000000000000000
--- a/c++/src/loadKinematicModel.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <iostream>
-#include <rl/mdl/Model.h>
-#include <rl/mdl/UrdfFactory.h>
-#include <rl/mdl/Kinematic.h>
-#include "loadKinematicModel.hpp"
-
-
-Arm::Arm(std::string path){
-    rl::mdl::UrdfFactory factory;
-    std::shared_ptr<rl::mdl::Model> model_tmp(factory.create(path));
-    model = model_tmp;
-    
-    
-    //std::cout << "adress of pointer load " << void_pointer << std::endl;
-    }
-
-std::shared_ptr<rl::mdl::Model> Arm::get_pointer2arm() {return model;}
-
-
-/* class Arm {
-    public:
-    // constrcutor
-    Arm(std::string path){
-    rl::mdl::UrdfFactory factory;
-    std::shared_ptr<rl::mdl::Model> model(factory.create(path));
-    kin_pointer = dynamic_cast<rl::mdl::Kinematic*>(model.get());
-    kin_model = *(kin_pointer);
-    rl::mdl::Kinematic* tmp_pointer = &kin_model;
-    void_pointer = (void*) tmp_pointer;
-    }
-
-    void* get_pointer2arm() { return  void_pointer; }
-
-    private:
-    rl::mdl::Kinematic* kin_pointer;
-    rl::mdl::Kinematic kin_model;
-    void* void_pointer;
- }; */
diff --git a/c++/src/main.cpp b/c++/src/main.cpp
deleted file mode 100644
index 43be50a532d9bcfabc7ffff62de23767ff0f2f3c..0000000000000000000000000000000000000000
--- a/c++/src/main.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include <iostream>
-#include "gpm.hpp"
-#include "loadKinematicModel.hpp"
-#include "pointer_example.hpp"
-
-#include <Eigen/Eigen>
-#include <rl/math/Unit.h>
-#include <rl/mdl/Kinematic.h>
-#include <rl/mdl/Model.h>
-#include <rl/mdl/UrdfFactory.h>
-
-
-int main(int, char**) {
-
-	enum yumi_arm{YUMI_RIGHT, YUMI_LEFT};
-
-	//rl::mdl::Kinematic *kinematic_ptr = loadKinematicModel("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_left.urdf");
-
-	
-	//std::cout << *((int*)p) << std::endl;
-
-	rl::mdl::UrdfFactory factory;
-	std::shared_ptr<rl::mdl::Model> model(factory.create("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_left.urdf"));
-	rl::mdl::Kinematic* kinematic = dynamic_cast<rl::mdl::Kinematic*>(model.get());
-
-	Arm right_arm("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_right.urdf");
-	std::shared_ptr<rl::mdl::Model> abc = right_arm.get_pointer2arm();
-
-	// Is Values
-	Eigen::Matrix<double, 6, 1> actualPosition;
-	Eigen::Matrix<double, 7, 1> jointAngles;
-	//jointAngles << 90.48, 17.87, -25.0, 48.0, -137.0, 122.0, -74.21; // start position left arm, angles from RS
-	jointAngles << -110.0, 29.85, 35.92, 49.91, 117.0, 123.0, -117.0; // start position right arm, angles from RS
-	//jointAngles << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
-	jointAngles *= rl::math::DEG2RAD;
-	
-	Eigen::Matrix<double, 7, 1> jointVelocity;
-	jointVelocity << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
-	
-	// Desired Values
-	Eigen::Matrix<double, 6, 1> desPose;
-	desPose << 0.300, 0.200, 0.200, 33.4*rl::math::DEG2RAD, 157.0*rl::math::DEG2RAD, 39.4*rl::math::DEG2RAD; // obtained from RS with stated joint values
-	Eigen::Matrix<double, 6, 1> desVelocity;
-	desVelocity << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
-
-	std::pair<Eigen::Matrix<double, 7, 1>, Eigen::Matrix<double, 6, 1>> result;
-	result = gpm(desPose, desVelocity, jointAngles, jointVelocity, abc);
-	
-	std::cout << "desired joint values: \n" << result.first << std::endl;
-	std::cout << "current pose: \n" << result.second << std::endl;
-
-
-
-	int number = 7;
-    int *mypointer = &number;
-	set_pointer(mypointer);
-
-	void * p = get_pointer();
-	set_pointer(p);
-	
-
-	
-	return 0;
-}
\ No newline at end of file
diff --git a/c++/src/pointer_example.cpp b/c++/src/pointer_example.cpp
deleted file mode 100644
index c140dbdbcdc78339ae4c30720ae037c509c6121a..0000000000000000000000000000000000000000
--- a/c++/src/pointer_example.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <iostream>
-
-void * get_pointer(){
-    static int number = 7;
-    int *p2number = &number;
-    std::cout << "pointer_ref" << (void*) p2number << std::endl;
-    return ((void *) p2number);
-}
-
-void set_pointer(void * pointer){
-    std::cout << "int value from pointer " << *((int*) pointer) << std::endl;
-    std::cout << "void pointer " << pointer << std::endl;
-} 
\ No newline at end of file
diff --git a/c++/src/py2gpmbind.cpp b/c++/src/py2gpmbind.cpp
index d9c9addeb5f3614af4bc5a82efc79670f53768ff..9aa1f932e39e45a1fec487bdcbb02a87730923cb 100644
--- a/c++/src/py2gpmbind.cpp
+++ b/c++/src/py2gpmbind.cpp
@@ -1,8 +1,6 @@
 #include <pybind11/pybind11.h>
 #include <pybind11/eigen.h>
-#include "gpm.hpp"
-#include "loadKinematicModel.hpp"
-#include "pointer_example.hpp"
+#include "yumi.hpp"
 #include <rl/mdl/UrdfFactory.h>
 
 namespace py = pybind11;
@@ -11,17 +9,13 @@ namespace py = pybind11;
 
 PYBIND11_MODULE(invKin, m) {
     m.doc() = "pybind11 binding to C++ function that computes IK based on GPM"; // optional module docstring
-    m.def("gpm", &gpm, "A function to compute the invserse kinematics for a 7 DOF serial manipulator on vecocity level with comfort pose and manipulabilty gradient",
-    py::arg("desired pose"),py::arg("desired Velocities"), py::arg("joint angles"), py::arg("joint velocities"), py::arg("left arm -> 1, right arm -> 0"), py::return_value_policy::copy);
-	
-    // load model and return ptr for future function calls
-    // https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies
 
-
-    m.def("set_pointer", &set_pointer, "set pointer", py::arg("pointer"), py::return_value_policy::move);
-    m.def("get_pointer", &get_pointer, py::return_value_policy::move);
-
-    py::class_<Arm>(m, "Arm")
+    py::class_<Yumi>(m, "Yumi")
        .def(py::init<std::string>())
-       .def("get_pointer2arm", &Arm::get_pointer2arm);
+       .def("set_jointValues", &Yumi::set_jointValues, py::arg("joint angles"), py::arg("joint velocities"))
+       .def("set_desPoseVel", &Yumi::set_desPoseVel, py::arg("desired pose"), py::arg("desired velocities"))
+       .def("process", &Yumi::process)
+       .def("get_newJointValues", &Yumi::get_newJointValues)
+       .def("get_newPose", &Yumi::get_newPose)
+       .def("printPose", &Yumi::print_pose); 
 	}
\ No newline at end of file
diff --git a/c++/src/yumi.cpp b/c++/src/yumi.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c835410e192007b1efed795fffe639e913a62560
--- /dev/null
+++ b/c++/src/yumi.cpp
@@ -0,0 +1,109 @@
+#include <iostream>
+
+#include <broccoli/control/kinematics/ComfortPoseGradient.hpp>
+#include <broccoli/core/math.hpp>
+
+#include <rl/math/Transform.h>
+#include <rl/mdl/Kinematic.h>
+#include <rl/mdl/Model.h>
+#include <rl/mdl/UrdfFactory.h>
+
+#include <yumi.hpp>
+
+// constructor
+Yumi::Yumi(std::string path){
+    rl::mdl::UrdfFactory factory;
+    std::shared_ptr<rl::mdl::Model> model(factory.create(path));
+    rl::mdl::Kinematic* kinematic = dynamic_cast<rl::mdl::Kinematic*>(model.get());
+    m_kin_model = *(kinematic);
+    m_kinematic = &m_kin_model;
+}
+
+void Yumi::set_jointValues(Eigen::Matrix<double, 7, 1> &jointAngles, Eigen::Matrix<double, 7, 1> &jointVelocity){
+    m_jointAngles = jointAngles;
+    m_jointVelocity = jointVelocity;
+}
+
+void Yumi::doForwardKinematics(rl::mdl::Kinematic* kinematic){
+    kinematic->setPosition(m_jointAngles);
+    kinematic->forwardPosition();
+    kinematic->calculateJacobian();
+    rl::math::Transform t = kinematic->getOperationalPosition(0);
+	m_position = t.translation();
+	m_orientation = t.rotation().eulerAngles(2, 1, 0).reverse();
+}
+
+void Yumi::print_pose(){
+    Yumi::doForwardKinematics(&m_kin_model);
+    std::cout << "pose " << m_position << "\n" << m_orientation << std::endl;
+}
+
+void Yumi::set_driftCompGain(double gain){
+    m_driftCompGain = gain;
+}
+
+void Yumi::set_sampleTime(double sampleTime){
+    m_sampleTime = sampleTime;
+}
+
+void Yumi::set_desPoseVel(Eigen::Matrix<double, 6, 1> &desPose, Eigen::Matrix<double, 6, 1> &desVelocity){
+
+    m_desPosition = desPose.head(3);
+    m_desOrientation = desPose.tail(3);
+    m_desPositionDot = desVelocity.head(3);
+    m_desOrientationDot = desVelocity.tail(3);
+}
+
+Eigen::Matrix3d Yumi::euler2rotMatrix(rl::math::Vector3 eulerAngles){
+    Eigen::Matrix3d desOrientation;
+	// go from Euler ZYX to rotation matrix
+	desOrientation = Eigen::AngleAxisd(eulerAngles(2), Eigen::Vector3d::UnitZ())
+					*Eigen::AngleAxisd(eulerAngles(1), Eigen::Vector3d::UnitY())
+					*Eigen::AngleAxisd(eulerAngles(0), Eigen::Vector3d::UnitX());
+    return desOrientation;
+}
+
+void Yumi::compTaskSpaceInput(){
+    Eigen::Quaterniond desiredOrientation(euler2rotMatrix(m_desOrientation));
+    Eigen::Quaterniond currentOrientation(euler2rotMatrix(m_orientation));
+
+    // chose the correct quaternion such that the distance between desired and current
+	// quaternion is the shortest
+	if (desiredOrientation.dot(currentOrientation) < 0.0) {
+		currentOrientation.coeffs() *= -1.0;
+	}
+	// calculate delta between quaternions
+	Eigen::Quaterniond errorQuaternion = currentOrientation.inverse() * desiredOrientation;
+	Eigen::Vector3d errorRotationInWorldFrame = currentOrientation * errorQuaternion.vec();
+
+    m_effectiveTaskSpaceInput.head(3) = m_driftCompGain/m_sampleTime * (m_desPosition - m_position)
+										+ m_desPositionDot;
+	m_effectiveTaskSpaceInput.tail(3) = m_driftCompGain/m_sampleTime * errorRotationInWorldFrame + m_desOrientationDot;
+
+}
+
+void Yumi::process(){
+
+    doForwardKinematics(&m_kin_model);
+    compTaskSpaceInput();
+
+    Eigen::Matrix<double, 7, 1> jointVelocities;
+    Eigen::Matrix<double, 7, 1> nullSpaceVelocity = -m_inverseWeighing * m_nullSpaceGradient;
+	jointVelocities = broccoli::core::math::solvePseudoInverseEquation((&m_kin_model)->getJacobian(), m_inverseWeighing, m_effectiveTaskSpaceInput,
+                     nullSpaceVelocity, m_activationFactorTaskSpace);
+
+	m_jointAnglesDelta << jointVelocities * m_sampleTime;
+
+    m_jointAngles += m_jointAnglesDelta;
+}
+
+Eigen::Matrix<double, 7, 1> Yumi::get_newJointValues(){
+    return m_jointAngles;
+}
+
+Eigen::Matrix<double, 6, 1> Yumi::get_newPose(){
+    doForwardKinematics(&m_kin_model);
+    Eigen::Matrix<double, 6, 1> pose;
+    pose << m_position, m_orientation;
+    return pose;
+}
diff --git a/python/taskspace_placement/computeJoints.py b/python/taskspace_placement/computeJoints.py
index df36d945882ef2a38dbfda8c1454b8235822ab8e..8939414ae0307f187b38c610ca80e18f45fcfbe5 100644
--- a/python/taskspace_placement/computeJoints.py
+++ b/python/taskspace_placement/computeJoints.py
@@ -4,7 +4,7 @@ from matplotlib import pyplot as plt
 
 import numpy as np
 import copy
-from libs.invKin import *
+import libs.invKin as invKin
 
 from data.get_data import get_trajectory, transform2yumi_workspace, place_trajectory, Yumi
 
@@ -29,62 +29,65 @@ jointVelocities = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
 dt = 0.0125
 
 # create arrays to store values of loop
-desJointAngles_left = np.zeros((len(p1[:,0]),7))
+compJointAngles_left = np.zeros((len(p1[:,0]),7))
 computedPose_left = np.zeros((len(p1[:,0]),6))
 error_left = np.zeros((len(p1[:,0]),6))
 
-left_arm = Arm("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_left.urdf")
-left_arm_p = left_arm.get_pointer2arm()
+yumi_left = invKin.Yumi("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_left.urdf")
+yumi_right = invKin.Yumi("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_right.urdf")
 
-right_arm = Arm("/home/joschua/Coding/forceControl/master-project/c++/models/urdf/yumi_right.urdf")
-right_arm_p = right_arm.get_pointer2arm()
+#yumi_left.printPose()
 
 # loop for the left arm
 for index, (pos, vel, phi, phi_dot) in enumerate(zip(p1, v1, phi_delta, dphi)): # loop through all the desired position of left arm
     desPose = np.concatenate((pos, phi), axis=0) 
     desVelocities = np.concatenate((vel, phi_dot), axis=0) 
     # call the c++ egm function, return joint values and resulting pose
-    result = gpm(desPose, desVelocities, jointAngles, jointVelocities, left_arm_p)
-    desJointAngles_left[index,:] = result[0] # computed joint values from IK
-    computedPose_left[index, :] = result[1] # resulting pose with joint values from IK
+    yumi_left.set_jointValues(jointAngles, jointVelocities)
+    yumi_left.set_desPoseVel(desPose, desVelocities)
+    yumi_left.process()
+
+    compJointAngles_left[index,:] = yumi_left.get_newJointValues() # computed joint values from IK
+    computedPose_left[index, :] = yumi_left.get_newPose() # resulting pose with joint values from IK
     if index > 0:
-        jointVelocities = (desJointAngles_left[index, :] - desJointAngles_left[index-1, :])/dt # only true in the ideal case where result of ik matches the desired pose
-    #print('IK joints:',  result[0])
-    #print('IK resulting pose',  result[1])
-    print('\n error', desPose - result[1])
-    error_left[index, :] = desPose - result[1]
-    jointAngles = result[0] 
+        jointVelocities = (compJointAngles_left[index, :] - compJointAngles_left[index-1, :])/dt # only true in the ideal case where result of ik matches the desired pose
+    error_left[index, :] = desPose - computedPose_left[index, :]
+    jointAngles = compJointAngles_left[index, :]
+
 
 
 
-desJointAngles_right = np.zeros((len(p1[:,0]),7))
+compJointAngles_right = np.zeros((len(p1[:,0]),7))
 computedPose_right = np.zeros((len(p1[:,0]),6))
 error_right = np.zeros((len(p1[:,0]),6))
 
 jointAngles = np.array([-110.0, 29.85, 35.92, 49.91, 117.0, 123.0, -117.0]) * np.pi/180.0 
 
 # loop for the right arm
-for index, (pos, vel, phi, phi_dot) in enumerate(zip(p2, v2, phi_delta, dphi)): # loop through all the desired position of left arm
+""" for index, (pos, vel, phi, phi_dot) in enumerate(zip(p2, v2, phi_delta, dphi)): # loop through all the desired position of left arm
     desPose = np.concatenate((pos, phi), axis=0) 
     desVelocities = np.concatenate((vel, phi_dot), axis=0) 
-    result = gpm(desPose, desVelocities, jointAngles, jointVelocities, right_arm_p)
-    desJointAngles_right[index,:] = result[0] 
-    computedPose_right[index, :] = result[1] 
+    yumi_right.set_jointValues(jointAngles, jointVelocities)
+    yumi_right.set_desPoseVel(desPose, desVelocities)
+    yumi_right.process()
+
+    compJointAngles_right[index,:] = yumi_right.get_newJointValues() # computed joint values from IK
+    computedPose_right[index, :] = yumi_right.get_newPose() # resulting pose with joint values from IK
+    
     if index > 0:
-        jointVelocities = (desJointAngles_left[index, :] - desJointAngles_left[index-1, :])/dt 
-    print('\n error', desPose - result[1])
-    error_right[index, :] = desPose - result[1]
-    jointAngles = result[0]  
+        jointVelocities = (compJointAngles_left[index, :] - compJointAngles_left[index-1, :])/dt 
+    error_right[index, :] = desPose - computedPose_right[index, :]
+    jointAngles = compJointAngles_right[index,:]  """
 
 # see development of joint values
 fig = plt.figure()
-plt.plot(desJointAngles_left[:,0], label='joint1')
-plt.plot(desJointAngles_left[:,1], label='joint2')
-plt.plot(desJointAngles_left[:,2], label='joint3')
-plt.plot(desJointAngles_left[:,3], label='joint4')
-plt.plot(desJointAngles_left[:,4], label='joint5')
-plt.plot(desJointAngles_left[:,5], label='joint6')
-plt.plot(desJointAngles_left[:,6], label='joint7')
+plt.plot(compJointAngles_left[:,0], label='joint1')
+plt.plot(compJointAngles_left[:,1], label='joint2')
+plt.plot(compJointAngles_left[:,2], label='joint3')
+plt.plot(compJointAngles_left[:,3], label='joint4')
+plt.plot(compJointAngles_left[:,4], label='joint5')
+plt.plot(compJointAngles_left[:,5], label='joint6')
+plt.plot(compJointAngles_left[:,6], label='joint7')
 plt.title('joint values over samples, left arm')
 plt.legend()
 plt.show()
@@ -108,25 +111,25 @@ plt.scatter(computedPose_left[:,0], computedPose_left[:,2], label='resulting pos
 fig.get_axes()[0].set_xlabel('x axis of yumi')
 fig.get_axes()[0].set_ylabel('z axis of yumi')
 plt.legend()
-plt.title('view on the x-z plane from the right arm side of yumi')
+plt.title('poses left')
 plt.show()
 
-fig = plt.figure()
+""" fig = plt.figure()
 plt.plot(computedPose_left[:,3], label='rx')
 plt.plot(computedPose_left[:,4], label='ry')
 plt.plot(computedPose_left[:,5], label='rz')
 plt.legend()
 plt.title('euler angles over trajectories')
-plt.show()
+plt.show() """
 
 fig = plt.figure()
-plt.plot(desJointAngles_right[:,0], label='joint1')
-plt.plot(desJointAngles_right[:,1], label='joint2')
-plt.plot(desJointAngles_right[:,2], label='joint3')
-plt.plot(desJointAngles_right[:,3], label='joint4')
-plt.plot(desJointAngles_right[:,4], label='joint5')
-plt.plot(desJointAngles_right[:,5], label='joint6')
-plt.plot(desJointAngles_right[:,6], label='joint7')
+plt.plot(compJointAngles_right[:,0], label='joint1')
+plt.plot(compJointAngles_right[:,1], label='joint2')
+plt.plot(compJointAngles_right[:,2], label='joint3')
+plt.plot(compJointAngles_right[:,3], label='joint4')
+plt.plot(compJointAngles_right[:,4], label='joint5')
+plt.plot(compJointAngles_right[:,5], label='joint6')
+plt.plot(compJointAngles_right[:,6], label='joint7')
 plt.title('joint values over samples, right arm')
 plt.legend()
 plt.show()
@@ -149,9 +152,9 @@ plt.scatter(computedPose_right[:,0], computedPose_left[:,2], label='resulting po
 fig.get_axes()[0].set_xlabel('x axis of yumi')
 fig.get_axes()[0].set_ylabel('z axis of yumi')
 plt.legend()
-plt.title('view on the x-z plane from the right arm side of yumi')
+plt.title('poses right')
 plt.show()
 
-np.save('data/desJointAngles_left', desJointAngles_left)
-np.save('data/desJointAngles_right', desJointAngles_right)
+np.save('data/compJointAngles_left', compJointAngles_left)
+np.save('data/compJointAngles_right', compJointAngles_right)