mc_rtc::Configuration general purpose configurationNote: api.h, CMakeLists.txt and src/CMakeLists.txt are the same as in the previous example
DualArmController.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#pragma once
#include <mc_control/mc_controller.h>
#include <mc_solver/CollisionsConstraint.h>
#include <mc_tasks/EndEffectorTask.h>
#include <mc_tasks/PostureTask.h>
#include "api.h"
enum ControllerPhase
{
IDLE = 0,
STARTED,
MOVE
};
enum ControllerState
{
GO = 0,
RETURN
};
struct DualArmController_DLLAPI DualArmController : public mc_control::MCController
{
public:
DualArmController(mc_rbdyn::RobotModulePtr rm, double dt, const mc_rtc::Configuration & config);
bool run() override;
void reset(const mc_control::ControllerResetData & reset_data) override;
private:
void runUr();
void runKinova();
ControllerPhase phase_ = IDLE;
ControllerState urState_ = RETURN;
ControllerState kinovaState_ = RETURN;
std::shared_ptr<mc_tasks::PostureTask> kinovaPostureTask_;
std::shared_ptr<mc_tasks::EndEffectorTask> urEndEffectorTask_;
std::unique_ptr<mc_solver::KinematicsConstraint> kinovaKinematics_;
const double iDist = 0.1;
const double sDist = 0.05;
};
DualArmController.cpp1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "DualArmController.h"
#include <mc_rbdyn/RobotLoader.h>
DualArmController::DualArmController(mc_rbdyn::RobotModulePtr rm, double dt, const mc_rtc::Configuration & config)
: mc_control::MCController({rm, mc_rbdyn::RobotLoader::get_robot_module("KinovaDefault")}, dt)
{
solver().addConstraintSet(contactConstraint);
solver().addConstraintSet(kinematicsConstraint);
solver().addConstraintSet(selfCollisionConstraint);
addCollisions("ur5e", "kinova_default", {{"*", "*", iDist, sDist, 0}});
postureTask->stiffness(1);
postureTask->weight(1);
solver().addTask(postureTask);
solver().setContacts({{}});
}
bool DualArmController::run()
{
if(phase_ == IDLE)
{
postureTask->target({{"elbow_joint", {-M_PI / 2}}, {"wrist_2_joint", {M_PI / 2}}});
phase_ = STARTED;
}
else if(phase_ == STARTED && postureTask->eval().norm() < 0.01 && postureTask->speed().norm() < 0.01)
{
phase_ = MOVE;
solver().addTask(urEndEffectorTask_);
}
else if(phase_ == STARTED) { urEndEffectorTask_->reset(); }
else if(phase_ == MOVE)
{
runUr();
runKinova();
}
return mc_control::MCController::run();
}
void DualArmController::runUr()
{
if(urState_ == GO && urEndEffectorTask_->eval().norm() < 0.05 && urEndEffectorTask_->speed().norm() < 0.01)
{
urState_ = RETURN;
urEndEffectorTask_->add_ef_pose({Eigen::Vector3d(0.0, -0.5, 0.0)});
}
else if(urState_ == RETURN && urEndEffectorTask_->eval().norm() < 0.01 && urEndEffectorTask_->speed().norm() < 0.05)
{
urState_ = GO;
urEndEffectorTask_->add_ef_pose({Eigen::Vector3d(0.0, 0.5, 0.0)});
}
}
void DualArmController::runKinova()
{
if(kinovaState_ == GO && kinovaPostureTask_->eval().norm() < 0.01 && kinovaPostureTask_->speed().norm() < 0.01)
{
kinovaState_ = RETURN;
kinovaPostureTask_->target({{"joint_2", {0.0}}});
}
else if(kinovaState_ == RETURN && kinovaPostureTask_->eval().norm() < 0.01
&& kinovaPostureTask_->speed().norm() < 0.01)
{
kinovaState_ = GO;
kinovaPostureTask_->target({{"joint_2", {-M_PI / 4}}});
}
}
void DualArmController::reset(const mc_control::ControllerResetData & reset_data)
{
mc_control::MCController::reset(reset_data);
std::string urBody = "tool0";
urEndEffectorTask_ = std::make_shared<mc_tasks::EndEffectorTask>(urBody, robots(), 0, 1);
kinovaPostureTask_ = std::make_shared<mc_tasks::PostureTask>(solver(), 1, 1, 1);
solver().addTask(kinovaPostureTask_);
kinovaKinematics_ = std::make_unique<mc_solver::KinematicsConstraint>(robots(), 1, solver().dt());
solver().addConstraintSet(kinovaKinematics_);
robots().robot(1).posW(sva::PTransformd(sva::RotZ(0.0), Eigen::Vector3d(0.7, 0.5, 0)));
}
CONTROLLER_CONSTRUCTOR("DualArmController", DualArmController)
dual_arm_controller.py1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import mc_control
import mc_rbdyn
import math
import mc_tasks
import sva
import eigen
import mc_solver
class ControllerPhase:
IDLE = 0
STARTED = 1
MOVE = 2
class ControllerState:
GO = 0
RETURN = 1
class DualArmController(mc_control.MCPythonController):
def __init__(self, rm, dt):
self.qpsolver.addConstraintSet(self.contactConstraint)
self.qpsolver.addConstraintSet(self.kinematicsConstraint)
self.qpsolver.addConstraintSet(self.selfCollisionConstraint)
iDist, sDist, damping = 0.1, 0.05, 0.1
self.addCollisions(
"ur5e",
"kinova_default",
[mc_rbdyn.Collision("*", "*", iDist, sDist, damping)],
)
self.postureTask.stiffness(1)
self.postureTask.weight(1)
self.qpsolver.addTask(self.postureTask)
self._phase = ControllerPhase.IDLE
self._ur_state = ControllerState.RETURN
self._kinova_state = ControllerState.RETURN
self._urEndEffectorTask = None
self._kinovaPostureTask = None
self._kinovaKinematicsConstraint = None
def run_callback(self):
if self._phase == ControllerPhase.IDLE:
self.postureTask.target(
{
"elbow_joint".encode("utf-8"): [-math.pi / 2],
"wrist_2_joint".encode("utf-8"): [math.pi / 2],
}
)
self._phase = ControllerPhase.STARTED
elif (
self._phase == ControllerPhase.STARTED
and self.postureTask.eval().norm() < 0.01
and self.postureTask.speed().norm() < 0.01
):
self._phase = ControllerPhase.MOVE
self.qpsolver.addTask(self._urEndEffectorTask)
elif self._phase == ControllerPhase.STARTED:
self._urEndEffectorTask.reset()
elif self._phase == ControllerPhase.MOVE:
self._run_ur5e()
self._run_kinova()
return True
def reset_callback(self, data):
self._urEndEffectorTask = mc_tasks.EndEffectorTask("tool0", self.robots(), 0, 1)
self._kinovaPostureTask = mc_tasks.PostureTask(self.qpsolver, 1, 5.0, 1000.0)
self._kinovaKinematicsConstraint = mc_solver.KinematicsConstraint(
self.robots(), 1, self.qpsolver.timeStep
)
self.qpsolver.addTask(self._kinovaPostureTask)
self.qpsolver.addConstraintSet(self._kinovaKinematicsConstraint)
self.robots().robot(1).posW(
sva.PTransformd(sva.RotZ(0), eigen.Vector3d(0.7, 0.5, 0))
)
@staticmethod
def create(robot, dt):
kinova = mc_rbdyn.get_robot_module("KinovaDefault")
return DualArmController([robot, kinova], dt)
def _run_kinova(self):
if (
self._kinova_state == ControllerState.GO
and self._kinovaPostureTask.eval().norm() < 0.01
and self._kinovaPostureTask.speed().norm() < 0.01
):
self._kinova_state = ControllerState.RETURN
self._kinovaPostureTask.target(
{
"joint_2".encode("utf-8"): [0.0],
}
)
elif (
self._kinova_state == ControllerState.RETURN
and self._kinovaPostureTask.eval().norm() < 0.01
and self._kinovaPostureTask.speed().norm() < 0.01
):
self._kinova_state = ControllerState.GO
self._kinovaPostureTask.target(
{
"joint_2".encode("utf-8"): [-math.pi / 4],
}
)
def _run_ur5e(self):
if (
self._ur_state == ControllerState.GO
and self._urEndEffectorTask.positionTask.eval().norm() < 0.05
and self._urEndEffectorTask.positionTask.speed().norm() < 0.05
):
self._ur_state = ControllerState.RETURN
self._urEndEffectorTask.add_ef_pose(
sva.PTransformd(sva.RotZ(0), eigen.Vector3d(0.0, -0.5, 0.0))
)
elif (
self._ur_state == ControllerState.RETURN
and self._urEndEffectorTask.positionTask.eval().norm() < 0.05
and self._urEndEffectorTask.positionTask.speed().norm() < 0.05
):
self._ur_state = ControllerState.GO
self._urEndEffectorTask.add_ef_pose(
sva.PTransformd(sva.RotZ(0), eigen.Vector3d(0.0, 0.5, 0.0))
)
__init__.py1
from my_first_controller import MyFirstController