工作筆記 程式組
今天是從介紹積分( integral )開始,在第一次的試驗當中(ki = 0.5),因為一開始距離 setpoint (10 feet) 較遠,也因此 error 較大,而加在一起時 errorsum 就會超大所以馬達輸出的馬力也超大,導致機器人衝過頭。
接著在嘗試後,它設定了 integral limit,也就是只有距離在 setpoint 固定的範圍內,它才會開始計算 Integral Output。而在設定這個距離時也要注意,機器人若是無法達到此範圍內而開始停住的話,就沒有積分( integral )協助它慢慢地抵達 setpoint,而當然這個 limit 的數字越小越好。
\[ Integral Output = kI × errorSum \]
\[ Derivative Output = KD × errorRate \]
\[ Motor Output = kp × error + kI × errorSum + KD × errorRate\]
\[ Output(t) = kp × e(t) +ki × \int_{0}^{t}e(t)dt + kd × \dfrac{d}{dt} e(t)\]
在最後是介紹 Derivative term,好像就是試試而已我覺得沒什麼…
我好像覺得這個比較沒什麼用…,感覺就只是輔助用而已,就類似預測下一個瞬間醬
package frc.robot;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonFX;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class Robot extends TimedRobot {
private WPI_TalonFX leftMotor1 = new WPI_TalonFX(1);
private WPI_TalonFX leftMotor2 = new WPI_TalonFX(2);
private WPI_TalonFX rightMotor1 = new WPI_TalonFX(3);
private WPI_TalonFX rightMotor2 = new WPI_TalonFX(4);
private Joystick js1 = new Joystick(0);
@Override
public void robotInit() {
}
@Override
public void robotPeriodic() {
}
@Override
public void autonomousInit() {
encorder.reset();
setpoint = 0;
lastError = 0;
lasteTimestamp = Timer.getFPGATimestamp();
}
final double kP = 0.5;
final double kI = 0.5
final double kD = 0.1;
final double iLimit = 1;
double setpoint = 0;
double errorSum = 0;
double lasteTimestamp = 0;
double lastError = 0;
@Override
public void autonomousPeriodic() {
if(js1.getRawButton(1)) setpoint = 10;
else if(js1.getRawButton(2)) setpoint = 0;
// get sensor position
double sensorPosition = encoder.get() * kDriveTick2Feet;
// calcculation
double error = setpoint - sensorPosition;
double dt = Timer.getFPGATimestamp() - lasteTimestamp;
if(Math.abs(error)<iLimit) errorSum += error * dt;
double errorRate = (error - lastError) / dt;
double outputSpees = kP * error + kI * errorSum + kD * errorRate;
// output to motors
leftMotor1.set(outputSpeed);
leftMotor2.set(outputSpeed);
rightMotor1.set(-outputSpeed);
rightMotor2.set(-outputSpeed);
// update last var
lasteTimestamp = Timer.getFPGATimestamp();
lastError = error;
}
@Override
public void teleopInit() {
}
@Override
public void teleopPeriodic() {
}
@Override
public void disabledInit() {
}
@Override
public void disabledPeriodic() {
}
@Override
public void testInit() {
}
@Override
public void testPeriodic() {
}
}
這次的影片主要是在介紹PID系統裡面的Integral term(積分項)和Derivative term(導數項)
因為這次的影片算是稍微將PID系統做離一個段落,因此我就順便都打出來吧(●'◡'●)
1.Proprotional Term
。前提:
-希望利用Proprotional term(比例項)來讓機器人停留在10 M(可更改)的位置
。公式:
-Output(電機輸出) = Kp(常數) * Error(目前位置距離目標位置的差值)
。解釋:
-將一常數去乘上一個會隨著移動更改的變數項,在藉由此結果來產生越接近設定位置速度會越來越低的效果
。問題:
-單單只使用Proprotional term(比例項)無法精準的停留在10 M這個位置,影片中測試了幾次後找出最適合那台機器的Kp值是0.5(不適用於其他機器人),要是將0.5套用在上面的公式中會出現非常接近10 M但還是無即時停止並修正的狀況(見下圖)
⇂ Proprotional term最佳效果圖
2.Integral term
。前提:
-由於單單只使用Proprotional Term無法達到精準停留在10 M(可更改)上,因此想加上Integral term(積分項)來針對無法準確停留在10 M做處理
。公式:
-Output = Kp * Error + Ki(常數) * erroeSum(誤差值過去一段時間的和,也就是誤差和)
。解釋:
-考慮到過去的誤差,將(誤差和)乘以一個的常數。一個簡單的比例系統會前後調整,因此會在預定值的附近來回變化。通過加上負的誤差值,系統誤差值就會漸漸減少。所以,最終這個PID迴路系統會在應該會在預設值穩定下來。
。問題
-藉由Proprotional Term和Integral term的共同作用,此機器人已經得到精準停在10 M上的能力(當Ki = 0.5時),但是還是出現了另一個問題:在達到10 M前會有一段爆衝(?)的這個狀況(見下圖)
⇂ Proprotional Term和Integral term最佳效果圖
2-1.Integral Limit
。用途:
-利用i-Limit值來降低爆衝的量
⇂ 加上i-Limit前後的比較圖
3.Derivative term
。前提:
-雖然Proprotional Term和Integral term已經能夠做到精準停留在10 M上,但是因為在到達前會有一段衝過頭的狀況,所以想藉由Derivative term(導數項)來解決衝過頭這個問題
。公式:
-Output = Kp * Error + Ki * erroeSum + Kd(常數) * ErorRate(類似預測將來的一個值?)
。解釋:
-導數項是類似於考慮將來誤差,計算誤差的一種…東西(?)。這個導數的控制會對系統的改變作出反應。導數的結果越大,那麼控制系統就對輸出結果作出更快速的反應。
。結果
-成功達到了精準在10 M停下來(Kd = 0.1)且不會有過衝的情形(見下圖)
⇂ PID系統最佳效果圖
看完這周的影片,相較於上周只有kP控制馬達輸出,這周多出了kI跟kD兩個,kI是利用多一個變數errorSum去讓接近10feet的時候能更小的馬達輸出,kD則是多一個errorRate,讓機器人在接近10feet時自動縮小馬達輸出。三個kP、kI、kD一起運作起來才是真正的PID控制以後也可以看情況用,不一定每次都要用kP、kI、kD,可以用kP+kI或kP一個就好,看情況。
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing