Skip to content

Commit d61db2a

Browse files
committed
feat: added desk and cli tool to panda
- added desk to panda - added cli tool to panda - refactored name of credential loading function: load_creds_fr3_desk to load_creds_franka_desk
1 parent dde15e8 commit d61db2a

5 files changed

Lines changed: 701 additions & 18 deletions

File tree

‎examples/fr3/fr3_direct_control.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from rcs._core.sim import CameraType
66
from rcs.camera.sim import SimCameraConfig, SimCameraSet
77
from rcs_fr3._core import hw
8-
from rcs_fr3.desk import FCI, ContextManager, Desk, load_creds_fr3_desk
8+
from rcs_fr3.desk import FCI, ContextManager, Desk, load_creds_franka_desk
99

1010
import rcs
1111
from rcs import sim
@@ -26,8 +26,8 @@
2626
2727
2828
Create a .env file in the same directory as this file with the following content:
29-
FR3_USERNAME=<username on franka desk>
30-
FR3_PASSWORD=<password on franka desk>
29+
DESK_USERNAME=<username on franka desk>
30+
DESK_PASSWORD=<password on franka desk>
3131
3232
When you use a real FR3 you first need to unlock its joints using the following cli script:
3333
@@ -50,7 +50,7 @@
5050
def main():
5151
context_manger: FCI | ContextManager
5252
if ROBOT_INSTANCE == RobotPlatform.HARDWARE:
53-
user, pw = load_creds_fr3_desk()
53+
user, pw = load_creds_franka_desk()
5454
context_manger = FCI(Desk(ROBOT_IP, user, pw), unlock=False, lock_when_done=False)
5555
else:
5656
context_manger = ContextManager()
@@ -100,7 +100,7 @@ def main():
100100
mjcf_path,
101101
"attachment_site_0",
102102
)
103-
robot = hw.FR3(ROBOT_IP, ik)
103+
robot = hw.Franka(ROBOT_IP, ik)
104104
robot_cfg = hw.FR3Config()
105105
robot_cfg.tcp_offset = rcs.common.Pose(rcs.common.FrankaHandTCPOffset())
106106
robot_cfg.ik_solver = hw.IKSolver.rcs_ik

‎extensions/rcs_fr3/src/rcs_fr3/__main__.py‎

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

55
import rcs_fr3
66
import typer
7-
from rcs_fr3.desk import load_creds_fr3_desk
7+
from rcs_fr3.desk import load_creds_franka_desk
88

99
logger = logging.getLogger(__name__)
1010

@@ -25,7 +25,7 @@ def home(
2525
unlock: Annotated[bool, typer.Option("-u", help="unlocks the robot")] = False,
2626
):
2727
"""Moves the FR3 to home position"""
28-
user, pw = load_creds_fr3_desk()
28+
user, pw = load_creds_franka_desk()
2929
rcs_fr3.desk.home(ip, user, pw, shut, unlock)
3030

3131

@@ -35,7 +35,7 @@ def info(
3535
include_gripper: Annotated[bool, typer.Option("-g", help="includes gripper")] = False,
3636
):
3737
"""Prints info about the robots current joint position and end effector pose, optionally also the gripper."""
38-
user, pw = load_creds_fr3_desk()
38+
user, pw = load_creds_franka_desk()
3939
rcs_fr3.desk.info(ip, user, pw, include_gripper)
4040

4141

@@ -44,7 +44,7 @@ def lock(
4444
ip: Annotated[str, typer.Argument(help="IP of the robot")],
4545
):
4646
"""Locks the robot."""
47-
user, pw = load_creds_fr3_desk()
47+
user, pw = load_creds_franka_desk()
4848
rcs_fr3.desk.lock(ip, user, pw)
4949

5050

@@ -53,7 +53,7 @@ def unlock(
5353
ip: Annotated[str, typer.Argument(help="IP of the robot")],
5454
):
5555
"""Prepares the robot by unlocking the joints and putting the robot into the FCI mode."""
56-
user, pw = load_creds_fr3_desk()
56+
user, pw = load_creds_franka_desk()
5757
rcs_fr3.desk.unlock(ip, user, pw)
5858
with rcs_fr3.desk.Desk(ip, user, pw) as d:
5959
d.activate_fci()
@@ -66,7 +66,7 @@ def fci(
6666
shutdown: Annotated[bool, typer.Option("-s", help="After ctrl+c shuts the robot down")] = False,
6767
):
6868
"""Puts the robot into FCI mode, optionally unlocks the robot. Waits for ctrl+c to exit."""
69-
user, pw = load_creds_fr3_desk()
69+
user, pw = load_creds_franka_desk()
7070
try:
7171
with rcs_fr3.desk.FCI(rcs_fr3.desk.Desk(ip, user, pw), unlock=unlock, lock_when_done=False):
7272
while True:
@@ -83,7 +83,7 @@ def guiding_mode(
8383
unlock: Annotated[bool, typer.Option("-u", help="unlocks the robot")] = False,
8484
):
8585
"""Enables or disables guiding mode."""
86-
user, pw = load_creds_fr3_desk()
86+
user, pw = load_creds_franka_desk()
8787
rcs_fr3.desk.guiding_mode(ip, user, pw, disable, unlock)
8888

8989

@@ -92,7 +92,7 @@ def shutdown(
9292
ip: Annotated[str, typer.Argument(help="IP of the robot")],
9393
):
9494
"""Shuts the robot down"""
95-
user, pw = load_creds_fr3_desk()
95+
user, pw = load_creds_franka_desk()
9696
rcs_fr3.desk.shutdown(ip, user, pw)
9797

9898

