robotraconteur / robotraconteur_abstract_robot_python

Apache License 2.0
0 stars 0 forks source link

Implementation issue with jog_cartesian function #1

Closed maxwelllls closed 2 weeks ago

maxwelllls commented 4 months ago

@johnwason I am attempting to directly call the robot’s jog_cartesian function using pyri to initiate robot jog motion, but I have encountered some issues that I hope to discuss with you.

There are two issues:

The jog_cartesian function prototype defined in robdef is as follows:
function void jog_cartesian(SpatialVelocity{int32} max_velocity, double timeout, bool wait) Here, the type SpatialVelocity{int32} corresponds to RRMapPtr<int32_t,SpatialVelocity> in RobotRaconteur. However, the description of jog_cartesian in AbstractRobot is as follows:

 def jog_cartesian(self, velocity, timeout, wait):
        """
        :param velocity: The desired end effector spatial velocity position in meters/s, radians/s
        :type joint_position: SpatialVelocity
        :param timeout: The timeout to run at the specified velocity
        :type timeout: float
        :param wait: Wait for completion or return immediately
        :type wait: bool
        :param handler: Handler to call when function is complete
        :type handler: Callable[[], Exception]
        """

Should the type of velocity be SpatialVelocityor SpatialVelocity{int32}? It seems that there is no reason to define velocity as a Map type. Can the definition in robdef be modified to jog_cartesian(SpatialVelocity max_velocity,?

For the implementation of the asynchronous jog_cartesian function, I referred to the implementation of async_jog_joint, but I could not find the call relationship between robotics_jog_service:self.robot.jog_joint()and abstract_robot:async_jog_joint(). I understand that this is an RPC call wrapped by RobotRaconteur, but the names and parameters on both ends are different. Is there an additional wrapper at some intermediate layer?

johnwason commented 4 months ago

jog_cartesian has been on my TODO list for a vey long time... The problem is dealing with constraining both the joint velocity and cartesian velocity without sending impulses to the robot.

My suggestion is you call jog_cartesian() in PyRI rather than calling the driver. This function uses a quadratic programming method. The jog service is automatically started when you run pyri-core.

An example of calling jog_cartesian in pyri:

from pyri.device_manager_client import DeviceManagerClient
from RobotRaconteur.Client import *

import time

d = DeviceManagerClient('rr+tcp://localhost:59902?service=device_manager')

d.refresh_devices(1)

jog_service = d.get_device_client("jog_cartesian",1)

print(jog_service.device_info.device.name)

jog = jog_service.get_jog("robot")

jog.prepare_jog()

while True:
    for i in range(20):
        jog.jog_cartesian3([0,0,1],[0,0,0])
        time.sleep(0.005)

    jog.stop_joints()

    for i in range(20):
        jog.jog_cartesian3([0,0,-1],[0,0,0])
        time.sleep(0.005)

    jog.stop_joints()

The jog_cartesian in the driver has stricter requirements then the PyRI service.

johnwason commented 4 months ago

Sorry, it looks like jog_cartesian3 was removed. I will get back to you on an example of using the service.

maxwelllls commented 4 months ago

I know that a SpatialVelocity type can be created using array_to_spatial_velocity as follows:

geom_util = GeometryUtil(client_obj = self.robot)
v_des = geom_util.array_to_spatial_velocity(vel2 * speed_perc * 0.01)
self.robot.jog_cartesian(v_des, 0.2, False)

However, , I do not know how to construct an object of type SpatialVelocity{int32}.

johnwason commented 4 months ago

The {int32} suffix means that the type is a dictionary with int32 key. It should be:

v_des2 = {0: v_des}

for the argument.