Changing control mode from velocity control to planned

I’m running into a issue where if I do the following:

  • Move the axis in velocity control mode (ie set vel_setpoint)
  • Execute a planned move (ie with move_incremental)

The axis seems to “undo” any move that was made in velocity control mode (at an extreme speed) before executing the planned move.

I’ve tried resetting the encoder count (with encoder_.set_linear_count(0)) and resetting the controller (with controller_.reset()) but they don’t appear to resolve the problem, rather make it worse.

Could I get some advice on how I can safely transition from velocity controlled mode into position controlled mode (move_incremental(...))? Thanks!

I think you need to set the control mode to 3 “position mode”
Try the following:
odrv0.axis0.controller.config.control_mode = 3
odrv0.axis0.controller.config.input_mode = 5

This sets you in position control and trajectory control so you can use move_incremental
Note: move_incremental is a relative motion and not absolute. Meaning that no matter the encoder count, the axis will move the specified counts in move_incremental(count, False) irrelevant of the encoder count.

Also note that to set the velocity in position and trajectory mode you need:
odrv0.axis0.trap_traj.config.vel_limit =
odrv0.axis0.trap_traj.config.accel_limit =
odrv0.axis0.trap_traj.config.decel_limit =

make sure that the velocity limit is at least equal to the vel_limit you set in the above command. Meaning make sure that odrv0.axis0.controller.config.vel_limit = should be atleast the limit you set above.


1 Like

Just noticed that odrv0.axis0.conroller.config.input_mode is only for the RazorsEdge firmware!
odrv0.axis0.controller.config.control_mode = 3 (position mode)
odrv0.axis0.controller.config.control_mode = 4 (trajectory mode)

No input_mode for default firmware


Thanks for the suggestions! I’m afraid I wasnt really clear in my initial post - I can enter planned control mode.

I can simplify my problem as follows:

odrv0.axis0.controller.vel_setpoint = 10000 # move the axis a little in velocity controlled mode
odrv0.axis0.controller.vel_setpoint = 0
odrv0.axis0.controller.config.control_mode = 3 # executing this line seems to make the axis "undo" all the movement done in velocity controlled mode as fast as possible, making the axis spin wildly

Essentially, entering position control after moving the axis in velocity control causes the motor to spin wildly. Is there a way to prevent this?

Yes. The issue I believe is that the commanded position does not match the encoder position, so once you place the controller in position mode, it would attempt to move to the commanded position as fast as possible, triggering over speed and possibly bus under voltage errors.

It is like if you give it a position and while the motor is moving you hold it physically from rotating, and when you let go, it will spin very rapidly.

Try look at controller.input_pos and compare it to encoder.pos_estimate, if they are not equal try to make them equal before entring position mode:

odrv0.axis0.controller.input_pos = odrv0.axis0.encoder.pos_estimate

See what happens.

Thanks. It’ll appear that input_pos is a RazorsEdge feature (on the input-filter branch which dosent seem to be there), is there a equivalent for the master branch?

Edit: Thanks for your assistance!

odrv0.axis0.controller.pos_setpoint = odrv0.axis0.encoder.pos_estimate stopped the jerk.


Your welcome and yes, in the master branch it is controller.move_to_pos(counts)
Keep in mind, move_to_pos() is an absolute motion, while move_incremental() is relative.

Thnak you. Solved my problem with switching from velocity mode to control mode.

I have exactly the same problem.
The solution from above doesn’t work for me because I’m using firmware version 0.5.1 and I can’t set pos_setpoint because it’s read-only.
I tried “odrv0.axis0.controller.input_pos= odrv0.axis0.encoder.pos_estimate” before switching from velocity control to position control but the problem is still the same. (pos_setpoint remains unchanged)
Does someone know a solution to this problem?

You will have to go through INPUT_MODE_PASSTHROUGH, unfortunately.

  1. Set input_pos = pos_estimate
  2. Go to INPUT_MODE_PASSTHROUGH. On the next cycle, it will set pos_setpoint from input_pos
  4. Set next input_pos
1 Like

Thank you!
I don’t have my setup near me right now. I will try this tomorrow and come back with a feedback.

It’s working perfectly! Thanks!

1 Like

Go to INPUT_MODE_PASSTHROUGH. On the next cycle, it will set pos_setpoint from input_pos

Do I need to wait before the next cycle?
Or can I directly send the command continuously?

By the way, is there any plane to optimize the problem between pos_estimate and pos_setpoint when the control mode or request state is switched?

Do I need to wait before the next cycle?
Or can I directly send the command continuously?

It’s a 125 microsecond cycle, so as long as you’re not sending faster than that you’re ok.

Not really. There’s no good solution - you end up breaking someone’s expectations whether you synchronize them or not.

Gosh thanks for this. I will delete the other topic I wrote asking about this.