संचय पर एकीकरण क्यों?


14

मैं DIY भौतिक विज्ञान के बारे में जानने के लिए शुरू कर रहा हूँ, और मैं सबसे बुनियादी स्तर पर एकीकरण को लागू करने के बारे में एक सवाल (यानी यह है है नहीं एक यूलर बनाम RK4 प्रश्न)।

मेरे द्वारा दिए गए लगभग हर उदाहरण में कुछ integrate()फ़ंक्शन होते हैं जो अंतिम अपडेट के बाद टाइमस्टेप प्राप्त करते हैं, और अंतिम अपडेट के बाद से त्वरण (और / या वेग और / या स्थिति) को अपडेट करते हैं।

सबसे सरल रूप में: position += velocity * deltaTime

हालाँकि, मुझे समझ में नहीं आता है कि जब यह किसी फ़ंक्शन को बदलकर आसानी से प्राप्त किया जा सकता है तो यह इस तरह क्यों जमा होता है । उदाहरण के लिए: getPosition = makeNewFunction()जो कुछ हस्ताक्षर कर सकता है, उस पर हस्ताक्षर कर सकता है Time -> Position, और उस फ़ंक्शन के आंतरिक कामकाज को उपयुक्त गणितीय सूत्र के माध्यम से उत्पन्न किया जाता है।

इस तरह, कोई संचय नहीं है ... जब भी स्थिति को प्राप्त करने की आवश्यकता होती है, तो वह उस फ़ंक्शन को वर्तमान समय के साथ कॉल करता है।

मेरी नौसिखिया समझ यह है कि यह उन त्रुटियों से भी बचना होगा जो संचय से आती हैं ... इसलिए यह काम क्यों नहीं करता है, मैं क्या याद कर रहा हूं?

(fwiw मैं था एक साथ इस विचार है की अवधारणा का मूल प्रमाण डाल यह भी एक ही समय में कुछ अन्य बातें परीक्षण है, हालांकि, तो यह साफ उदाहरण नहीं है: https://github.com/dakom/ball-bounce-frp )

EDIT 1: जैसा कि टिप्पणियों में बताया गया है, यह इंगित करना महत्वपूर्ण है कि मैंने अभी तक त्वरण को बदलने के बारे में नहीं सीखा है, या झटके और अन्य चीजों से निपटना है जो निरंतर त्वरण की तुलना में उच्च-क्रम एकीकरण की आवश्यकता होती है।

EDIT 2: यहाँ विचार का कुछ मूल नमूना कोड है, और छद्म जावास्क्रिप्ट सिंटैक्स - ध्यान दें कि getKinematicPositionइसे आंशिक रूप से लागू किया गया है, इसलिए यह सिर्फ समय -> स्थिति का एक नया कार्य लौटा रहा है:

मैं यहाँ स्थिति के लिए चिपका रहा हूँ, लेकिन यह कुछ और हो सकता है, जैसे getVelocity, मुझे लगता है ...

getKinematicPosition = initialVelocity => acceleration => time => 
  ((.5 *acceleration) * (time * time)) + (initialVelocity * time);

getPosition = getKinematicPosition ([0,0,0]) (GRAVITY);

onTick = totalTime => {
   position = getPosition (totalTime);
   onCollision = () => {
     getPosition = changeTheFunction(totalTime);
     //changeTheFunction uses totalTime to base updates from 0
     //it could use getKinematicPosition or something else entirely
   }
}

1
यदि आपके पास निरंतर गति / त्वरण नहीं है तो आपका कार्य क्या होगा?
लिनिथ

मुझे पता नहीं है! : D यदि वह कारण है - उदाहरण के लिए, मैं अभी तक त्वरण बदलने के लिए नहीं मिला है, मैं वास्तव में इस जवाब के रूप में टूट जाएगा जहां एक फुलर स्पष्टीकरण की सराहना करेंगे (अन्यथा मैं इस कार्यात्मक सड़क नीचे जा सकते हैं और एक मृत अंत मारा !)
डेविदकोमर

6
ठीक है अगर आपकी वस्तु सिर्फ एक सर्कल में घूमती है, तो निश्चित रूप से ... क्या होगा जब यह एक बॉक्स है जो खिलाड़ी को धक्का दे रहा है? जब आप getPosition (अब + 100) को कॉल करते हैं, तो क्या यह भविष्य को जानने के लिए भविष्यवाणी करता है कि खिलाड़ी इसे धक्का देना कब बंद करेगा? जब आप getPosition (अब -१०००) को कॉल करते हैं तो क्या उसे अतीत को याद रखना पड़ता है?
user253751

जवाबों:


34

... उस फ़ंक्शन के आंतरिक कामकाज उचित गणितीय सूत्र के माध्यम से उत्पन्न होते हैं ...

यह समस्याओं के कुछ वर्गों के लिए काम करेगा, और खोज करने के लिए महत्वपूर्ण वाक्यांश एक बंद-रूप समाधान है। उदाहरण के लिए, कार्बल स्पेस प्रोग्राम में, कक्षा में एक अंतरिक्ष यान की गति की गणना इस प्रकार की जाती है। दुर्भाग्य से, अधिकांश गैर-तुच्छ समस्याओं (उदाहरण के लिए अंतरिक्ष यान की वायुमंडलीय पुनरावृत्ति) का कोई ज्ञात बंद-रूप समाधान नहीं है। इस प्रकार गणितीय रूप से सरल संख्यात्मक सन्निकटन की आवश्यकता (अर्थात integrate()समय के साथ)।


आह… कमाल! यदि आपके पास एक मिनट है - आप इस कार्यात्मक दृष्टिकोण के लिए लक्ष्य बनाने के बारे में क्या सोचते हैं, और फिर जमा करने पर वापस गिर जाते हैं अगर मैं यह पता नहीं लगा सकता कि इसे कैसे काम किया जाए (जैसे अगर मैं एक गैर-बंद फॉर्म समस्या से निपट रहा हूं या मैं यह पता नहीं लगा सकता कि इसे एक में कैसे बदल दिया जाए)? मुझे कार्य को उत्पन्न करने का विचार पसंद है क्योंकि यह गणित 1: 1 को फिट करता है - लेकिन अगर मैं हमेशा अनिवार्य रूप से एक डेड-एंड
मारूंगा तो

8
@davidkomer आप भी जनरेटिंग फंक्शन क्यों रखना चाहते हैं? यदि आप इसे बंद कर सकते हैं, तो आप केवल पूर्व-गणना कर सकते हैं और पूरे प्रक्षेपवक्र को रिकॉर्ड कर सकते हैं! बेशक, लोग पहले से ही ऐसा करते हैं: इसे एनीमेशन कहा जाता है , और इसकी सूक्ष्मताओं का हिस्सा है।
जोकर_vD

रनटाइम डायनेमिक्स के आधार पर फंक्शन बदल जाते हैं ... उदाहरण के लिए FRP बॉल-बाउंस देखें
davidkomer

वास्तव में मुझे उस उदाहरण को अपडेट करने की आवश्यकता होगी, जैसे कि पॉन्ग की तरह कुछ होना, चलती वस्तुओं के साथ यादृच्छिक रूप से / उपयोगकर्ता द्वारा नियंत्रित ...
davidkomer

10

आपके दृष्टिकोण के साथ समस्या यह है कि आपके पास अपनी वस्तु का इतिहास नहीं है । यदि आप एक दिशा में आगे बढ़ते हैं, तो आप स्थिति की गणना कर सकते हैं, लेकिन क्या होगा यदि आप किसी चीज को मारते हैं और वापस उछालते हैं?
यदि आप अपनी अंतिम ज्ञात स्थिति से जमा होते हैं, तो आप प्रभाव को संभाल सकते हैं और वहां से जा सकते हैं। यदि आप इसे शुरू से गणना करने की कोशिश करते हैं, तो आपको हर बार प्रभाव को फिर से समझना होगा, या इसे नई शुरुआत की स्थिति के रूप में सेट करना होगा।

आपके उदाहरण ने मुझे एक रेसिंग गेम की याद दिला दी। (मुझे नहीं पता कि क्या स्थिति भौतिकी इंजन द्वारा नियंत्रित की जाएगी, लेकिन मुझे लगता है कि यह समझाने के लिए बहुत अच्छा काम करता है)
यदि आप अपनी कार से ड्राइव करते हैं तो आप तेजी और धीमा कर सकते हैं। आप अपनी स्थिति की गणना यह जानकर नहीं कर सकते हैं कि आपकी कार की गति प्रोफ़ाइल शुरू से अब तक कैसी दिखती थी। प्रारंभ से अब तक हर फ्रेम में आपके द्वारा की गई गति को संग्रहीत करने की तुलना में संचय दूरी आसान है।

डिस्क्लेमर: मैंने अब तक गेम भौतिकी नहीं लिखा है, बस यही समस्या है।

संपादित करें:
इस आरेख में आप देख सकते हैं कि समय के साथ मान कैसे बदलते हैं।
लाल = त्वरण (नीचे शुरू करने के लिए तेजी लाने से)
हरा = गति (शुरू करने से रोकने के लिए)
नीला = जिस तरह से आप गए।

कुल गति आपके प्रारंभ बिंदु से आपके वास्तविक लॉग में त्वरण का अभिन्न अंग है। (रेखा और अक्ष के बीच का क्षेत्र)
रास्ता आपकी गति का अभिन्न अंग है।
यदि आप अपने त्वरण के लिए मूल्यों को जानते हैं, तो आप अन्य मूल्यों की गणना कर सकते हैं। लेकिन अगर मैं गलत नहीं हूँ अभिन्न भी पीसी पर संचय द्वारा गणना कर रहे हैं। और यह सभी त्वरण मूल्यों को संग्रहीत करने के लिए अधिक उपरि तरीका है।
साथ ही हर फ्रेम की गणना करना बहुत संभव है।

त्वरण / गति / रास्ता-समय आरेख

मुझे पता है, मेरे रंग कौशल महान हैं। ;)

संपादन 2:
यह उदाहरण रैखिक आंदोलन के लिए है। दिशा निर्देशन इसे और भी कठिन बना देता है।


"या इसे नई शुरुआत की स्थिति के रूप में सेट करें।" - हाँ, लेकिन मैं उस समस्या को नहीं देखता हूं :) पुन: कार का उदाहरण ... मुझे यह महसूस हो रहा है कि मुझे वास्तव में कुछ और जटिल चीजों के साथ खेलना शुरू करना होगा, जैसे कि सहज रूप से यह समझना कि यह विफल कहाँ है .. ।
डेविदकोमर

नई स्थिति सेट करना शायद कोई समस्या नहीं है। मैंने कार भाग को संपादित किया
लिनिथ जूल

1
एक कार गेम में, मुझे लगता है कि त्वरण और भी अधिक जटिल होगा। वहाँ शायद कूदता है और spikes, और यह गति पर निर्भर हो सकता है। (जैसे, कार की गति तेज होने के कारण त्वरण घटकर 0 हो जाता है।)
jpmc26

3
@davidkomer एक कार के साथ भी परेशान नहीं करता है (जब तक आप नहीं चाहते हैं), एक बुनियादी platformer करेगा। सुपर मारियो में mario.getPosition (समय) कैसे काम करता है?
user253751

8

हालाँकि, मुझे समझ में नहीं आता है कि जब यह किसी फ़ंक्शन को बदलकर आसानी से प्राप्त किया जा सकता है तो यह इस तरह क्यों जमा होता है। उदाहरण के लिए: getPosition = makeNewFunction () जो समय -> स्थिति के हस्ताक्षर वाले कुछ लौटा सकता है, और उस फ़ंक्शन के आंतरिक कामकाज उचित गणितीय सूत्र के माध्यम से उत्पन्न होते हैं।

आप ऐसा कर सकते हैं!

इसे एक विश्लेषणात्मक या बंद फॉर्म समाधान का उपयोग करना कहा जाता है । इसका लाभ यह है कि यह अधिक सटीक है, क्योंकि समय के साथ जमा होने वाली त्रुटियां गैर-मौजूद हैं।

हालांकि, यह काम करता है अगर और केवल अगर आप पहले से इस तरह के एक बंद रूप को जानते हैं। खेल के लिए, यह अक्सर बस मामला नहीं है।

खिलाड़ी आंदोलन अनिश्चित है और बस कुछ पूर्व-गणना फ़ंक्शन में नहीं डाला जा सकता है। खिलाड़ी अपने वेग और अभिविन्यास को अक्सर बदल सकता है और बदल सकता है।

एनपीसी संभावित रूप से बंद फॉर्म समाधानों का उपयोग कर सकता है, और वास्तव में वे कभी-कभी करते हैं। हालांकि इसमें कुछ अन्य कमियां भी हैं। एक साधारण रेसिंग गेम के बारे में सोचें। जब भी आपका वाहन किसी अन्य वाहन से टकराता है, आपको अपना कार्य बदलना पड़ता है। हो सकता है कि भूमिगत के आधार पर कार तेजी से आगे बढ़े। फिर इस तरह के बंद-रूप समाधान को खोजना काफी मुश्किल होगा। वास्तव में, ऐसे अधिक मामले होने की संभावना है जहां इस तरह के बंद रूप को खोजना या तो असंभव है या इतना जटिल है कि यह बस संभव नहीं है।

क्लोज-फॉर्म सॉल्यूशन का उपयोग करने का एक शानदार उदाहरण केर्बल स्पेस प्रोग्राम है। जैसे ही आपका रॉकेट कक्षा में है और जोर के तहत नहीं है, केएसपी इसे "रेल पर" डाल सकता है। ऑर्बिट दो-बॉडी सिस्टम में पूर्व-निर्धारित हैं, और आवधिक हैं। जब तक रॉकेट किसी और जोर पर लागू नहीं होता है, आप पहले से ही जानते हैं कि रॉकेट कहां होगा, और आप बस कॉल कर सकते हैं getPositionAtTime(t)(इसका नाम बिल्कुल नहीं है, लेकिन आपको विचार मिलता है)।

व्यवहार में, हालांकि, केवल चरण-दर-चरण एकीकरण का उपयोग करना अक्सर अधिक व्यावहारिक होता है। लेकिन जब आप ऐसी स्थिति देखते हैं जहां एक बंद-रूप समाधान मौजूद होता है और गणना करना आसान होता है, तो इसके लिए जाएं! इसका उपयोग करने का कोई कारण नहीं है।

उदाहरण के लिए, यदि आपका पात्र तोप का निशाना बना रहा है, तो आप बंद फॉर्म के समाधान का उपयोग करके आसानी से तोप के गोले के पूर्वानुमानित प्रभाव को दिखा सकते हैं। और, यदि आपका गेम तोप के गोले को बदलने के लिए अनुमति नहीं देता है (उदाहरण के लिए कोई हवा नहीं), तो आप इसे तोप के गोले को हिलाने के लिए भी इस्तेमाल कर सकते हैं। ध्यान दें कि आपको अपनी तोप की गेंद के रास्ते में आने वाली बाधाओं का विशेष ध्यान रखने की जरूरत है।

इसी तरह की बहुत सारी स्थितियां हैं। यदि आप एक राउंड-आधारित गेम का निर्माण कर रहे हैं, तो कहीं अधिक क्लोज-फॉर्म सॉल्यूशंस उपलब्ध होने की संभावना है, तब आरटीएस गेम का निर्माण करते समय, क्योंकि आप पहले से सभी मापदंडों को जानते हैं और निश्चितता के साथ कह सकते हैं कि वे नहीं बदलते हैं (कुछ भी अचानक नहीं चलता है) उस रास्ते में, उदाहरण के लिए)।

ध्यान दें कि चरणबद्ध एकीकरण की संख्यात्मक अशुद्धियों का मुकाबला करने की तकनीकें हैं। उदाहरण के लिए, आप संचित त्रुटि का ट्रैक रख सकते हैं और त्रुटि को रोककर रखने के लिए सुधारात्मक शब्द लगा सकते हैं, जैसे कहन समन


8

बस एक साधारण बाउंसिंग गेंद के मामले में, बंद फॉर्म समाधान के साथ आना आसान है। हालाँकि, अधिक जटिल प्रणालियों के लिए एक साधारण अंतर समीकरण (ODE) को हल करने की आवश्यकता होती है। संख्यात्मक सॉल्वर को सभी लेकिन सरलतम मामलों को संभालने की आवश्यकता होती है।

वास्तव में संख्यात्मक ODE सॉल्वर की दो कक्षाएं हैं: स्पष्ट और अंतर्निहित। स्पष्ट सॉल्वर आपके अगले राज्य के लिए एक बंद रूप सन्निकटन प्रदान करते हैं, जबकि निहित सॉल्वर को ऐसा करने के लिए एक समीकरण को हल करने की आवश्यकता होती है। आप अपनी उछलती गेंद के लिए जो वर्णन करते हैं, वह वास्तव में एक अंतर्निहित ODE सॉल्वर है, चाहे आप इसे जानते हों या नहीं!

इंप्लाट सॉल्वर के पास अधिक बड़े समय चरणों का उपयोग करने में सक्षम होने का लाभ है। आपके बाउंसिंग बॉल एल्गोरिथ्म के लिए, आपका टाइमस्टेप कम से कम अवधि तक बड़ा हो सकता है जब तक कि अगली टक्कर (जो आपके फ़ंक्शन को बदल देगा)। इससे आपका प्रोग्राम बहुत तेजी से चल सकता है। हालाँकि, सामान्य तौर पर, हम हमेशा ODE के लिए अच्छे निहित समाधान नहीं खोज सकते हैं जिसमें हम रुचि रखते हैं। जब हम नहीं कर सकते, तो हम स्पष्ट एकीकरण के साथ वापस आते हैं।

मैं स्पष्ट एकीकरण के साथ जो बड़ा लाभ देख रहा हूं, वह यह है कि गोचरों को अच्छी तरह से जाना जाता है। आप 60 के दशक से किसी भी पाठ्यपुस्तक को खोल सकते हैं और उन सभी को पढ़ सकते हैं जो विशेष एकीकरण तकनीकों के साथ उत्पन्न होने वाली छोटी-छोटी क्विर्क के बारे में जानना चाहते हैं। इस प्रकार, एक डेवलपर एक बार इन कौशलों को सीखता है, और उन्हें फिर कभी नहीं सीखना पड़ता है। यदि आप अंतर्निहित एकीकरण कर रहे हैं, तो प्रत्येक उपयोग का मामला थोड़ा अलग है, थोड़ा अलग गोच के साथ। आपने एक कार्य से अगले एक तक जो सीखा है उसे लागू करना थोड़ा कठिन है।


1

पॉस (टी) = वी (टी) * टी

केवल तभी काम करता है जब पॉज़ (0) = 0 और v (t) = k हो

आप प्रारंभिक स्थिति और पूरे वेग फ़ंक्शन के ज्ञान के बिना समय से स्थिति को संबंधित नहीं कर सकते हैं, इसलिए समीकरण अभिन्न के एक अनुमान के रूप में है

पॉज़ (t) = v (t) dt का इंटीग्रल 0 से t तक

संपादित करें _________

टिप्पणियों के प्रति एक छोटा सा सबूत (अनुमान पॉस (0) = 0)

let v (t) = 4

eqn 1: पॉज़ (t) = 4 * t (सही)

eqn 2: pos (t) = c + 4 * t 0 से t = 4 * t (सही)

let v (t) = 2 * t

eqn 1: pos (t) = 2 * t ^ 2 (गलत)

eqn 2: pos (t) = c + t ^ 2 से 0 से t = t ^ 2 (सही)

मुझे यह जोड़ना चाहिए कि आपका समीकरण पहले से ही निरंतर त्वरण में कारक है (यानी आपका समीकरण eqn 2 है जहाँ v (t) = v0 + a * t और एकीकरण की सीमाएँ t0 और t) हैं, इसलिए जब तक आप अपडेट करते हैं, तब तक आपका समीकरण काम करना चाहिए प्रारंभिक स्थिति, प्रारंभिक वेग, और त्वरण स्थिर रहता है।

EDIT2 ________

मुझे यह भी जोड़ना चाहिए कि आप प्रारंभिक स्थिति, प्रारंभिक वेग, प्रारंभिक त्वरण और निरंतर झटका के साथ स्थिति की गणना भी कर सकते हैं। दूसरे शब्दों में, आप eqn 2 के आधार पर एक फ़ंक्शन बना सकते हैं, जो समय बनाम स्थिति का प्रतिनिधित्व करता है, इसे इसे डेरिवेटिव यानी वेग, झटके, जो भी आगे आता है, आदि, आदि से अलग करता है, आदि, लेकिन आप केवल अपने समीकरण में सटीक होंगे यदि v (t) को इस तरह से मॉडल किया जा सकता है। यदि v (t) को केवल वेग, त्वरण, निरंतर झटके इत्यादि के साथ मॉडलिंग नहीं किया जा सकता है, तो आपको eqn 2 के लगभग अनुमान पर वापस जाने की आवश्यकता है, जो तब होता है जब आपके पास उछलती, वायु प्रतिरोध, हवा, आदि चीजें होती हैं। ।


निरंतर। इसका मतलब सिर्फ v (t) समय के साथ अलग-अलग नहीं होना चाहिए
Ky1313

मुझे इसके साथ बैठना होगा और यह जानना होगा कि यह सच क्यों है ... अभी के लिए upvoting :) मैंने इस मामले में प्रश्न में एक कोड नमूना पोस्ट किया है जो चीजों को बदलता है
davidkomer

कोई बात नहीं, बेहतर शब्दों के साथ फिर से अद्यतन :)
Kyy13
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.