2b-t / myactuator_rmd

C++ and Python SDK for controlling actuators of the MyActuator RMD-X series, written in C++ with Python bindings
MIT License
15 stars 12 forks source link

Closed-loop position control mode jumping along a trajectory #10

Closed TheIndoorDad closed 3 months ago

TheIndoorDad commented 3 months ago

Hello again Tobit,

I have been trying to use closed-loop position control commands (using your repo installed as a python package) to get a motor to follow a smooth position curve: as a simple test, a sin(t) curve with a typical time step of 1 ms (though I have tried various step sizes up to 0.1 s and down to 0.1 ms). Like this:

startup_pos = {}
for id in motor_IDs:
    startup_pos[id] = motor[id].getMultiTurnAngle()

t = 0
dt = 0.001

def sin_pos(t):
    max_angle = 30 # degrees
    freq = 0.5 # Hz
    return startup_pos[5] + max_angle * math.sin(2 * math.pi * freq * t)

while True:
    fr_knee.sendPositionAbsoluteSetpoint(sin_pos(t), 500)
    time.sleep(dt)
    t += dt

However, this results in my motor jumping to various positions along the expected curve and stopping at each for a moment (maybe about a half-second), like it is only receiving some of the commands and ignoring the others. The frequency of the jumps does not seem to vary with time step size that I can tell. Have you experienced similar? Do you know if there is a substantial delay between when these motors will accept new closed-loop position commands? I'm using several RMD-X8-Pro-H V3, and each I've tested has done the same.

I have also tried various max velocity inputs, which as expected changes the speed at which the motor jumps from one position to the other, but otherwise is the same.

I'm aware this may be an issue with the motor rather than with your repo, so I apologize if this is an inappropriate forum for this discussion. I just figured you may be knowledgeable, so it was worth asking. I have reached out to myactuator for comment also. If this is just a behaviour of the motor for this control mode, I would like to try Motion Control Mode as an alternative, thus #9.

Thanks again, Stefan

2b-t commented 3 months ago

Hi again Stefan, I did some initial tests with a very simple code similar to yours and I observed the very same behaviour that you are describing when setting new set points repeatedly. It works fine though when I send it a single target command and wait for it to complete. There is not much information about the inner workings of this command online. What I expect to be happening is that the actuator itself has its own (secondary) closed loop control with its own gains that in an example like above you are interfacing with your primary loop in an open loop fashion (You never check the position that the actuator returns you and do not adjust your commanded value accordingly). I assume the actuator will try to reach the given set-point at its own speed limited by the max speed you set which might result in a choppy start-stop motion if the gains of the inner loop are not well tuned. You should be able to improve this behaviour by playing around with the max speed parameter though. I was not too interested in position control and so I have not looked much more into it. If I remember I got it reasonably smooth by choosing appropriate max velocity values.

Several comments under this Youtube video suggest that it might be a potential firmware issue with the actuator and that the manufacturer could supply you with an updated firmware that allows you to change the acceleration limits to 0 which should fix this behaviour:

UPDATE: it works great with Arduino, if we set the “position plan max acc” = 0 and “position plan max dec” = 0. In this case the motion is smooth (no steps).

I have not come around to test this though. If you try it out (or MyActuator comes back with an explanation), please let me know!

TheIndoorDad commented 3 months ago

Hi Tobit,

Setting the position planning acceleration and deceleration limits to 0 seems to have worked - each motor I've tested can now follow a smooth curve on position control. Good find on that video. I wonder what setting these parameters to 0 actually does though... Maybe it unlimits the acceleration?

FYI MyActuator did get back to me as well. They said:

The time between sending and receiving the motor command of X8-Pro-H is about 2ms. Sending and receiving the command too quickly will cause CAN message blocking

Which I take to mean a time step of either 2 ms or 4 ms (depending on your interpretation) is required. I'm using 2 ms now and so far its working well. However, prior to changing the acceleration limits the jumping behaviour occurred regardless of time step.

For future reference: I have motors of two RMD models and both exhibited the same behaviour (and are fixed by the same method): X8-Pro-H V3 1:6 and X8-Pro V2 1:9.

Thank you also for your thoughts re: adjusting the max velocity value as a potential improvement. Doing so changed the speed at which the motor would jump from one position to another but it would still stop at each position for a moment. I wasn't able to find a value that resulted in sufficiently smooth movement.

Cheers and thanks again!

P.S. This fix is helpful, but I am also still interested in an implementation of Motion Mode Control as #9. Thank you for taking a look at that - I look forward to hearing your thoughts.

TheIndoorDad commented 3 months ago

Just to add a couple details: I was able to change the acceleration limits to 0 without a firmware update. I did so with a manually sent (can-utils cansend) CAN frame though, since I think there is a lower bound on the allowable values in your code (though I didn't try to use it). Presumably I could have also done so in their software connecting through the UART module.

2b-t commented 3 months ago

It is likely that you can't send these values through my code. I implemented it according to their protocol documentation. Setting the limits to 0 is not something that is discussed there. I will update the code accordingly and add a comment. Sure, I will have a look at how to implement this and respond to your other issue in the following days.

Yes, I have seen the 2 ms (and therefore 500 Hz update rate) as well in previous tests, see https://github.com/2b-t/myactuator_rmd_ros/pull/1#issuecomment-2156685589.

TheIndoorDad commented 3 months ago

Thanks. Yes it may be helpful to have something in the code to change acceleration limit to 0: in some further testing today it does seem like setting the acceleration limit to 0 unlocks the acceleration, so when I send a single position control command with a max velocity e.g., of 500 I get a very high acceleration on motion start and some overshoot at the destination. For my application that's likely fine, as I expect to mostly use position commands at each time step over a path rather than a single command for a large position change. It may be helpful to be able to update the acceleration limit to and from 0 in the code depending on whether you're sending repeated or single commands though.