運指の数孊線圢2次制埡

数孊者プログラマヌの生掻の䞭で数時間、たたはりィキペディアを読む


たず、 ロックンロヌルナヌドを゚ピグラフずしお匕甚したす 。
-こんにちは、私の名前はusernameであり、そこで䜕が起こっおいるのかを理解するために、シグマ衚蚘の金額を玙に密かに公開したす。
-こんにちは、username


ですから、前回の蚘事で述べたように、数孊を恐れるパニックな生埒がいたすが、趣味ずしおはんだごおを遞び、今ではセグりェむカヌトを組み立おたいず思っおいたす。 圌らはそれを集めたしたが、圌女はバランスを保ちたくありたせん。 圌らはPIDコントロヌラヌを䜿甚するこずを考えたしたが、うたく機胜するように係数を遞択できたせんでした。 アドバむスを求めに来おください。 しかし、制埡理論では䞀般的にブヌムブヌムに近づきたせんでした。 しかし、ハブで䞀床、線圢二次レギュレヌタが著者を助けたが、pidは圹に立たなかったずいう蚘事を芋たした 。

それでも指にPIDがあるず想像するず ここに私の蚘事がありたすが、これはある皮の時蚈ぞの恐怖に転じたものです、他の制埡方法に぀いおも聞いおいたせんでした。 したがっお、私のタスクは、線圢2次レギュレヌタが䜕であるかを想像するこずですそしお、同時に孊生に説明したす。 これたでのずころ、鉄を䜿った仕事はありたせん。文孊を䜿っお仕事をする方法を瀺したす。これが私の仕事の倧郚分を占めるからです。

私の䜜品に぀いおの露出䞻矩がなくなったので、ここに私の職堎がありたすクリック可胜


䜿甚した゜ヌス


それで、私が最初にするこずは、 りィキペディアに行くこずです。 ロシアのりィキペディアは残酷で容赊ないので、私たちは英語のテキストのみを読みたす。 圌も嫌なのですが、ただそうではありたせん。 だから、読んだ。 すべおの入門テキストブリックのうち、私に興味を持っおいるフレヌズは1぀だけです。
最適制埡の理論は、動的システムを最小コストで運甚するこずに関するものです。 システムダむナミクスが䞀連の線圢埮分方皋匏で蚘述され、コストが2次関数で蚘述される堎合は、LQ問題ず呌ばれたす。


ロシア語に翻蚳するず、圌らは埮分方皋匏ある恐怖によっお特定の動的システムをモデル化し、制埡を盎接遞択しお、ある皮の2次関数を最小化するず蚀いたすああ最小二乗近䌌を感じたす。 いいね さらに読み蟌もう

有限地平線、連続時間LQR、
[䞀連のひどい数匏]


私たちはそれをスキップしたす、それは沌でのそのような読み取りです、さらに、あなたの手で連続的な機胜を考慮するこずは明らかにうんざりするでしょう。

無限の地平線、連続時間LQR、
[さらに恐ろしい匏のシリヌズ]


1時間ごずは簡単ではなく、䞍適切な積分がなくなったため、スキップするず、突然さらに興味深いものが芋぀かりたす。

有限時間、離散時間LQR


ああ、それが倧奜きです。 離散システムがあり、䞀定の間隔最初の読み取りの䞀郚の間隔は垞に1秒に等しいで状態を調べたす。 方皋匏の導関数はなくなりたした。なぜなら、 珟圚、x_ {k + 1} -x_ {l}/ 1秒ずしお近䌌できたす。 ここで、x_kが䜕であるかを理解しおおくずいいでしょう。

䞀次元の䟋


ファむンマンは、すべおの方皋匏をどのように読むか、圌がしなければならないこずを正確に曞いた。
実際、私の掚枬には䞀定量の本物の品質がありたした。 誰かが説明しおいるずきに今日も䜿っおいるスキヌムがありたした
私が理解しようずしおいるこず私は䟋を䜜り続けおいたす。 䟋えば、数孊者は玠晎らしい定理を持ち蟌み、圌らは皆興奮しおいたす。 定理の条件を教えおくれるので、すべおの条件に合うものを構築したす。 セット1぀のボヌル-バラバラ2぀のボヌルがありたす。 それから、ボヌルは私の頭の䞭で色を倉えたり、髪の毛などを成長させたりしたす。 最埌に圌らは定理を述べおいたす。これは私の毛むくじゃらの緑色のボヌルの事には圓おはたらないボヌルに぀いおの銬鹿げたこずです。


たあ、私たちはファむンマンよりもクヌルですか 個人的にはそうではありたせん。 それではこれをやろう。 ある初速床で走行しおいる車がありたす。 タスクは、特定の最終速床たで加速するこずですが、圱響を䞎えるこずができるのは、アクセルペダルたたは車の加速だけです。

車が完璧で、この法則に埓っお動くず想像しおみたしょう。


x_kは1秒あたりの車の速床k、u_kは必芁なアクセルペダルの䜍眮です。1秒あたりの加速床kずしお解釈できたす。 合蚈で、特定の速床x_0で開始し、次にそのような数倀積分を実行したすどの単語に入ったのか。 m / sおよびm / s ^ 2を远加しないこずに泚意しおください。u_kには、枬定間隔の1秒が乗算されたす。 デフォルトでは、すべおの係数が0たたは1のいずれかです。

それで、䜕が起こっおいるのかを理解するために、私はこの皮のコヌドを曞いおい たす 私は曞いた盎埌に捚おる1回限りのコヌドをたくさん曞いおいたす。 念のためここにリストしたすが、い぀ものように、 OpenNLを䜿甚しお倧芏暡なスパヌス線圢方皋匏を解きたす。

非衚瀺のテキスト
#include <iostream> #include "OpenNL_psm.h" int main() { const int N = 60; const double xN = 2.3; const double x0 = .5; const double hard_penalty = 100.; nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, N*2); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); nlBegin(NL_ROW); // x0 = x0 nlCoefficient(0, 1); nlRightHandSide(x0); nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); // xN = xN nlCoefficient((N-1)*2, 1); nlRightHandSide(xN); nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); // uN = 0, for convenience, normally uN is not defined nlCoefficient((N-1)*2+1, 1); nlScaleRow(hard_penalty); nlEnd(NL_ROW); for (int i=0; i<N-1; i++) { nlBegin(NL_ROW); // x{i+1} = xi + ui nlCoefficient((i+1)*2 , -1); nlCoefficient((i )*2 , 1); nlCoefficient((i )*2+1, 1); nlScaleRow(hard_penalty); nlEnd(NL_ROW); } for (int i=0; i<N; i++) { nlBegin(NL_ROW); // xi = xN, soft nlCoefficient(i*2, 1); nlRightHandSide(xN); nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); nlSolve(); for (int i=0; i<N; i++) { std::cout << nlGetVariable(i*2) << " " << nlGetVariable(i*2+1) << std::endl; } nlDeleteContext(nlGetCurrent()); return 0; } 


だから、私がやっおいるこずを理解したしょう。 はじめに、N = 60ず蚀いたす。すべおに60秒かかりたす。 それから私は、最終速床は毎秒2.3メヌトル、最初の毎秒0.5メヌトルであるべきだず蚀いたす。これはブルドヌザヌから蚭定されたす。 60 * 2の倉数-60の速床倀ず60の加速床倀厳密に蚀えば、59の加速床があるはずですが、60があり、最埌は厳密に0であるず蚀う方が簡単です。

合蚈、2 * N個の倉数N = 60があり、偶数の倉数通垞のプログラマヌのようにれロからカりントを開始は速床であり、奇数の倉数は加速です。 これらの行で初期速床ず最終速床を蚭定したす。
実際、私は初期速床をx0.5m / sに、そしお最終的な-xN2.3m / sにしたいず蚀った。
  nlBegin(NL_ROW); // x0 = x0 nlCoefficient(0, 1); nlRightHandSide(x0); nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); // xN = xN nlCoefficient((N-1)*2, 1); nlRightHandSide(xN); nlScaleRow(hard_penalty); nlEnd(NL_ROW); 


x {i + 1} = xi + uiであるこずがわかっおいるので、システムにN-1個のそのような方皋匏を远加したしょう。

  for (int i=0; i<N-1; i++) { nlBegin(NL_ROW); // x{i+1} = xi + ui nlCoefficient((i+1)*2 , -1); nlCoefficient((i )*2 , 1); nlCoefficient((i )*2+1, 1); nlScaleRow(hard_penalty); nlEnd(NL_ROW); } 


それで、私たちはすべおの厳しい制限をシステムに远加したした、そしお実際、正確に最適化したいものは䜕ですか x_iをできるだけ早く最終速床xNに到達させたいず蚀っお始めたしょう。

  for (int i=0; i<N; i++) { nlBegin(NL_ROW); // xi = xN, soft nlCoefficient(i*2, 1); nlRightHandSide(xN); nlEnd(NL_ROW); } 


さお、システムの準備ができおおり、状態間の遷移に関する厳密なルヌルが蚭定されおいたす。システムの品質の2次関数も蚭定されおいたす。ボックスを振っお、最小二乗が解x_i、u_iずしお䞎えられるこずを確認したしょう赀い線は速床、緑は加速床です



Oookey、実際には毎秒0.5メヌトルから毎秒3のコンマである2メヌトルに加速したしたが、私たちのシステムは過床に加速したしたできるだけ早く収束するこずを芁求したため、これは論理的です。

そしお、最小の加速を求める最速の収束ではなく、目的関数を倉曎したしょう ここではcommitしたす 

  for (int i=0; i<N; i++) { nlBegin(NL_ROW); // ui = 0, soft nlCoefficient(i*2+1, 1); nlEnd(NL_ROW); } 




うヌん、今では車は1分間に毎秒2メヌトル加速しおいたす。 では、最終的な速床にすばやく収束させお、少し加速しおみたしょう ここがコミットです。

  for (int i=0; i<N; i++) { nlBegin(NL_ROW); // ui = 0, soft nlCoefficient(i*2+1, 1); nlEnd(NL_ROW); nlBegin(NL_ROW); // xi = xN, soft nlCoefficient(i*2, 1); nlRightHandSide(xN); nlEnd(NL_ROW); } 


うん、すごい、今は矎しくなっおいる



したがっお、制埡の倧きさの高速収束ず制限は、もちろん、競合する目暙です。 Wikipediaの段萜の最初の行で停止した時点で、ひどい数匏があり、それらは理解できたせん。 倚くの堎合、蚘事を読むこずは、キヌワヌドを怜玢し、私が個人的に所有しおいるのず同じデバむスを䜿甚しおすべおの結果を完党に衚瀺するこずになりたす。

では、珟時点では䜕がありたすか システムの初期状態+システムの最終状態+秒数を持぀こずにより、理想的な制埡u_iを芋぀けるこずができたす。 これは、セグりェむがあたり適切でない堎合にのみ有効です。 くそヌ、どうやっおそれをやるの したがっお、Wikipediaで次のテキストを読んでください。

次のように定矩されたパフォヌマンスむンデックス



パフォヌマンスむンデックスを最小化する最適な制埡シヌケンスは、



ここで[次は䜕ですか]


だから 「J = ...」ずいう匏の等号の埌はわかりたせんが、これは明らかに2次関数です。 目暙ぞの迅速な収束ず最小コストのように、埌で詳しく芋おいきたす。これで理解は十分です。

u_k = -F x_k。 おっず。 圌らは、私たちの1次元の䟋では、い぀でも最適な加速床は定数-Fに珟圚の速床を掛けたものであるず蚀っおいたす。 さあ、さあ。 しかし、真実は、緑ず赀のグラフィックが互いに疑わしいほど䌌おいるずいうこずです

1Dの䟋で実際の方皋匏を曞いおみたしょう。

そのため、品質管理機胜がありたす。



車の速床の隣接する倀の間の接続の制限を芳察しながら、それを最小化したい



ストップ-ストップ-ストップですが、りィキペディアのx_k ^ TQ x_kは䞀䜓䜕ですか 結局のずころ、これは単玔なx_k ^ 2であり、x_k-x_N^ 2 モミの朚、しかし圌らは我々が入りたいず思う最終状態はれロベクトルだず仮定したす!!! [怜閲枈み]これに぀いおは、WIKIPEDIA党䜓のペヌゞに単語がありたすか

さお、深く呌吞し、萜ち着いおください。 ここで、制限がないように、u_iを介しおJの定匏化ですべおのx_iを衚珟したす。 これで、制埡ベクトルのみが倉数になりたす。 そのため、次のように蚘述された関数Jを最小化したす。



぀たずく。 ブラケットを開きたしょう゚ピグラフを参照



ここの省略蚘号は、u_0から独立しおいるかすを意味したす。 最小倀を探しおいるので、それを芋぀けるために、すべおの偏埮分をれロに蚭定する必芁がありたすが、最初はu_0に関する偏埮分に興味がありたす。



合蚈するず、u_0に次の匏がある堎合にのみ最適な制埡が最適になるこずがわかりたす。



この匏には他の䞍明なu_iも含たれたすが、「but」が1぀あるこずに泚意しおください。 冗談は、車が毎分2メヌトルしか加速しないようにするこずです。 私が圌女に䞎えた分は、故意に十分な時間のようでした。 そしお、私は1時間を䞎えるこずができたす。 u_iに䟝存する甚語は、倱瀌な堎合、すべお加速の仕事であり、Nに䟝存したせん。 したがっお、Nが十分に倧きい堎合、最適なu_0は最終䜍眮からx0がどれだけ離れおいるかにのみ線圢的に䟝存したす。

぀たり、制埡は次のようになりたす。システムをモデル化し、u_iずx_iを線圢に接続するマゞック係数を芋぀けお蚘述し、ロボットで、芋぀かったマゞック係数を䜿甚しお線圢比䟋コントロヌラヌを䜜成したす。


非垞に正盎に蚀うず、この時点たではもちろん、コヌドを曞くこずはしたせんでした。私は心の䞭で䞊蚘のすべおを行い、䞀枚の玙に少し曞きたした。 しかし、これは私が䞀床だけ倚くのコヌドを曞くずいう事実を吊定するものではありたせん。

2Dの䟋



盎芳ずしお、これは玠晎らしいですが、 ここに私が実際に曞いた最初のコヌドがありたす 
非衚瀺のテキスト
 #include <iostream> #include <vector> #include "OpenNL_psm.h" int main() { const int N = 60; const double x0 = 3.1; const double v0 = .5; const double hard_penalty = 100.; const double rho = 16.; nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, N*3); nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); nlBegin(NL_SYSTEM); nlBegin(NL_MATRIX); nlBegin(NL_ROW); nlCoefficient(0, 1); // x0 = 3.1 nlRightHandSide(x0); nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); nlCoefficient(1, 1); // v0 = .5 nlRightHandSide(v0); nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); nlCoefficient((N-1)*3, 1); // xN = 0 nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); nlCoefficient((N-1)*3+1, 1); // vN = 0 nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); // uN = 0, for convenience, normally uN is not defined nlCoefficient((N-1)*3+2, 1); nlScaleRow(hard_penalty); nlEnd(NL_ROW); for (int i=0; i<N-1; i++) { nlBegin(NL_ROW); // x{N+1} = xN + vN nlCoefficient((i+1)*3 , -1); nlCoefficient((i )*3 , 1); nlCoefficient((i )*3+1, 1); nlScaleRow(hard_penalty); nlEnd(NL_ROW); nlBegin(NL_ROW); // v{N+1} = vN + uN nlCoefficient((i+1)*3+1, -1); nlCoefficient((i )*3+1, 1); nlCoefficient((i )*3+2, 1); nlScaleRow(hard_penalty); nlEnd(NL_ROW); } for (int i=0; i<N; i++) { nlBegin(NL_ROW); // xi = 0, soft nlCoefficient(i*3, 1); nlEnd(NL_ROW); nlBegin(NL_ROW); // vi = 0, soft nlCoefficient(i*3+1, 1); nlEnd(NL_ROW); nlBegin(NL_ROW); // ui = 0, soft nlCoefficient(i*3+2, 1); nlScaleRow(rho); nlEnd(NL_ROW); } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); nlSolve(); std::vector<double> solution; for (int i=0; i<3*N; i++) { solution.push_back(nlGetVariable(i)); } nlDeleteContext(nlGetCurrent()); for (int i=0; i<N; i++) { for (int j=0; j<3; j++) { std::cout << solution[i*3+j] << " "; } std::cout << std::endl; } return 0; } 



ここではすべおが同じで、システム倉数のみが2぀になりたした。速床だけでなく、マシンの座暙も2぀です。
したがっお、初期䜍眮+初期速床x0、v0が䞎えられるず、最終䜍眮0,0に到達し、原点で停止する必芁がありたす。
ある瞬間から次の瞬間ぞの遷移は、x_ {k + 1} = x_k + v_k、およびv_ {k + 1} = v_k + u_kずしお実行されたす。

私は以前のコヌドに぀いお十分にコメントしたしたが、これは問題を匕き起こさないはずです。 䜜業の結果は次のずおりです。



赀い線は座暙、緑は速床、青はアクセルペダルの䜍眮です。 前のものに基づいお、青い曲線は赀ず緑の加重和であるず想定されたす。 うヌん、そうですか 数えおみよう
぀たり、理論的には、u_i = a * x_i + b * v_iのような2぀の数倀aずbを芋぀ける必芁がありたす。 そしお、これは前回の蚘事で行った線圢回垰にすぎたせん これがコヌドです。

その䞭で、最初に䞊の図にある曲線を怜蚎し、次に青い曲線= a *èµ€+ b *緑になるようにaずbを探したす。

ここに、実際のu_iず、緑ず赀の線を折りたたんで埗たものずの違いを瀺したす。


1秒あたり1秒あたり100分の1メヌトルのオヌダヌの偏差 かっこいい!!! 私が匕甚したコミットは、a = -0.0513868、b = -0.347324を提䟛したす。 偏差は本圓に小さいですが、これは正垞です。初期デヌタは倉曎したせんでした。

それでは 、マシンの初期䜍眮ず速床を根本的に倉曎しお、以前の蚈算からマゞック番号aずbを残しおみたしょう。

この最適な゜リュヌションず、最も愚かな手順で埗られるものずの違いを次に瀺したす。もう䞀床完党に説明したす。
  double xi = x0; double vi = v0; for (int i=0; i<N; i++) { double ui = xi*a + vi*b; xi = xi + vi; vi = vi + ui; std::cout << (ui-solution[i*3+2]) << std::endl; } 




りィキペディアが提䟛しおくれたリカッチ埮分方皋匏はありたせん。 私も圌らに぀いお読む必芁があるかもしれたせんが、圌らが料理するずき、それは埌でありたす。 それたでの間、単玔な2次関数は私を完党に満足させたす。

也燥残枣



合蚈これを䜿甚するには、䞻に2぀の困難がありたす。
a良奜な遷移行列AおよびBを芋぀けたす。もちろん、すべおがオブゞェクトや他のものの質量に䟝存するため、運動方皋匏を蚘述する必芁がありたす。
b目暙ぞの最速の収束の目暙間の適切な劥協係数を芋぀けたすが、同時に䜙分な努力をするこずはありたせん。

aずbが完了するず、メ゜ッドは有望に芋えたす。 唯䞀のこずは、システムの状態に関する完党な知識を必芁ずするこずであり、垞に機胜するずは限りたせん。 たずえば、セグりェむの䜍眮はわかりたせん。ゞャむロスコヌプや加速床蚈などのセンサヌのデヌタに基づいお掚枬するこずしかできたせん。 ええ、これはそれに぀いおです。次回は生埒に教えたす。

だから、私は3぀の目暙を達成したかった
alqrずは䜕かを理解する
b私が理解したこずを生埒ずあなたに説明する
cあなたず私の生埒に、私ほずんどの人がそうであるように数孊のテキストでは気の毒なこずを理解しおいないこずを瀺したす。 私たちは、しがみ぀くキヌワヌドを探し、冗長で䞍必芁な方法ず抜象化を捚お、珟圚の知識の範囲内に抌し蟌もうずしおいたす。

私は成功したず思いたす。 繰り返しになりたすが、私は制埡理論の専門家ではありたせん。補足や修正が必芁な堎合は、恥ずかしがらないでください。

お楜しみください

Source: https://habr.com/ru/post/J277671/


All Articles