Skip to content

Commit 3310e1f

Browse files
authored
Merge pull request #219 from RobotControlStack/refactor/kinematics
refactor: inverse and forward kinematics interface
2 parents aa1e628 + a832b36 commit 3310e1f

43 files changed

Lines changed: 548 additions & 417 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,14 @@ find_package(MuJoCo REQUIRED)
3939
find_package(pinocchio REQUIRED)
4040

4141

42-
FetchContent_Declare(rl
43-
GIT_REPOSITORY https://github.com/roboticslibrary/rl.git
44-
GIT_TAG 0b3797215345a1d37903634095361233d190b2e6
45-
GIT_PROGRESS TRUE
46-
EXCLUDE_FROM_ALL
47-
)
4842
FetchContent_Declare(pybind11
4943
GIT_REPOSITORY https://github.com/pybind/pybind11.git
5044
GIT_TAG v2.13.4
5145
GIT_PROGRESS TRUE
5246
EXCLUDE_FROM_ALL
5347
)
5448

55-
FetchContent_MakeAvailable(rl pybind11)
49+
FetchContent_MakeAvailable(pybind11)
5650
include(compile_scenes)
5751

5852
add_subdirectory(src)

Makefile

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,8 @@ stubgen:
3535
find ./python/rcs/_core -name '*.pyi' -print | xargs sed -i 's/tuple\[typing\.Literal\[\([0-9]\+\)\], typing\.Literal\[1\]\]/tuple\[typing\.Literal[\1]\]/g'
3636
find ./python/rcs/_core -name '*.pyi' -print | xargs sed -i 's/tuple\[\([M|N]\), typing\.Literal\[1\]\]/tuple\[\1\]/g'
3737
ruff check --fix python/rcs/_core
38-
pybind11-stubgen -o extensions --numpy-array-use-type-var rcs_fr3
39-
find ./extensions/rcs_fr3 -not -path "./extensions/rcs_fr3/_core/*" -name '*.pyi' -delete
40-
find ./extensions/rcs_fr3 -name '*.pyi' -print | xargs sed -i '1s/^/# ATTENTION: auto generated from C++ code, use `make stubgen` to update!\n/'
41-
find ./extensions/rcs_fr3 -name '*.pyi' -print | xargs sed -i 's/tuple\[typing\.Literal\[\([0-9]\+\)\], typing\.Literal\[1\]\]/tuple\[typing\.Literal[\1]\]/g'
42-
find ./extensions/rcs_fr3 -name '*.pyi' -print | xargs sed -i 's/tuple\[\([M|N]\), typing\.Literal\[1\]\]/tuple\[\1\]/g'
43-
rm -r extensions/rcs_fr3/src/rcs_fr3/_core
44-
mv extensions/rcs_fr3/_core/ extensions/rcs_fr3/src/rcs_fr3/
45-
ruff check --fix extensions/rcs_fr3/src/rcs_fr3/_core
46-
isort python/rcs/_core extensions/rcs_fr3/src/rcs_fr3/_core
47-
black python/rcs/_core extensions/rcs_fr3/src/rcs_fr3/_core
38+
isort python/rcs/_core
39+
black python/rcs/_core
4840

4941
# Python
5042
pycheckformat:

examples/fr3/fr3_direct_control.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ def main():
6060
gripper: rcs.common.Gripper
6161
if ROBOT_INSTANCE == RobotPlatform.SIMULATION:
6262
simulation = sim.Sim(rcs.scenes["fr3_empty_world"].mjb)
63-
urdf_path = rcs.scenes["fr3_empty_world"].urdf
64-
ik = rcs.common.RL(str(urdf_path))
63+
mjcf_path = rcs.scenes["fr3_empty_world"].mjcf_robot
64+
ik = rcs.common.Pin(
65+
mjcf_path,
66+
"attachment_site_0",
67+
)
6568
cfg = sim.SimRobotConfig()
6669
cfg.add_id("0")
6770
cfg.tcp_offset = rcs.common.Pose(rcs.common.FrankaHandTCPOffset())
@@ -92,8 +95,11 @@ def main():
9295
simulation.open_gui()
9396

9497
else:
95-
urdf_path = rcs.scenes["fr3_empty_world"].urdf
96-
ik = rcs.common.RL(str(urdf_path))
98+
mjcf_path = rcs.scenes["fr3_empty_world"].mjcf_robot
99+
ik = rcs.common.Pin(
100+
mjcf_path,
101+
"attachment_site_0",
102+
)
97103
robot = hw.FR3(ROBOT_IP, ik)
98104
robot_cfg = hw.FR3Config()
99105
robot_cfg.tcp_offset = rcs.common.Pose(rcs.common.FrankaHandTCPOffset())

