Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback Error In Multi RouterClient: No callback list instantiated #166

Open
WLucky opened this issue Apr 26, 2023 · 2 comments
Open

Callback Error In Multi RouterClient: No callback list instantiated #166

WLucky opened this issue Apr 26, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@WLucky
Copy link

WLucky commented Apr 26, 2023

Description

When creating two routers in the same code using the Python API, and operating both arms in collaboration using multi-threading, an error "No callback list instantiated" is raised, and one of the arms times out waiting for a response.

Version

At a minimum, provide the Kortex API and Kortex-enabled device versions.

KortexAPI : kortex_api-2.5.0.post6-py3-none-any.whl

Kortex Device : kinova gen3

Steps to reproduce

  1. Create two or more RouterClient instances
  2. create two threads to run two arms meanwhile like human, we use example_trajectory in examples/110-Waypoints/01-send_angular_wapoint_trajectory.py
  3. Error: No callback list instantiated for one arm and will wait for timeout after action end.

Code example

with utilities.DeviceConnection.createTcpConnection(ip=LEFT_ARM_IP) as left_router, utilities.DeviceConnection.createTcpConnection(ip=RIGHT_ARM_IP) as right_router:
        # Create required services
        left_base = BaseClient(left_router)
        right_base = BaseClient(right_router)
        
       action_thread([action_1_l, action_1_r], [left_base, right_base])


def action_thread(aciton_func_list, base_list):
    threads = []
    for action_func, base in zip(aciton_func_list, base_list):
        t = threading.Thread(target=action_func, args=(base,))
        threads.append(t)

    for t in threads:
        t.start()

    for t in threads:
        t.join()

def action_1_l(base, jointPoses = left_jointPoses, durations = durations):
    
    # Example core
    success = True

    # success &= move_to_home_position(base)
    success &= move_trajectory(base, jointPoses, durations)
    
    return 0 if success else 1

Expected behavior

Describe the expected behavior (in regard to the bug described above).

I hope both arms can receive the returned message after completing their respective actions, such as completion notification, and then perform the corresponding processing.

Any other information

Any other information you believe the developers need to know.

The reason for the error is that the notificationService in RouterClient is unique to the class, rather than unique to the instance. As a result, when registering the notification callback, the subsequent router will overwrite the callback function of the previous instance, leading to an error.

class RouterClient:
    notificationService = {}

    def __init__(self, transport, errorCallback=None):
        self.transport = transport
        self.sessionId = 0
        self.m_isActive = True
        self.callback = partial(self.onFrameCallback)
        self.transport.registerOnFrameCallback(self.callback)
        self.errorCallback = errorCallback
        self.frameHandler = FrameHandler()
        self.m_hitCallback = None

fixed:

class RouterClient:
    def __init__(self, transport, errorCallback=None):
        self.notificationService = {}
        self.transport = transport
        self.sessionId = 0
        self.m_isActive = True
        self.callback = partial(self.onFrameCallback)
        self.transport.registerOnFrameCallback(self.callback)
        self.errorCallback = errorCallback
        self.frameHandler = FrameHandler()
        self.m_hitCallback = None
@felixmaisonneuve
Copy link
Contributor

Hi @WLucky,

I looked into it, it seems to only apply for the python API.
I opened a bug internally and it will be fixed in an upcoming release.

I will leave this issue opened until it is fixed.

In the meantime, you can either use the C++ API or apply the modification you suggested directly in your local python package (somewhere in home/user/.local/lib/pythonX.X/site-packages/kortex_api/RouterClient.py)

I assume you already did the second option since you posted the fix as well. I assume your system is running now.

Thank you very much for sharing this bug,
Felix

@WLucky
Copy link
Author

WLucky commented May 11, 2023

Hi @WLucky,

I looked into it, it seems to only apply for the python API. I opened a bug internally and it will be fixed in an upcoming release.

I will leave this issue opened until it is fixed.

In the meantime, you can either use the C++ API or apply the modification you suggested directly in your local python package (somewhere in home/user/.local/lib/pythonX.X/site-packages/kortex_api/RouterClient.py)

I assume you already did the second option since you posted the fix as well. I assume your system is running now.

Thank you very much for sharing this bug, Felix

Thank you for your reply. I am glad that I could contribute to this project.

@felixmaisonneuve felixmaisonneuve added the bug Something isn't working label May 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants