abr / abr_control

Robotic arm control in Python
Other
417 stars 99 forks source link

TypeError: 'numpy.ndarray' object is not callable #94

Closed whynpt closed 2 years ago

whynpt commented 2 years ago

my code is demo in readme:

from abr_control.arms import jaco2
from abr_control.controllers import OSC
from abr_control.interfaces import Mujoco
import numpy as np

robot_config = jaco2.Config()
interface = Mujoco(robot_config)
interface.connect()

ctrlr = OSC(robot_config, kp=20,
            # control (x, y, z) out of [x, y, z, alpha, beta, gamma]
            ctrlr_dof=[True, True, True, False, False, False])

target_xyz = [.2, .2, .5]  # in metres
target_orientation = [0, 0, 0]  # Euler angles, relevant when controlled
for ii in range(1000):
    feedback = interface.get_feedback()  # returns a dictionary with q, dq
    u = ctrlr.generate(
        q=feedback['q'],
        dq=feedback['dq'],
        target=np.hstack([target_xyz, target_orientation]))
    interface.send_forces(u)  # send forces and step CoppeliaSim sim forward

interface.disconnect()

an error occured at line 224 of basic_config.g(). The traceback is:

Traceback (most recent call last):
  File "/home/room525/Desktop/code/abr_control/demo.py", line 19, in <module>
    u = ctrlr.generate(
  File "/home/room525/Desktop/code/abr_control/abr_control/controllers/osc.py", line 301, in generate
    u -= self.robot_config.g(q=q)
  File "/home/room525/Desktop/code/abr_control/abr_control/arms/base_config.py", line 224, in g
    return np.array(self._g(*parameters), dtype="float32").flatten()
TypeError: 'numpy.ndarray' object is not callable

the problem is caused by self._g(*parameters), where self._g is a np.ndarray [0. 0. 0. 0. 0. 0.], the parameters is joint angle that's a tuple. Does self._g(*parameters)mean self._g plus parameters?

whynpt commented 2 years ago

I find what is the exact cause of problem. To control jaco2 with mujoco, I run robot_config = jaco2.Config() interface = Mujoco(robot_config) interface.connect(), but jaco2.Config() object has no attribute '_connect' where MujocoConfig has. So i did some change in jaco2.Config(). I make jaco2.Config()child class ofMujocoConfig, but _g shows both in Baseconfig and MujocoConfig. Baseconfig._g is None, and MujocoConfig_g is np.zeros(6). so i want to know how to connect jaco2 with mujoco, simultaneously add gravity to robot.

p3jawors commented 2 years ago

The problem is that you are using the abr_control.arms.jaco2 config with the Mujoco interface. Mujoco has it's own xml format it expects for arm configs, so instead of using the jaco2.py config in the arms folder, you need to load the xml into the MujocoConfig, which subclasses the base config. I've added an item to the backlog to update the README to explain the differences between backends.

I've updated your script and it should run for you now. I've tested it on my machine and it runs fine. Note, if you go to abr_control/docs/examples/Mujoco there are many examples showing how to use the various controllers and path planners.

Cheers

import traceback

import glfw
import numpy as np

from abr_control.arms.mujoco_config import MujocoConfig as arm
from abr_control.controllers import OSC
from abr_control.interfaces.mujoco import Mujoco

robot_config = arm('jaco2')
interface = Mujoco(robot_config, dt=0.001)
interface.connect()

ctrlr = OSC(robot_config,
            kp=200,
            # control (x, y, z) out of [x, y, z, alpha, beta, gamma]
            # NOTE due to the angles of the jaco2 wrist joints, there
            # are cases where we hit a singularity that reduces the arm
            # to less than 6 controllable degrees of freedom, so control
            # of 6 degrees does not work well in some cases
            ctrlr_dof=[True, True, True, False, False, False])

target_xyz = [.2, .2, .5]  # in metres
target_orientation = [0, 0, 0]  # Euler angles, relevant when controlled
for ii in range(1000):
    # NOTE look into abr_control path planners to filter your path to target
    # using a single, unfiltered target will results in worse peformance and
    # more jerk
    feedback = interface.get_feedback()  # returns a dictionary with q, dq
    u = ctrlr.generate(
        q=feedback['q'],
        dq=feedback['dq'],
        target=np.hstack([target_xyz, target_orientation]))
    # add gripper joint angles (not force controllable)
    # these are the steady state positions, but can be changed
    u = np.hstack((u, np.zeros(robot_config.N_GRIPPER_JOINTS)))
    interface.send_forces(u)  # send forces and step CoppeliaSim sim forward

interface.disconnect()

Note that if you want 6DOF control (position and orientation) you'll need to change ctrlr_dof to be True for all 6 degrees of freedom. The performance of the jaco2 in this case will not be great as it has singularities that get introduced due to the ~60deg wrist joints.