Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   C/C++ (http://www.chiefdelphi.com/forums/forumdisplay.php?f=183)
-   -   Keeping two motors in sync (http://www.chiefdelphi.com/forums/showthread.php?t=134738)

Ether 18-02-2015 17:57

Re: Keeping two motors in sync
 
Quote:

Originally Posted by GeeTwo (Post 1446612)
I am wondering about the slave part:

Are you intentionally basing the P value on the error from the set point, but the I value on the error from the master?

Yes.

Quote:

If so, I'm going to have to puzzle a bit as to what would happen if the master jammed.
Additional logic could be added to detect and mitigate the consequences of either master or slave jamming.



Kevin Sevcik 18-02-2015 18:42

Re: Keeping two motors in sync
 
Quote:

Originally Posted by GeeTwo (Post 1446612)
I am wondering about the slave part:

Are you intentionally basing the P value on the error from the set point, but the I value on the error from the master? If so, I'm going to have to puzzle a bit as to what would happen if the master jammed.

That's Ether's proposed master-slave dual PID from the thread I linked above. The consequences of the master jamming would depend on the max setpoint error and the P and I values.
If P*error < i2bLimit, then the I term will halt the slave, quickly or slowly depending on I and possibly reverse it and drag it back down to e1pos. Things would obviously settle down somewhere near where P*error = i2bLimit, or at e1pos, once the I term stopped oscillating around e1pos.
If P*error > i2bLimit, then e2is going to go past e1pos and stabilize wherever P*error finds drops down below i2bLimit.

Ether,
I think your pseudo code implements your proposed controller correctly, I'm just not entirely certain the actual dynamics would work as intended. I think it'd take a good deal of tweaking to get your slave's I value tuned well enough that it's going to fight that RLPC trying to drag it upwards with ever increasing error.

Here's something that just popped into my head. What if you limit the RLPC sort of how you limit the integral error? Since we're not doing proper servoing with fatal following errors or anything, we can just choose to slow down (or stop) the ramp if a motor gets in a bind. Super Pseudo code:
1. Calculate RLPC as above, probably saving the change value / actual increment.
2. Calculate output commands for both motors as 2 standard independent PIDs following the RLPC.
3. If both motor outputs are less than abs(1.0) then you're done and you set values and wait for the next loop.
4. If a motor value is >= abs(1.0), then you back calculate the necessary incremental change to hit 1.0 output on the limited motor. Go back to step 1, but with your new (temporary) rate limit (which may be 0). Make sure you only loop back at most twice. Any more would be pointless since you've already tried to reduce things for both motors.

It's a good bit trickier with the back calculating and all, but I think it accomplishes our actual goal. If I'm thinking about it correctly, then what should happen is if either side gets stuck, the RLPC just stops moving. The free side will servo up to the RLPC, obviously, but the RLPC should only be a small-ish distance ahead. Whatever error it takes to get the stuck side to hit 1.0 output. (Possibly we ignore the I and D terms when figuring this.) I think initial moves from standstill and reversals would be interesting, since limiting the rate to only what's currently achievable by the motor would act as a defacto soft-ish start. With an RLPC controller (which is the modified PID I've already implemented) the starts can be a little bumpy, since you can pretty quickly hit maximum output cause your setpoint has infinite acceleration and the motors don't. The setpoint can get far ahead of the normal steady state error, so the motors can over shoot once they break free and start moving.

Mind you, it'll run a little strange what with the speeding up and slowing down, but I think if your PIDs are already pretty stable, it shouldn't add any weird oscillations from the two systems interacting with each other through mechanical delay. Worst case is the RLPC just stops moving completely because the two sides are oscillating around it out of phase and at max command values. You'd have to throw up your hands and curse me for peddling hare-brained poorly thought out control algorithms, but your system would probably survive.

amesmich 18-02-2015 19:34

Re: Keeping two motors in sync
 
Quote:

Originally Posted by Kevin Sevcik (Post 1446598)
I don't have code for a master-slave system yet. I do have C++ code for a PIDController derivative that will let you smoothly ramp the setpoint from A to B at a given rate. As long as you have the PID loops tuned well and you keep the rate below the max speed for your slower side, things should work and stay level.

I should've asked earlier, but what language are you guys using? If it's C++, I can cleanup and better document my code tonight and post it tomorrow. If it's Java, I'll have to port things, which will take a day or two, and won't be tested, obviously. If it's Labview.... I'll have to think about how to approach the problem in Labview.

We are using C++. I just read through all these posts and they are a huge help. We appreciate the feed back, and would very much appreciate a look at your code. Thanks

Ether 18-02-2015 19:55

Re: Keeping two motors in sync
 
Quote:

Originally Posted by Kevin Sevcik (Post 1446649)
Ether,
I think your pseudo code implements your proposed controller correctly, I'm just not entirely certain the actual dynamics would work as intended. I think it'd take a good deal of tweaking to get your slave's I value tuned well enough that it's going to fight that RLPC trying to drag it upwards with ever increasing error.

The purpose of the position command rate-limiting (RLPC) is to help M2's integrator keep up. Yes it's an integrator so it's going to lag somewhat, but don't forget the contribution of M2's proportional action which has no lag.

The best way to settle the matter I guess is to run it on hardware or a simulation.



Jared Russell 18-02-2015 20:14

Re: Keeping two motors in sync
 
This is fundamentally no different than getting a differential drive robot to drive straight. You want both sides of the mechanism to end up in the same place at the same time.

In drivetrains people often use a controller that is something like:

Code:

output_steering = PID(steering_error)
output_throttle = PID(distance_error)

left_command = output_throttle + output_steering
right_command = output_throttle - output_steering

PID() could be any feedback (or feedforward + feedback) controller you want, and the steering and throttle controllers would have different gains.

distance_error is usually computed as:

Code:

distance_error = desired_distance - (left_distance + right_distance) / 2
...and steering error could be calculated by a gyro, or by integrating encoder values over time.

This has worked well on hundreds of FIRST robots for driving, and generalizes as a simple way for coordinating two separate mechanisms. You just need to be careful with how you handle saturation/integral windup and you're golden.

Ether 18-02-2015 21:27

Re: Keeping two motors in sync
 
Quote:

Originally Posted by Jared Russell (Post 1446708)
You want both sides of the mechanism to end up in the same place at the same time.

That's half the problem. The other half is keeping the sides synchronized while doing so.

For an elevator the synchronization is important because of binding. For drivetrains it's important because the final location of the robot depends on the sides staying in sync during the journey..


Quote:

In drivetrains people often use a controller that is something like:

Code:

output_steering = PID(steering_error)
output_throttle = PID(distance_error)

left_command = output_throttle + output_steering
right_command = output_throttle - output_steering


Nice and symmetric. No master/slave.


Quote:

distance_error is usually computed as:

Code:

distance_error = desired_distance - (left_distance + right_distance) / 2

I think that's a big part of making this work, so that the throttle and steer controllers don't fight each other. They can be satisfied independently.

Quote:

...and steering error could be calculated by a gyro, or by integrating encoder values over time.
Could you elaborate on what you mean here by "integrating encoder values over time"? Could it be as simple as just using encoder counts instead of rate?




kylelanman 18-02-2015 23:02

Re: Keeping two motors in sync
 
Quote:

Originally Posted by GeeTwo (Post 1446225)
Belt and suspenders? No argument here.

OBTW, by "criss-cross chain", you don't mean a figure 8, do you?

Yes I do! We have a guide/spacer at the crossing point to ensure the chain doesn't hit itself.

Jared Russell 18-02-2015 23:35

Re: Keeping two motors in sync
 
Quote:

Originally Posted by Ether (Post 1446751)
Could you elaborate on what you mean here by "integrating encoder values over time"? Could it be as simple as just using encoder counts instead of rate?

Yeah. The process variable for the steering controller in a differentially steered vehicle is heading, which is just the difference in encoder counts times a constant (to do a unit conversion). The constant is theoretically the inverse of the radius of the wheelbase; in practice you can tune it empirically to incorporate slip (if desired).

In the generalized motor synchronization case, using (left_distance - right_distance) would be fine.

Using a trajectory generator to make nice smooth, non-saturated position setpoint profiles is a great way to help solve the saturation/windup problem.

GeeTwo 18-02-2015 23:40

Re: Keeping two motors in sync
 
Quote:

Originally Posted by kylelanman (Post 1446821)
[Figure 8 chain] Yes I do! We have a guide/spacer at the crossing point to ensure the chain doesn't hit itself.

What's the angle between the two axles? Teeth on each sprocket? Distance between axles' CPA? Chain size? We're trying to do a figure 8 roller chain at a massive scale for our team motto, "Infinite Possibilities", and could use a bit of help in art of the possible here. Our team logo is a 7-tooth sprocket, so we're really limited in how much horizontal spacing we get for any given angle. Our massive scale last year didn't work out so well - we went with about an 8" pitch on the chain (don't quote me; I wasn't part of the team on this) using masonite board. At some point, the chain fell on the floor and shattered. We turned off the motor and just put up the two sprockets with the "tiger eye" in the center hole. It still looked cool, but not nearly as cool as we'd hoped.

Kevin Sevcik 18-02-2015 23:58

Re: Keeping two motors in sync
 
1 Attachment(s)
So here's a stripped down version of our robot code with just the lift stuff and the rate controlled PID that I worked up.

There's some features I added to the PID class that may not be relevant to your system. I added a Kv term for velocity feedforward based on whatever your ramp rate is. There's also limit switches integrated in there so the PID stops if a limit is hit in the direction you're moving. It both prohibits motor command in that direction, and updates the target setpoint to whatever the current position is when you run into a limit. If you're not using limits, just leave those blank or set to NULL and that logic will be skipped. To accommodate different wiring practices, the bool limitHit parameter sets what value indicates that a limit has been hit/tripped. There's a few others as well, so ask if there's any confusion

Ether 19-02-2015 00:43

Re: Keeping two motors in sync
 
Quote:

Originally Posted by Jared Russell (Post 1446837)
Using a trajectory generator to make nice smooth, non-saturated position setpoint profiles is a great way to help solve the saturation/windup problem.

Attached is a simple trajectory generator in Maxima. It inputs max accel, max speed, and distance to destination... and outputs equations for and a plot of speed and distance vs time.

Edit: moved attachments here.



amesmich 19-02-2015 06:37

Re: Keeping two motors in sync
 
This is amazing. I am learned so much. Kevin, Ether, and Jared. You have helped more than you know. I wish I had more to say but I am busy reading whay you wrote and this site which has helped me wrap myhead around the variables and acronyms you have been using. Thanks.


All times are GMT -5. The time now is 13:12.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi