Skip to content

The wrong feedback of franka Panda's Fk and its F/T sensor #739

@HongyuanChen

Description

@HongyuanChen

System Info

Ubuntu 20.04
Robosuite 1.5

Information

When I try to use Robosuite to do the Reinforcement Learning, I focus on the existing environment in manipulation folder. However, I encountered problems about the wrong feedback of Panda(its default gripper:panda hand). When I do the action to make the EEF continuously downward until the robot touch the desk. I get the EEF_pos and F/Tsensor data from eef_pos = np.array(env.robot._hand_pos["right"]) and eef_force = np.array(self.robot.ee_force["right"]). When I run the scipts, the robot does the action,but the eef_pos and eef_force remain consistent.
(Note: the eef_force seems have a bias the ForceZ remain -4N]

Reproduction

panda_pickplace_env.py:

`from robosuite import make
from robosuite import load_composite_controller_config

from robosuite.wrappers.gym_wrapper import GymWrapper
import gym
import numpy as np
from gym import spaces
from robosuite.controllers.composite.composite_controller_factory import load_composite_controller_config
import random

import robosuite.robots.robot
class PandaPickPlaceRLWrapper(gym.Env):
def init(self, has_renderer=False, camera_name="agentview", camera_size=(84, 84), control_delta_clip=0.05):
super().init()
self.camera_name = camera_name
self.camera_size = camera_size
self.control_delta_clip = control_delta_clip

    controller_config = load_composite_controller_config(controller="BASIC",robot="Panda")
    controller_config["use_sensors"] = True
    
    self.env = make(
        env_name="PickPlaceCan",
        robots="Panda",
        controller_configs=controller_config,
        has_renderer=has_renderer,
        has_offscreen_renderer=True,
        use_camera_obs=True,
        use_object_obs=False,
        reward_shaping=True,
        reward_scale = 1.0,
        control_freq=20,
        camera_names=[camera_name],
        camera_heights=camera_size[1],
        camera_widths=camera_size[0],
        render_camera=camera_name,
    )

    self.sim = self.env.sim
    self.control_freq = self.env.control_freq
    self.robot = self.env.robots[0]
    obs = self.env.reset()
    self.obs_img_shape = (3,) + camera_size

    # new
    self.force_torque_offset = None
    self._calibrate_sensors()

    self.observation_space = spaces.Dict({
        "image": spaces.Box(0, 255, shape=self.obs_img_shape, dtype=np.uint8),
        "joint_pos": spaces.Box(low=-np.pi,high = np.pi,shape=(7,),dtype=np.float32),
        "force_torque": spaces.Box(low=-np.inf, high=np.inf, shape=(6,), dtype=np.float32)
    })

    self.action_space = spaces.Box(low=-self.control_delta_clip, high=self.control_delta_clip, shape=(7,), dtype=np.float32)
    self.total_reward = 0
    self.episode_rewards = []

# new
def _calibrate_sensors(self):
    """校准力/力矩传感器"""
    obs = self.env.reset()
    try:
        force_data = self.sim.data.sensor("gripper0_right_force_ee")
        torque_data = self.sim.data.sensor("gripper0_right_torque_ee")
        print(f"MuJoCo Sensor: Force: {force_data}, Torque: {torque_data}")
    except ValueError as e:
        print(f"Sensor Error: {e}")
    eef_force = np.array(self.robot.ee_force["right"])
    eef_torque = np.array(self.robot.ee_torque["right"])
    self.force_torque_offset = np.concatenate([eef_force, eef_torque])
    print(f"Sensor offset: {self.force_torque_offset}")

def reset(self):
    # new
    self.robot.set_robot_joint_positions([00, -0.5, 0, -2.0, 0, 1.5, 0.785])
    obs = self.env.reset()
    self.total_reward = 0
    return self._obs_to_dict(obs)

def step(self, action):
    action = np.clip(action, self.action_space.low, self.action_space.high)
    # current_qpos = self.robot.get_joint_positions()
    # new_qpos = current_qpos + action
    # self.robot.set_joint_positions(new_qpos)
    obs, reward, done, info = self.env.step(action)
    self.total_reward += reward
    if done:
        self.episode_rewards.append(self.total_reward)
    return self._obs_to_dict(obs), reward, done, info

def _obs_to_dict(self, obs):
    image = obs[f"{self.camera_name}_image"].astype(np.uint8)
    # (H,W,C)-->(C,H,W)
    image = np.transpose(image,(2,0,1))
    joint_pos = obs["robot0_joint_pos"]
    if "robot0_eef_force" in obs and "robot0_eef_torque" in obs:
        eef_force = obs["robot0_eef_force"]
        eef_torque = obs["robot0_eef_torque"]
    else:
        eef_force = np.array(self.robot.ee_force["right"])
        eef_torque = np.array(self.robot.ee_torque["right"])
    force_torque = np.concatenate([eef_force,eef_torque])
    # state = np.concatenate([joint_pos, eef_force, eef_torque]).astype(np.float32)
    return {"image": image, "joint_pos": joint_pos,"force_torque":force_torque}

def render(self, mode="human"):
    self.env.render()

def close(self):
    self.env.close()

def get_episode_rewards(self):
    return self.episode_rewards

def seed(self,seed=None):
    if seed is not None:
        random.seed(seed)
        np.random.seed(seed)
        self.sim.model.seed = seed
    return [seed]`