extensions/rcs_fr3/src/hw/FR3.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
namespace rcs {
2121
namespace hw {
22-
FR3::FR3(const std::string &ip, std::optional<std::shared_ptr<common::IK>> ik,
22+
FR3::FR3(const std::string &ip,
23+
std::optional<std::shared_ptr<common::Kinematics>> ik,
2324
const std::optional<FR3Config> &cfg)
2425
: robot(ip), m_ik(ik) {
2526
// set collision behavior and impedance
@@ -650,7 +651,9 @@ double quintic_polynomial_speed_profile(double time, double start_time,
650651
// return (1 - std::cos(M_PI * progress)) / 2.0;
651652
}
652653

653-
std::optional<std::shared_ptr<common::IK>> FR3::get_ik() { return this->m_ik; }
654+
std::optional<std::shared_ptr<common::Kinematics>> FR3::get_ik() {
655+
return this->m_ik;
656+
}
654657

655658
void FR3::set_cartesian_position(const common::Pose &x) {
656659
// pose is assumed to be in the robots coordinate frame
@@ -686,8 +689,8 @@ void FR3::set_cartesian_position_ik(const common::Pose &pose) {
686689
"No inverse kinematics was provided. Cannot use IK to set cartesian "
687690
"position.");
688691
}
689-
auto joints = this->m_ik.value()->ik(pose, this->get_joint_position(),
690-
this->cfg.tcp_offset);
692+
auto joints = this->m_ik.value()->inverse(pose, this->get_joint_position(),
693+
this->cfg.tcp_offset);
691694

692695
if (joints.has_value()) {
693696
this->set_joint_position(joints.value());

extensions/rcs_fr3/src/hw/FR3.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <string>
1111
#include <thread>
1212

13-
#include "rcs/IK.h"
13+
#include "rcs/Kinematics.h"
1414
#include "rcs/LinearPoseTrajInterpolator.h"
1515
#include "rcs/Pose.h"
1616
#include "rcs/Robot.h"
@@ -34,6 +34,8 @@ struct FR3Config : common::RobotConfig {
3434
// TODO: max force and elbow?
3535
// TODO: we can either write specific bindings for each, or we use python
3636
// dictionaries with these objects
37+
common::RobotType robot_type = common::RobotType::FR3;
38+
common::RobotPlatform robot_platform = common::RobotPlatform::HARDWARE;
3739
IKSolver ik_solver = IKSolver::franka_ik;
3840
double speed_factor = DEFAULT_SPEED_FACTOR;
3941
std::optional<FR3Load> load_parameters = std::nullopt;
@@ -48,7 +50,7 @@ class FR3 : public common::Robot {
4850
private:
4951
franka::Robot robot;
5052
FR3Config cfg;
51-
std::optional<std::shared_ptr<common::IK>> m_ik;
53+
std::optional<std::shared_ptr<common::Kinematics>> m_ik;
5254
std::optional<std::thread> control_thread = std::nullopt;
5355
common::LinearPoseTrajInterpolator traj_interpolator;
5456
double controller_time = 0.0;
@@ -62,7 +64,7 @@ class FR3 : public common::Robot {
6264

6365
public:
6466
FR3(const std::string &ip,
65-
std::optional<std::shared_ptr<common::IK>> ik = std::nullopt,
67+
std::optional<std::shared_ptr<common::Kinematics>> ik = std::nullopt,
6668
const std::optional<FR3Config> &cfg = std::nullopt);
6769
~FR3() override;
6870

@@ -100,7 +102,7 @@ class FR3 : public common::Robot {
100102

101103
void set_cartesian_position(const common::Pose &pose) override;
102104

103-
std::optional<std::shared_ptr<common::IK>> get_ik() override;
105+
std::optional<std::shared_ptr<common::Kinematics>> get_ik() override;
104106

105107
void set_cartesian_position_internal(const common::Pose &pose,
106108
double max_time,

extensions/rcs_fr3/src/hw/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <franka/exception.h>
22
#include <franka/gripper.h>
33
#include <franka/robot.h>
4-
#include <rcs/IK.h>
4+
#include <rcs/Kinematics.h>
55

66
#include <iostream>
77
#include <memory>

extensions/rcs_fr3/src/pybind/rcs.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
#include <memory>
1111

12-
#include "rcs/IK.h"
12+
#include "rcs/Kinematics.h"
1313
#include "rcs/Pose.h"
1414
#include "rcs/Robot.h"
1515
#include "rcs/utils.h"
@@ -99,7 +99,7 @@ PYBIND11_MODULE(_core, m) {
9999
(py::object)py::module_::import("rcs").attr("common").attr("Robot");
100100
py::class_<rcs::hw::FR3, std::shared_ptr<rcs::hw::FR3>>(hw, "FR3", robot)
101101
.def(py::init<const std::string &,
102-
std::optional<std::shared_ptr<rcs::common::IK>>>(),
102+
std::optional<std::shared_ptr<rcs::common::Kinematics>>>(),
103103
py::arg("ip"), py::arg("ik") = std::nullopt)
104104
.def("set_config", &rcs::hw::FR3::set_config, py::arg("cfg"))
105105
.def("get_config", &rcs::hw::FR3::get_config)

extensions/rcs_fr3/src/rcs_fr3/_core/hw/__init__.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class FHState(rcs._core.common.GripperState):
5252
def width(self) -> float: ...
5353

5454
class FR3(rcs._core.common.Robot):
55-
def __init__(self, ip: str, ik: rcs._core.common.IK | None = None) -> None: ...
55+
def __init__(self, ip: str, ik: rcs._core.common.Kinematics | None = None) -> None: ...
5656
def automatic_error_recovery(self) -> None: ...
5757
def controller_set_joint_position(
5858
self, desired_q: numpy.ndarray[tuple[typing.Literal[7]], numpy.dtype[numpy.float64]]

extensions/rcs_fr3/src/rcs_fr3/creators.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def __call__( # type: ignore
3838
camera_set: HardwareCameraSet | None = None,
3939
max_relative_movement: float | tuple[float, float] | None = None,
4040
relative_to: RelativeTo = RelativeTo.LAST_STEP,
41-
urdf_path: str | PathLike | None = None,
4241
) -> gym.Env:
4342
"""
4443
Creates a hardware environment for the FR3 robot.
@@ -55,14 +54,16 @@ def __call__( # type: ignore
5554
translational movement in meters. If tuple, it restricts both translational (in meters) and rotational
5655
(in radians) movements. If None, no restriction is applied.
5756
relative_to (RelativeTo): Specifies whether the movement is relative to a configured origin or the last step.
58-
urdf_path (str | PathLike | None): Path to the URDF file. If None the included one is used. A URDF file is needed for collision guarding.
5957
6058
Returns:
6159
gym.Env: The configured hardware environment for the FR3 robot.
6260
"""
63-
if urdf_path is None:
64-
urdf_path = rcs.scenes["fr3_empty_world"].urdf
65-
ik = rcs.common.RL(str(urdf_path)) if urdf_path is not None else None
61+
ik = rcs.common.Pin(
62+
robot_cfg.kinematic_model_path,
63+
robot_cfg.attachment_site,
64+
urdf=robot_cfg.kinematic_model_path.endswith(".urdf"),
65+
)
66+
# ik = rcs_robotics_library._core.rl.RoboticsLibraryIK(robot_cfg.kinematic_model_path)
6667
robot = hw.FR3(ip, ik)
6768
robot.set_config(robot_cfg)
6869

@@ -111,11 +112,15 @@ def __call__( # type: ignore
111112
camera_set: HardwareCameraSet | None = None,
112113
max_relative_movement: float | tuple[float, float] | None = None,
113114
relative_to: RelativeTo = RelativeTo.LAST_STEP,
114-
urdf_path: str | PathLike | None = None,
115115
) -> gym.Env:
116116

117-
urdf_path = rcs.scenes["fr3_empty_world"].urdf
118-
ik = rcs.common.RL(str(urdf_path)) if urdf_path is not None else None
117+
ik = rcs.common.Pin(
118+
robot_cfg.kinematic_model_path,
119+
robot_cfg.attachment_site,
120+
urdf=robot_cfg.kinematic_model_path.endswith(".urdf"),
121+
)
122+
# ik = rcs_robotics_library._core.rl.RoboticsLibraryIK(robot_cfg.kinematic_model_path)
123+
119124
robots: dict[str, hw.FR3] = {}
120125
for ip in ips:
121126
robots[ip] = hw.FR3(ip, ik)

extensions/rcs_fr3/src/rcs_fr3/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
from rcs_fr3._core import hw
22

3+
import rcs
34
from rcs import common
45

56

67
def default_fr3_hw_robot_cfg(async_control: bool = False) -> hw.FR3Config:
78
robot_cfg = hw.FR3Config()
9+
robot_cfg.robot_type = rcs.scenes["fr3_empty_world"].robot_type
10+
robot_cfg.kinematic_model_path = rcs.scenes["fr3_empty_world"].mjcf_robot
811
robot_cfg.tcp_offset = common.Pose(common.FrankaHandTCPOffset())
12+
robot_cfg.attachment_site = "attachment_site_0"
913
robot_cfg.speed_factor = 0.1
1014
robot_cfg.ik_solver = hw.IKSolver.rcs_ik
1115
robot_cfg.async_control = async_control

0 commit comments

Comments
 (0)