AnswerBun.com

Res-Scaling method beats PID controller. How?

Robotics Asked by Pe Dro on October 26, 2020

Scenario:

I have a robotic arm that has a (1D) lidar on its end, to orient itself with respect to the slant table in front of it. The lidar returns pretty accurate distance values in mm. The motor controlling the arm’s motion towards the table (or away from it), uses time-duration values in seconds provided by the user and moves the arm fast or slow, at a pre-defined velocity.

e.g., arm_up(0.5) pulls the arm up at some velocity, for 0.5 seconds.

What am I trying to do:

I am trying to control the the position of the arm before it comes to a certain distance from the table (200 mm). That is, it moves more when far and less when near it.

enter image description here

Attempts:

I planned to use a controller to achieve this. First attempt included using a P-controller (P: Proportional) which involved fixing a gain Kp that gets multiplied with the error. I wanted the output of this controller to be in the range 0.1 to 1.0. I tried multiple values of Kp but did not get factor values proportional to the distance to be covered. When I set Kp=0.008, It works well when the error = 500 (mm), and the factor comes out to be = error x Kp, or 500 x 0.008=0.4, but when the error=10mm, factor=10 x 0.008=0.8 which is too below for the actuator to do anything, owing to the fact that all values must be in the range 0.1 to 1.0. Alternatively, setting higher values for Kp (as 0.01), requires me to clamp the output to a fixed value.

Kp = 0.003
if(LIDAR_1 > 200):
                # P Controller
                error = abs(200 - LIDAR_1)
                duration = error * Kp
                # To keep everything < 1.0 
                factor = duration%1.0
                arm_down(factor)

Then, I used the feature scaler to scale the range (given by the lidar) to the desired range (0.1 to 1.0). To filter very high values, I used a mod operator a.k.a % in Python.

if(LIDAR_1 > 200):
                # Using Feature Scaling
                duration = ((LIDAR_1-200)*0.8/800) + 0.2
                # To keep everything < 1.0 
                factor = duration%1.0
                arm_down(factor)

How is the (P) controller not standing up to its task ? Is it not meant to provide a value of Kp that satisfy all the cases (arm’s distant or close encounters)

One Answer

How is the (P) controller not standing up to its task ?

Well, just like you said - how is it not standing up to its task? What is it doing that makes you think it's not working? You said,

I tried multiple values of Kp but could not succeed

Nobody here knows what that means. "Could not succeed" could be a lot of problems. My guess is that you're trying to regulate something with only a proportional controller. Integral gains are the only way to drive steady-state error to zero.

What are some other things you could be doing wrong? Well, for starters, you said:

I am trying to control the the position of the arm [so]... it moves more when far and less when near [the table].

This sounds like you want a signed error, to drive your arm in two directions, yet your code you provided has error calculated as:

error = abs(200 - LIDAR_1)

If your error only has one sign (positive) then your arm only moves in one direction. Also, your error is calculated only with LIDAR_1, even though your entry into that calculation depends on LIDAR_1 and LIDAR_2. Are you sure that you don't want something like

error = LIDAR_2 - LIDAR1

or something similar? You haven't provided any diagrams showing what your values are, what the significance of 200 is, what angle it is you're trying to control, or how you're calculating that angle.

Next, following your code all the way through:

error = abs(200 - LIDAR_1)
duration = error * Kp
# To keep everything < 1.0 
factor = factor%1.0
arm_down(factor)

Let's look at your code line-by-line:

  1. Calculate the (absolute value of an) error,
  2. Modify the error with a proportional gain to make a "duration,"
  3. Modify a "factor,"
  4. Use the factor to run arm_down.

Note: At no point in there did you use the duration. Maybe you meant factor = duration % 1.0?

But, finally, modulus is not your friend. This is definitely NOT what you want for it to be doing.

On the topic of the modulus, you said

to scale the range (given by the lidar) to the desired range (0.1 to 5.0). To filter very high values, I used a mod operator a.k.a % in Python.

First, you say that you want the desired range to be 0.1 to 5.0, but you're doing value % 1.0, so you're only going to get numbers between 0 and 0.999.

Second, you're making your control signal "wrap." Assuming you actually did value % 5.0, which I think is what you were intending given your stated desired range, then you get the following:

4.8 % 5.0 = 4.8
4.9 % 5.0 = 4.9
5.0 % 5.0 = 0
5.1 % 5.0 = 0.1
5.2 % 5.0 = 0.2

If you think of this like a cruise-control system, a very fast acceleration would have you push the pedal all the way to the floor, but if you wanted to accelerate even faster then your modulus operation actually has the controller take its foot completely off the pedal.

What you need instead is to clamp the value, like

if(duration > 5.0)
    duration = 5.0

The best thing you can do for us, and yourself, is to make a drawing that shows where your lidar units are, what measurement you're expecting from them, and how those measurements relate to an angle you're trying to control.

You should then calculate that angle, using the diagram as a guide for developing the equation, and use the angle instead of raw lidar readings in your code.

Finally, structurally speaking, your PID/controller code should accept the angle/error and use that to calculate a raw control signal. If you have some downstream process that needs it to be in a particular range, then you can modify/saturate/clamp that signal inside that downstream process. This keeps your code more modular and easier to troubleshoot.

Answered by Chuck on October 26, 2020

Add your own answers!

Related Questions

Ask a Question

Get help from others!

© 2022 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir