Skip to content

Commit bf74c23

Browse files
authored
Merge pull request #119 from utn-mi/walter/fix-vive-pose
fix: pose calculation and control for vive teleoperation
2 parents 6efbc39 + 20b73e1 commit bf74c23

7 files changed

Lines changed: 63 additions & 49 deletions

File tree

python/rcsss/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
import pathlib
44
import site
55

6-
from rcsss import camera, desk, sim
6+
from rcsss import camera, control, sim
77
from rcsss._core import __version__, common, hw
88

99
scenes = {
1010
path.stem: path / "scene.mjb" for path in (pathlib.Path(site.getsitepackages()[0]) / "rcsss" / "scenes").glob("*")
1111
}
1212

13-
__all__ = ["__doc__", "__version__", "common", "hw", "sim", "desk", "camera", "scenes"]
13+
__all__ = ["__doc__", "__version__", "common", "hw", "sim", "camera", "scenes", "control"]

python/rcsss/cli/main.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import pyrealsense2 as rs
88
import rcsss
9+
import rcsss.control.fr3_desk
910
import typer
1011
from PIL import Image
1112
from rcsss.camera.realsense import RealSenseCameraSet
@@ -113,7 +114,7 @@ def home(
113114
):
114115
"""Moves the FR3 to home position"""
115116
cfg = read_config_yaml(path)
116-
rcsss.desk.home(ip, cfg.hw.username, cfg.hw.password, shut)
117+
rcsss.control.fr3_desk.home(ip, cfg.hw.username, cfg.hw.password, shut)
117118

118119

119120
@fr3_app.command()
@@ -123,7 +124,7 @@ def lock(
123124
):
124125
"""Locks the robot."""
125126
cfg = read_config_yaml(path)
126-
rcsss.desk.lock(ip, cfg.hw.username, cfg.hw.password)
127+
rcsss.control.fr3_desk.lock(ip, cfg.hw.username, cfg.hw.password)
127128

128129

129130
@fr3_app.command()
@@ -133,8 +134,8 @@ def unlock(
133134
):
134135
"""Prepares the robot by unlocking the joints and putting the robot into the FCI mode."""
135136
cfg = read_config_yaml(path)
136-
rcsss.desk.unlock(ip, cfg.hw.username, cfg.hw.password)
137-
with rcsss.desk.Desk(ip, cfg.hw.username, cfg.hw.password) as d:
137+
rcsss.control.fr3_desk.unlock(ip, cfg.hw.username, cfg.hw.password)
138+
with rcsss.control.fr3_desk.Desk(ip, cfg.hw.username, cfg.hw.password) as d:
138139
d.activate_fci()
139140

140141

@@ -148,12 +149,14 @@ def fci(
148149
"""Puts the robot into FCI mode, optionally unlocks the robot. Waits for ctrl+c to exit."""
149150
cfg = read_config_yaml(path)
150151
try:
151-
with rcsss.desk.FCI(rcsss.desk.Desk(ip, cfg.hw.username, cfg.hw.password), unlock=unlock):
152+
with rcsss.control.fr3_desk.FCI(
153+
rcsss.control.fr3_desk.Desk(ip, cfg.hw.username, cfg.hw.password), unlock=unlock
154+
):
152155
while True:
153156
sleep(1)
154157
except KeyboardInterrupt:
155158
if shutdown:
156-
rcsss.desk.shutdown(ip, cfg.hw.username, cfg.hw.password)
159+
rcsss.control.fr3_desk.shutdown(ip, cfg.hw.username, cfg.hw.password)
157160

158161

159162
@fr3_app.command()
@@ -164,7 +167,7 @@ def guiding_mode(
164167
):
165168
"""Enables or disables guiding mode."""
166169
cfg = read_config_yaml(path)
167-
rcsss.desk.guiding_mode(ip, cfg.hw.username, cfg.hw.password, disable)
170+
rcsss.control.fr3_desk.guiding_mode(ip, cfg.hw.username, cfg.hw.password, disable)
168171

169172

170173
@fr3_app.command()
@@ -174,7 +177,7 @@ def shutdown(
174177
):
175178
"""Shuts the robot down"""
176179
cfg = read_config_yaml(path)
177-
rcsss.desk.shutdown(ip, cfg.hw.username, cfg.hw.password)
180+
rcsss.control.fr3_desk.shutdown(ip, cfg.hw.username, cfg.hw.password)
178181

179182

180183
@fr3_app.command()
@@ -194,7 +197,9 @@ def record(
194197
with ExitStack() as stack:
195198
for r_ip in name2ip.values():
196199
stack.enter_context(
197-
rcsss.desk.Desk.fci(r_ip, username=cfg.hw.username, password=cfg.hw.password, unlock=True)
200+
rcsss.control.fr3_desk.Desk.fci(
201+
r_ip, username=cfg.hw.username, password=cfg.hw.password, unlock=True
202+
)
198203
)
199204

200205
p = PoseList.load(name2ip, lpaths, cfg.hw.urdf_model_path)
@@ -203,7 +208,9 @@ def record(
203208
else:
204209
with ExitStack() as stack:
205210
gms = [
206-
rcsss.desk.Desk.guiding_mode(r_ip, username=cfg.hw.username, password=cfg.hw.password, unlock=True)
211+
rcsss.control.fr3_desk.Desk.guiding_mode(
212+
r_ip, username=cfg.hw.username, password=cfg.hw.password, unlock=True
213+
)
207214
for r_ip in name2ip.values()
208215
]
209216
for gm in gms:

python/rcsss/control/liveplot.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
port = 54322
1212
FMT = "!" + 7 * "d" + "i"
1313

14-
buffsize = 30
15-
# buffsize = 300
14+
# buffsize = 30
15+
buffsize = 300
1616
# Order of buffers: x, y, z, rx, ry, rz
1717

1818
titles = [["x", "rx"], ["y", "ry"], ["z", "rz"]]
@@ -64,4 +64,4 @@
6464

6565
plt.draw()
6666
plt.pause(0.001)
67-
plt.pause(0.5)
67+
# plt.pause(0.5)

python/rcsss/control/vive.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import threading
33
from enum import IntFlag, auto
44
from socket import AF_INET, SOCK_DGRAM, socket
5-
from struct import unpack # , pack
5+
from struct import pack, unpack
66

77
import gymnasium as gym
88
import numpy as np
@@ -34,8 +34,8 @@
3434
EGO_LOCK = False
3535
VIVE_HOST = "192.168.100.1"
3636
VIVE_PORT = 54321
37-
USE_REAL_ROBOT = False
38-
INCLUDE_ROTATION = False
37+
USE_REAL_ROBOT = True
38+
INCLUDE_ROTATION = True
3939
ROBOT_IP = "192.168.101.1"
4040

4141

@@ -77,7 +77,7 @@ def __init__(
7777
def next_action(self) -> Pose:
7878
transform = Pose(
7979
translation=self._last_controller_pose.translation() - self._offset_pose.translation(),
80-
quaternion=(self._offset_pose.inverse() * self._last_controller_pose).rotation_q(),
80+
quaternion=(self._last_controller_pose * self._offset_pose.inverse()).rotation_q(),
8181
)
8282
return (
8383
self._ego_transform
@@ -93,11 +93,11 @@ def get_last_controller_pose(self) -> Pose:
9393
def run(self):
9494
warning_raised = False
9595

96-
with socket(AF_INET, SOCK_DGRAM) as sock:
97-
# with socket(AF_INET, SOCK_DGRAM) as send_sock:
96+
with socket(AF_INET, SOCK_DGRAM) as sock, socket(AF_INET, SOCK_DGRAM) as send_sock:
9897
sock.settimeout(2)
98+
sock.setblocking(False)
9999
sock.bind((self._host, self._port))
100-
# send_sock.connect(("127.0.0.1", self._port + 1))
100+
send_sock.connect(("127.0.0.1", self._port + 1))
101101
while not self._exit_requested:
102102
try:
103103
unpacked = unpack(UDPViveActionServer.FMT, sock.recv(7 * 8 + 4))
@@ -155,18 +155,18 @@ def run(self):
155155
self._last_controller_pose = last_controller_pose
156156

157157
# plot current offset with liveplot.py
158-
# transform = Pose(
159-
# translation=self._last_controller_pose.translation() - self._offset_pose.translation(),
160-
# quaternion=(self._offset_pose.inverse() * self._last_controller_pose).rotation_q(),
161-
# )
162-
# offset = (
163-
# self._ego_transform
164-
# * UDPViveActionServer.transform_from_openxr
165-
# * transform
166-
# * UDPViveActionServer.transform_from_openxr.inverse()
167-
# * self._ego_transform.inverse()
168-
# )
169-
# send_sock.sendall(pack(UDPViveActionServer.FMT, *offset.rotation_q(), *offset.translation(), 0))
158+
transform = Pose(
159+
translation=self._last_controller_pose.translation() - self._offset_pose.translation(),
160+
quaternion=(self._last_controller_pose * self._offset_pose.inverse()).rotation_q(),
161+
)
162+
offset = (
163+
self._ego_transform
164+
* UDPViveActionServer.transform_from_openxr
165+
* transform
166+
* UDPViveActionServer.transform_from_openxr.inverse()
167+
* self._ego_transform.inverse()
168+
)
169+
send_sock.sendall(pack(UDPViveActionServer.FMT, *offset.rotation_q(), *offset.translation(), 0))
170170

171171
if Button(int(unpacked[7])) & self._grp_btn and not Button(int(self._buttons)) & self._grp_btn:
172172
# just pressed
@@ -210,7 +210,7 @@ def hw():
210210
rcfg = rcsss.hw.FR3Config()
211211
rcfg.tcp_offset = rcsss.common.Pose(rcsss.common.FrankaHandTCPOffset())
212212
rcfg.speed_factor = 0.2
213-
# rcfg.controller = rcsss.hw.IKController.robotics_library
213+
rcfg.controller = rcsss.hw.IKController.robotics_library
214214
robot.set_parameters(rcfg)
215215

216216
# env = FR3Env(robot, ControlMode.CARTESIAN_TQuart)

python/rcsss/envs/base.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,21 @@ def step(self, action: CartOrJointContType) -> tuple[ArmObsType, float, bool, bo
213213
raise RuntimeError(msg)
214214

215215
if self.get_base_control_mode() == ControlMode.JOINTS and (
216-
self.prev_action is None or not np.allclose(action_dict[self.joints_key], self.prev_action[self.joints_key])
216+
self.prev_action is None
217+
or not np.allclose(action_dict[self.joints_key], self.prev_action[self.joints_key], atol=1e-03, rtol=0)
217218
):
218219
# cast is needed because typed dicts cannot be checked at runtime
219220
self.robot.set_joint_position(action_dict[self.joints_key])
220221
elif self.get_base_control_mode() == ControlMode.CARTESIAN_TRPY and (
221-
self.prev_action is None or not np.allclose(action_dict[self.trpy_key], self.prev_action[self.trpy_key])
222+
self.prev_action is None
223+
or not np.allclose(action_dict[self.trpy_key], self.prev_action[self.trpy_key], atol=1e-03, rtol=0)
222224
):
223225
self.robot.set_cartesian_position(
224226
common.Pose(translation=action_dict[self.trpy_key][:3], rpy_vector=action_dict[self.trpy_key][3:])
225227
)
226228
elif self.get_base_control_mode() == ControlMode.CARTESIAN_TQuart and (
227-
self.prev_action is None or not np.allclose(action_dict[self.tquart_key], self.prev_action[self.tquart_key])
229+
self.prev_action is None
230+
or not np.allclose(action_dict[self.tquart_key], self.prev_action[self.tquart_key], atol=1e-03, rtol=0)
228231
):
229232
self.robot.set_cartesian_position(
230233
common.Pose(translation=action_dict[self.tquart_key][:3], quaternion=action_dict[self.tquart_key][3:])

src/hw/FR3.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,13 @@ FR3::FR3(const std::string &ip, const std::optional<std::string> &filename,
3939
if (filename.has_value()) {
4040
this->rl = RL();
4141

42-
this->rl.value().mdl = rl::mdl::UrdfFactory().create(filename.value());
43-
this->rl.value().kin =
44-
std::dynamic_pointer_cast<rl::mdl::Kinematic>(this->rl.value().mdl);
45-
this->rl.value().ik = std::make_shared<rl::mdl::JacobianInverseKinematics>(
46-
this->rl.value().kin.get());
42+
this->rl->mdl = rl::mdl::UrdfFactory().create(filename.value());
43+
this->rl->kin =
44+
std::dynamic_pointer_cast<rl::mdl::Kinematic>(this->rl->mdl);
45+
this->rl->ik = std::make_shared<rl::mdl::JacobianInverseKinematics>(
46+
this->rl->kin.get());
47+
this->rl->ik->setRandomRestarts(0);
48+
this->rl->ik->setEpsilon(1e-3);
4749
}
4850
}
4951

@@ -218,17 +220,17 @@ void FR3::set_cartesian_position_rl(const common::Pose &pose) {
218220
throw rl::mdl::Exception(
219221
"No file for robot model was provided. Cannot use RL for IK.");
220222
}
221-
this->rl.value().kin->setPosition(this->get_joint_position());
222-
this->rl.value().kin->forwardPosition();
223+
this->rl->kin->setPosition(this->get_joint_position());
224+
this->rl->kin->forwardPosition();
223225
rcs::common::Pose new_pose = pose * this->cfg.tcp_offset.inverse();
224226

225-
this->rl.value().ik->addGoal(new_pose.affine_matrix(), 0);
226-
bool success = this->rl.value().ik->solve();
227+
this->rl->ik->addGoal(new_pose.affine_matrix(), 0);
228+
bool success = this->rl->ik->solve();
227229
if (success) {
228230
// is this forward needed and is it mabye possible to call
229231
// this on the model?
230-
this->rl.value().kin->forwardPosition();
231-
this->set_joint_position(this->rl.value().kin->getPosition());
232+
this->rl->kin->forwardPosition();
233+
this->set_joint_position(this->rl->kin->getPosition());
232234
} else {
233235
// throw error
234236
throw rl::mdl::Exception("IK failed");

src/sim/FR3.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ void FR3::construct() {
6464
std::make_shared<rl::mdl::JacobianInverseKinematics>(this->rl.kin.get());
6565
this->rl.ik->setDuration(
6666
std::chrono::milliseconds(this->cfg.ik_duration_in_milliseconds));
67+
this->rl.ik->setRandomRestarts(0);
68+
this->rl.ik->setEpsilon(1e-3);
6769
this->init_ids();
6870
this->sim->register_cb(std::bind(&FR3::collision_callback, this),
6971
this->cfg.seconds_between_callbacks);

0 commit comments

Comments
 (0)