‎extensions/rcs_fr3/src/rcs_fr3/desk.py‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,28 @@
2828
"""
2929

3030

31-
def load_creds_fr3_desk() -> tuple[str, str]:
31+
def load_creds_franka_desk(postfix: str = "") -> tuple[str, str]:
32+
"""Loads the FR3 Desk credentials from a .env file.
33+
34+
The keys in the .env file are expected to be DESK_USERNAME and DESK_PASSWORD.
35+
36+
If you have multiple robots with multiple credentials, you can specify a postfix
37+
which is appended to the keys, e.g. for postfix "1" the keys would be DESK_USERNAME_1 and DESK_PASSWORD_1.
38+
"""
3239
load_dotenv()
33-
assert "DESK_USERNAME" in os.environ, "DESK_USERNAME not set in .env file or environment var."
34-
assert "DESK_PASSWORD" in os.environ, "DESK_PASSWORD not set in .env file or environment var."
35-
return os.environ["DESK_USERNAME"], os.environ["DESK_PASSWORD"]
40+
username_key = f"DESK_USERNAME_{postfix}" if postfix else "DESK_USERNAME"
41+
password_key = f"DESK_PASSWORD_{postfix}" if postfix else "DESK_PASSWORD"
42+
43+
assert username_key in os.environ, f"{username_key} not set in .env file or environment var."
44+
assert password_key in os.environ, f"{password_key} not set in .env file or environment var."
45+
return os.environ[username_key], os.environ[password_key]
3646

3747

3848
def home(ip: str, username: str, password: str, shut: bool, unlock: bool = False):
3949
with Desk.fci(ip, username, password, unlock=unlock):
4050
f = rcs_fr3.hw.Franka(ip)
4151
config = rcs_fr3.hw.FR3Config()
4252
config.speed_factor = 0.2
43-
config.ik_solver = rcs_fr3.hw.IKSolver.franka_ik
4453
f.set_config(config)
4554
config_hand = rcs_fr3.hw.FHConfig()
4655
g = rcs_fr3.hw.FrankaHand(ip, config_hand)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import logging
2+
from time import sleep
3+
from typing import Annotated
4+
5+
import rcs_panda
6+
import typer
7+
from rcs_panda.desk import load_creds_franka_desk
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
# panda CLI
13+
panda_app = typer.Typer(
14+
help=(
15+
"Commands to control a Franka Panda in RCS. "
16+
"This includes tools that you would usually do with Franka's Desk interface."
17+
),
18+
)
19+
20+
21+
@panda_app.command()
22+
def home(
23+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
24+
shut: Annotated[bool, typer.Option("-s", help="Should the robot be shut down")] = False,
25+
unlock: Annotated[bool, typer.Option("-u", help="unlocks the robot")] = False,
26+
):
27+
"""Moves the panda to home position"""
28+
user, pw = load_creds_franka_desk()
29+
rcs_panda.desk.home(ip, user, pw, shut, unlock)
30+
31+
32+
@panda_app.command()
33+
def info(
34+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
35+
include_gripper: Annotated[bool, typer.Option("-g", help="includes gripper")] = False,
36+
):
37+
"""Prints info about the robots current joint position and end effector pose, optionally also the gripper."""
38+
user, pw = load_creds_franka_desk()
39+
rcs_panda.desk.info(ip, user, pw, include_gripper)
40+
41+
42+
@panda_app.command()
43+
def lock(
44+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
45+
):
46+
"""Locks the robot."""
47+
user, pw = load_creds_franka_desk()
48+
rcs_panda.desk.lock(ip, user, pw)
49+
50+
51+
@panda_app.command()
52+
def unlock(
53+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
54+
):
55+
"""Prepares the robot by unlocking the joints and putting the robot into the FCI mode."""
56+
user, pw = load_creds_franka_desk()
57+
rcs_panda.desk.unlock(ip, user, pw)
58+
with rcs_panda.desk.Desk(ip, user, pw) as d:
59+
d.activate_fci()
60+
61+
62+
@panda_app.command()
63+
def fci(
64+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
65+
unlock: Annotated[bool, typer.Option("-u", help="unlocks the robot")] = False,
66+
shutdown: Annotated[bool, typer.Option("-s", help="After ctrl+c shuts the robot down")] = False,
67+
):
68+
"""Puts the robot into FCI mode, optionally unlocks the robot. Waits for ctrl+c to exit."""
69+
user, pw = load_creds_franka_desk()
70+
try:
71+
with rcs_panda.desk.FCI(rcs_panda.desk.Desk(ip, user, pw), unlock=unlock, lock_when_done=False):
72+
while True:
73+
sleep(1)
74+
except KeyboardInterrupt:
75+
if shutdown:
76+
rcs_panda.desk.shutdown(ip, user, pw)
77+
78+
79+
@panda_app.command()
80+
def guiding_mode(
81+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
82+
disable: Annotated[bool, typer.Option("-d", help="Disable guiding mode")] = False,
83+
unlock: Annotated[bool, typer.Option("-u", help="unlocks the robot")] = False,
84+
):
85+
"""Enables or disables guiding mode."""
86+
user, pw = load_creds_franka_desk()
87+
rcs_panda.desk.guiding_mode(ip, user, pw, disable, unlock)
88+
89+
90+
@panda_app.command()
91+
def shutdown(
92+
ip: Annotated[str, typer.Argument(help="IP of the robot")],
93+
):
94+
"""Shuts the robot down"""
95+
user, pw = load_creds_franka_desk()
96+
rcs_panda.desk.shutdown(ip, user, pw)
97+
98+
99+
if __name__ == "__main__":
100+
panda_app()

0 commit comments

Comments
 (0)