In this tutorial, we will learn how to set up a Gym-compatible environment interface to control the Franka Emika Panda robot. This can be changed for multiple robots/different robots/more objects and sensors as well.
In this example we assume you are running a simulation that has the same set up seen below:
Add a file called franka_env.py
in the scripts folder.
This file defines a custom environment FrankaEnv
that integrates with the Ark=robotics framework. It is designed to control and observe a Franka Emika Panda robot interacting with a ball object, either in simulation or the real world.
from ark.env.ark_env import ArkEnv
from arktypes import joint_group_command_t, joint_state_t, rigid_body_state_t
from arktypes.utils import pack, unpac
FrankaEnv
class FrankaEnv(ArkEnv):
This class wraps around ArkEnv
and defines an environment tailored for the Franka robot. It is compliant with standard RL environment conventions.
Key Elements
In this case we will define our action and observation channels as below
Action Channel:
Franka/joint_group_command/sim
→ joint_group_command_t
Sends desired joint positions.
Observation Channels:
Franka/joint_states/sim
→ joint_state_t
Receives joint angles from Franka.
ball/ground_truth/sim
→ rigid_body_state_t
Receives position and orientation of the ball.
def __init__(self, config=None, sim=True)
config
: path or dict to the system configuration YAML.sim
: whether to run in simulation or real-world mode.
environment_name = "Franka_Enviroment"
action_space = {
'Franka/joint_group_command/sim': joint_group_command_t,
}
observation_space = {
'Franka/joint_states/sim': joint_state_t,
'ball/ground_truth/sim': rigid_body_state_t,
}
Franka/joint_states/sim
: receives robot joint angles.ball/ground_truth/sim
: receives the pose of a ball in the scene. super().__init__(
environment_name=environment_name,
action_channels=action_space,
observation_channels=observation_space,
global_config=config,
sim=sim
)
ArkEnv
constructor, which:
def action_packing(self, action):
return {
'Franka/joint_group_command/sim': pack.joint_group_command(
name="all",
cmd=action,
)
}
joint_group_command
helper to create a packed message.def observation_unpacking(self, observation):
ball_position = unpack.unpack_rigid_body_state(
observation['ball/ground_truth/sim']
)
joint_states = unpack.unpack_joint_state(
observation['Franka/joint_states/sim']
return [ball_position, joint_states]
def terminated_truncated_info(self, state, action, next_state):
Currently we will leave this blank but is a placeholder logic to decide whether the episode should terminate or truncate, for more advanced RL/IL examples Currently returns:
(False, False, None)
Can be extended based on task goals (e.g., if ball is reached or time limit exceeded).
def reward(self, state, action, next_state):
This can also be customised to reflect task-specific rewards (e.g., distance between gripper and ball).
def reset_objects(self):
Called during env.reset()
. Responsible for putting all objects back into their initial state.
You can call reset component function to reset the objects in the simulation.
self.reset_component("Franka")
Resets the Franka robot using configuration or user-defined values.
Optional keyword arguments if resetting a robot is:
If left blank it will default to the values given in the config file.
self.reset_component("ball", base_position=[-0.5, 1, 0.5])
Likewise we can reset the ball to any position of our choosing.
Optional keyword arguments if resetting an object is:
If left blank it will default to the values given in the config file.
| --- | --- |