test_force_torque.py:

`import robosuite as suite
from panda_pickplace_env import PandaPickPlaceRLWrapper
import numpy as np
import matplotlib.pyplot as plt
import time
import os

env = PandaPickPlaceRLWrapper(has_renderer=True)
obs = env.reset()

steps = []
eef_positions = []
force_torques = []
contacts = []

for step in range(1000):
action = np.zeros(7)
action[2] = -0.05
action[-1] = 0.0
obs, reward, done, info = env.step(action)

eef_pos = np.array(env.robot._hand_pos["right"])
force_torque = obs["force_torque"]
contact = any(c.dist <= 0 for c in env.sim.data.contact[:env.sim.data.ncon])

steps.append(step)
eef_positions.append(eef_pos)
force_torques.append(force_torque)
contacts.append(contact)

env.render()
time.sleep(0.01)  
if done:
    obs = env.reset()

env.close()

eef_positions = np.array(eef_positions) # (200, 3)
force_torques = np.array(force_torques) # (200, 6)
contacts = np.array(contacts) # (200,)

plt.figure(figsize=(12, 8))

plt.subplot(2, 1, 1)
plt.plot(steps, eef_positions[:, 0], label='X', color='r')
plt.plot(steps, eef_positions[:, 1], label='Y', color='g')
plt.plot(steps, eef_positions[:, 2], label='Z', color='b')
plt.title('EEF Position vs. Time Step')
plt.xlabel('Time Step')
plt.ylabel('Position (m)')
plt.legend()
plt.grid(True)

contact_steps = np.where(contacts)[0]
if len(contact_steps) > 0:
plt.axvline(x=contact_steps[0], color='k', linestyle='--', label='First Contact')
plt.legend()

plt.subplot(2, 1, 2)
labels = ['Fx', 'Fy', 'Fz', 'Tx', 'Ty', 'Tz']
colors = ['r', 'g', 'b', 'c', 'm', 'y']
for i in range(6):
plt.plot(steps, force_torques[:, i], label=labels[i], color=colors[i])
plt.title('Force/Torque vs. Time Step')
plt.xlabel('Time Step')
plt.ylabel('Force (N) / Torque (Nm)')
plt.legend()
plt.grid(True)

if len(contact_steps) > 0:
plt.axvline(x=contact_steps[0], color='k', linestyle='--', label='First Contact')
plt.legend()

plt.tight_layout()
output_dir = "plots"
os.makedirs(output_dir, exist_ok=True)
plt.savefig(os.path.join(output_dir, "eef_pos_force_torque.png"))
plt.close()

data = np.hstack([np.array(steps)[:, None], eef_positions, force_torques, contacts[:, None]])
np.savetxt(os.path.join(output_dir, "test_data.csv"), data, delimiter=",",
header="Step,X,Y,Z,Fx,Fy,Fz,Tx,Ty,Tz,Contact", comments="")`

Expected behavior

No response

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions