elephantrobotics / pymycobot

This is a python API for ElephantRobotics product.
MIT License
109 stars 54 forks source link

Real-Time Synchronization of movement #13

Closed tkdsym2 closed 3 years ago

tkdsym2 commented 3 years ago

Describe the bug myCobot reads the slider values and does not run smoothly.

To Reproduce I set up an OSC server in python and send values using the pymycobot module. Here is a part of the function. However, I just use prepared functions.

def sync_angle(self, _angles, _speed):
        self.arm.sync_send_angles(_angles, _speed)

Here is a video recording of the operation of the slider and the actual movement. At 1 minute and 7 seconds, I try to move the slider while holding it, but mycobot does not move smoothly. https://www.youtube.com/watch?v=13HlRCM19ws

Expected behavior It is expected that the position and angle of myCobot will move smoothly according to the position of the slider. It is also hoped that a tracking device such as Leap Motion can be used to synchronize the position of the mycobot with the position of one's hand by continuously sending values in real time.

Screenshots Recording Video: https://www.youtube.com/watch?v=13HlRCM19ws

Desktop (please complete the following information):

Additional context myCobot is Tranponder mode.

zlj-zz commented 3 years ago

This sync method relies on is_in_position(), but is_in_positon is not so stable. Serial communication contains packet loss and delay, so this may be the reason why mycobot can not run smoothly.

tkdsym2 commented 3 years ago

@zlj-zz Thank you very much for your feedback. I am using the official Transponder program. The rate is 115200, it means fastest. So you mean that in order to achieve smoother movement, the Transponder program needs to be modified or the signals sent by the python program need to be better controlled.

In addition, I just saw a couple of samples that realize the smooth movement (1, 2). One of them uses ROS, while the other one looks like it implements the original program. Do they cover packets and delays, and the losses therein? I have checked the script to control myCobot from ROS. However, it looks like it just sends_radians here. Is there something else you are doing on the ROS side?

Do you have any ideas on how to send signals from python to myCobot to make it run smoothly?

zlj-zz commented 3 years ago

@tkdsym2 The probability of packet loss is very small.The question is on is_in_position(). According to my current test, this method cannot return to true immediately after the manipulator reaches the point.

The manipulator may not be able to reach the target point completely due to the large force distance, and the error between the real angle and the target angle is too large (for example > 5mm), so is_in_position() can not judge the position successfully. So you may need to wait until the timeout (the default is 7S).

If you want to achieve a function similar to tracking, then I believe your data should be continuous and the time interval is very short.So you may not need to use this method. You can try to send data continuously (e.g. angles), as follows:

while True:
    angles = queue.get() # Getting data from a queue.
    mycobot.send_angles(angles, 90)
    time.sleep(.05)

It should also be noted that the time taken to send the data itself is about 5ms(e.g. send_angles() or something).

tkdsym2 commented 3 years ago

@zlj-zz Thank you very much for your great feedback, and I am sorry to be late.

I had been trying to use your example. However, the movement of myCobot was the same. I just pushed my codes using Processing instead of TouchDesigner. It is easier and more simple than using TouchDesigner. The code just sends one angle based on the parameter from the slider on Processing program.

Could you please see if what I am doing is the same as what you have shown me? Also, it would be great if you could actually run the code to see what is happening.

thanks!

zlj-zz commented 3 years ago

I am sorry, I don't have a Processing environment. But I looked at your code and it didn't look like a problem.

But the following code will read the serial port 9 times, too much fast reading may lead to empty data return. It seems that once is enough.

    while True:
                if connection:
                    simpleClient.send_message('/util/status/angles', arm.get_arm_status()['angles'])
                    simpleClient.send_message('/util/status/coords', arm.get_arm_status()['coords'])
                    simpleClient.send_message('/util/status/radians', arm.get_arm_status()['radians'])
                    # print('{}'.format(arm.get_arm_status()))

                asyncio.sleep(0.01)

BTW. Do you have any other questions? This doesn't seem to be tracking.

zlj-zz commented 3 years ago

If there is no activity for a long time, this issue will be closed.