ทำไมต้องรวมกันมากกว่าการสะสม?


14

ฉันเริ่มเรียนรู้วิธีการทำฟิสิกส์แบบ DIY และฉันมีคำถามเกี่ยวกับการนำการบูรณาการมาใช้ในระดับพื้นฐานที่สุด (เช่นนี่ไม่ใช่คำถามของออยเลอร์กับ RK4)

เกือบทุกตัวอย่างที่ฉันเจอมีintegrate()ฟังก์ชั่นบางอย่างที่ได้รับการประทับเวลาตั้งแต่การอัปเดตครั้งล่าสุดและอัปเดตการเร่งความเร็ว (และ / หรือความเร็วและ / หรือตำแหน่ง) ตั้งแต่การอัปเดตครั้งล่าสุด

ในรูปแบบที่ง่ายที่สุด: position += velocity * deltaTime

แต่ผมไม่เข้าใจว่าทำไมมันสะสมเช่นนี้เมื่อมันสามารถได้อย่างง่ายดายเพียงได้รับอากาศโดยเปลี่ยนฟังก์ชั่น ตัวอย่างเช่น: getPosition = makeNewFunction()ซึ่งสามารถคืนสิ่งที่มีลายเซ็นTime -> Positionและผลงานภายในของฟังก์ชันนั้นถูกสร้างขึ้นผ่านสูตรทางคณิตศาสตร์ที่เหมาะสม

ด้วยวิธีนี้ไม่มีการสะสม ... เมื่อใดก็ตามที่ต้องได้รับตำแหน่งมันจะเรียกฟังก์ชันนั้นตามเวลาปัจจุบัน

การทำความเข้าใจเกี่ยวกับมือใหม่ของฉันคือการที่จะหลีกเลี่ยงข้อผิดพลาดที่เกิดจากการสะสม ... ดังนั้นทำไมมันไม่ทำงานฉันจะพลาดอะไร

(fwiw ฉันได้รวบรวมหลักฐานพื้นฐานของแนวคิดของความคิดนี้ - แม้ว่ามันจะทดสอบสิ่งอื่น ๆ ในเวลาเดียวกันดังนั้นมันจึงไม่ใช่ตัวอย่างที่สะอาดที่สุด: https://github.com/dakom/ball-bounce-frp )

แก้ไข 1:ดังที่กล่าวไว้ในความคิดเห็นอาจเป็นสิ่งสำคัญที่ชี้ให้เห็นว่าฉันยังไม่ได้เรียนรู้เกี่ยวกับการเปลี่ยนการเร่งความเร็วหรือการจัดการกับกระตุกและสิ่งอื่น ๆ ที่ต้องมีการรวมลำดับสูงกว่าเร่งความเร็วคงที่

แก้ไข 2:นี่คือตัวอย่างโค้ดพื้นฐานของแนวคิดและไวยากรณ์ javascript หลอก - โปรดทราบว่า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
ฟังก์ชั่นของคุณจะทำอะไรถ้าคุณไม่มีความเร็ว / ความเร่งคงที่
Linaith

ฉันไม่รู้! : D ถ้านั่นคือเหตุผล - เช่นฉันยังไม่ได้เปลี่ยนความเร่งเลยฉันขอขอบคุณคำอธิบายที่สมบูรณ์กว่านี้ว่าคำตอบจะสลายไปได้อย่างไร (ไม่เช่นนั้นฉันอาจไปตามถนนที่ใช้งานได้นี้ !)
davidkomer

6
ถ้าวัตถุของคุณหมุนวนเป็นวงกลมแน่นอนว่า ... แล้วมันเป็นกล่องที่ผู้เล่นดันอยู่หรือเปล่า? เมื่อคุณโทรหา getPosition (ตอนนี้ + 100) มันทำนายอนาคตที่จะรู้ว่าเมื่อไรที่ผู้เล่นจะหยุดผลักมัน? เมื่อคุณเรียกใช้ getPosition (ตอนนี้ -1000) จะต้องจดจำอดีตหรือไม่
user253751

คำตอบ:


34

... ผลงานภายในของฟังก์ชันนั้นถูกสร้างขึ้นผ่านสูตรทางคณิตศาสตร์ที่เหมาะสม ...

สิ่งนี้จะใช้ได้กับปัญหาบางประเภทและวลีสำคัญในการค้นหาเป็นโซลูชันแบบปิด ตัวอย่างเช่นในโปรแกรม Kerbal Space การเคลื่อนที่ของยานอวกาศในวงโคจรจะถูกคำนวณด้วยวิธีนี้ น่าเสียดายที่ปัญหาที่ไม่น่ารำคาญที่สุด (เช่นการย้อนยานอวกาศของยานอวกาศดังกล่าว) กลับไม่มีวิธีแก้ปัญหาแบบปิด ดังนั้นความจำเป็นในการประมาณเชิงตัวเลขที่ง่ายขึ้นทางคณิตศาสตร์ (เช่นintegrate()เมื่อเวลาผ่านไป)


อ่า ... สุดยอด! หากคุณมีเวลาสักครู่ - คุณคิดอย่างไรกับการตั้งเป้าหมายในการใช้งานฟังก์ชั่นนี้แล้วถอยกลับมารวมตัวกันถ้าฉันไม่สามารถหาวิธีทำให้มันใช้งานได้ (เช่นถ้าฉันจัดการกับปัญหาแบบไม่ปิดหรือ ฉันไม่สามารถหาวิธีแปลงให้เป็นหนึ่งได้) ผมชอบความคิดในการสร้างฟังก์ชั่นเนื่องจากมันเหมาะกับคณิตศาสตร์ 1: 1 - แต่ถ้าฉันมักจะตีจุดจบอย่างหลีกเลี่ยงไม่ได้มันอาจจะไม่คุ้มค่า ...
davidkomer

8
@davidkomer ทำไมคุณถึงต้องการสร้างฟังก์ชันต่อไป หากคุณสามารถดึงสิ่งนี้ออกได้คุณสามารถคำนวณล่วงหน้าและบันทึกวิถีทั้งหมดได้! แน่นอนคนทำสิ่งนี้แล้ว: มันเรียกว่าภาพเคลื่อนไหวและมันมีส่วนแบ่งย่อยของมัน
Joker_vD

ฟังก์ชั่นการเปลี่ยนแปลงขึ้นอยู่กับพลวัตรันไทม์ ... ดู FRP ball-bounce ตัวอย่าง
davidkomer

จริง ๆ แล้วฉันจะต้องอัปเดตตัวอย่างนั้นให้เป็นอะไรที่ยิ่งกว่าพงษ์โดยวัตถุที่เคลื่อนไหวจะถูกควบคุมแบบสุ่ม / โดยผู้ใช้ ...
davidkomer

10

ปัญหาเกี่ยวกับวิธีการของคุณคือคุณไม่มีประวัติวัตถุของคุณ คุณสามารถคำนวณตำแหน่งถ้าคุณเคลื่อนที่ไปในทิศทางเดียว แต่จะเกิดอะไรขึ้นถ้าคุณกดบางสิ่งแล้วเด้งกลับมา
หากคุณสะสมจากตำแหน่งที่รู้จักล่าสุดของคุณคุณสามารถจัดการผลกระทบและไปจากที่นั่น หากคุณพยายามที่จะคำนวณมันตั้งแต่เริ่มต้นคุณต้องคำนวณผลกระทบใหม่ทุกครั้งหรือตั้งเป็นตำแหน่งเริ่มต้นใหม่

ตัวอย่างของคุณทำให้ฉันนึกถึงเกมแข่งรถ (ฉันไม่รู้ว่าตำแหน่งนั้นจะถูกควบคุมโดยเครื่องยนต์ฟิสิกส์หรือไม่ แต่ฉันคิดว่ามันใช้งานได้ดีในการอธิบาย)
ถ้าคุณขับรถด้วยรถยนต์คุณสามารถเร่งและชะลอความเร็วได้ คุณไม่สามารถคำนวณตำแหน่งของคุณได้โดยไม่ทราบว่ารูปแบบความเร็วของรถของคุณเป็นอย่างไรตั้งแต่ต้นจนถึงตอนนี้ การสะสมระยะทางนั้นง่ายกว่าการเก็บความเร็วที่คุณมีในทุกเฟรมตั้งแต่เริ่มต้นจนถึงตอนนี้

คำเตือน: ฉันยังไม่ได้เขียนฟิสิกส์ของเกมในตอนนี้นั่นเป็นเพียงวิธีที่ฉันเห็นปัญหา

แก้ไข:
ในแผนภาพนี้คุณสามารถดูว่าค่าเปลี่ยนแปลงตลอดเวลาอย่างไร
สีแดง = ความเร่ง (ตั้งแต่เริ่มเร่งไปจนถึงลด
ความเร็ว) เขียว = ความเร็ว (ตั้งแต่เริ่มหยุดจนถึง)
สีน้ำเงิน = วิธีที่คุณไป

ความเร็วรวมนั้นเป็นส่วนสำคัญของการเร่งความเร็วจากจุดเริ่มต้นไปสู่การเข้าสู่ระบบจริงของคุณ (พื้นที่ระหว่างเส้นและแกน)
วิธีคือความสำคัญของความเร็วของคุณ
หากคุณรู้ค่าสำหรับการเร่งความเร็วของคุณคุณสามารถคำนวณค่าอื่น ๆ แต่ถ้าฉันไม่เข้าใจผิดก็คืออินทิเกรลคำนวณโดยการสะสมบนพีซี และเป็นวิธีที่ค่าใช้จ่ายมากขึ้นในการจัดเก็บค่าความเร่งทั้งหมด
นอกจากนี้อาจมีการคำนวณทุกเฟรมมากเกินไป

แผนภาพการเร่งความเร็ว / ความเร็ว / เวลา

ฉันรู้ว่าทักษะการทาสีของฉันยอดเยี่ยม ;)

แก้ไข 2:
ตัวอย่างนี้ใช้สำหรับการเคลื่อนที่เชิงเส้น การกำหนดทิศทางทำให้สิ่งนี้ยากยิ่งขึ้น


"หรือตั้งเป็นตำแหน่งเริ่มต้นใหม่" - ใช่ แต่ฉันไม่เห็นปัญหาเกี่ยวกับเรื่องนั้น :) Re: ตัวอย่างรถยนต์ ... ฉันรู้สึกว่าฉันต้องเริ่มเล่นกับบางสิ่งที่ซับซ้อนกว่าเช่นนั้น .
davidkomer

การตั้งค่าตำแหน่งใหม่อาจไม่ใช่ปัญหา ฉันแก้ไขส่วนรถยนต์
Linaith

1
ในเกมรถฉันคิดว่าการเร่งความเร็วจะซับซ้อนกว่านี้มาก อาจมีการกระโดดและหนามและอาจขึ้นอยู่กับความเร็ว (เช่นความเร่งลดลงเป็น 0 เมื่อรถเข้าใกล้ความเร็วสูงสุด)
jpmc26

3
@davidkomer ไม่ต้องรำคาญกับรถยนต์ (เว้นแต่คุณต้องการ), platformer พื้นฐานจะทำ mario.getPosition (เวลา) ทำงานใน Super Mario Bros อย่างไร
253751

8

อย่างไรก็ตามฉันไม่เข้าใจว่าทำไมการสะสมเช่นนี้เมื่อได้รับอย่างง่ายดายเพียงแค่เปลี่ยนฟังก์ชั่น ตัวอย่างเช่น: getPosition = makeNewFunction () ซึ่งสามารถคืนสิ่งที่มีลายเซ็นของเวลา -> ตำแหน่งและการทำงานภายในของฟังก์ชันนั้นถูกสร้างขึ้นผ่านสูตรทางคณิตศาสตร์ที่เหมาะสม

คุณสามารถ!

มันถูกเรียกว่าการใช้วิธีการแก้ปัญหาแบบวิเคราะห์หรือปิด มันมีประโยชน์ที่จะแม่นยำมากขึ้นเนื่องจากข้อผิดพลาดในการปัดเศษที่สะสมเมื่อเวลาผ่านไปไม่มีอยู่จริง

อย่างไรก็ตามวิธีนี้ใช้ได้ถ้าหากคุณทราบถึงรูปแบบปิดดังกล่าวล่วงหน้า สำหรับเกมนี้ค่อนข้างบ่อยไม่ใช่กรณี

การเคลื่อนไหวของผู้เล่นนั้นผิดปกติและไม่สามารถใส่ลงในฟังก์ชั่นที่คำนวณไว้ล่วงหน้าได้ ผู้เล่นสามารถและจะเปลี่ยนความเร็วและทิศทางของเขาค่อนข้างบ่อย

NPCs อาจใช้ประโยชน์จากโซลูชั่นแบบปิดและในความเป็นจริงบางครั้งพวกเขาทำ อย่างไรก็ตามมีข้อเสียอื่น ๆ คิดถึงเกมแข่งรถที่เรียบง่าย ทุกครั้งที่รถของคุณชนกับยานพาหนะคันอื่นคุณต้องเปลี่ยนฟังก์ชั่นของคุณ บางทีรถเคลื่อนที่เร็วขึ้นอยู่กับรถไฟใต้ดิน จากนั้นการหาวิธีแก้ปัญหาแบบปิดจะค่อนข้างยาก ในความเป็นจริงมีหลายกรณีที่การค้นพบรูปแบบปิดนั้นเป็นไปไม่ได้หรือซับซ้อนจนไม่สามารถทำได้

ตัวอย่างที่ดีของการใช้โซลูชันแบบปิดคือ Kerbal Space Program ทันทีที่จรวดของคุณอยู่ในวงโคจรและไม่อยู่ภายใต้แรงขับ KSP อาจวาง "บนราง" วงโคจรถูกกำหนดล่วงหน้าในระบบสองตัวและเป็นคาบ ตราบใดที่จรวดไม่ได้ใช้แรงผลักดันอีกต่อไปคุณก็รู้อยู่แล้วว่าจรวดจะอยู่ที่ใดและคุณสามารถเรียกได้ง่ายgetPositionAtTime(t)มันได้ (ไม่ใช่ชื่อที่แน่นอน

อย่างไรก็ตามในทางปฏิบัติการใช้เพียงการรวมทีละขั้นตอนมักจะเป็นประโยชน์มากกว่า แต่เมื่อคุณเห็นสถานการณ์ที่มีวิธีแก้ปัญหาแบบปิดอยู่และง่ายต่อการคำนวณลองทำดู! ไม่มีเหตุผลจะไม่ใช้มัน

ตัวอย่างเช่นหากตัวละครของคุณเล็งปืนใหญ่คุณสามารถแสดงจุดกระแทกที่คาดการณ์ไว้ของลูกกระสุนปืนโดยใช้วิธีแก้ปัญหาแบบปิด และถ้าเกมของคุณไม่อนุญาตให้มีการเปลี่ยนแปลงสนามบอล (เช่นไม่มีลม) คุณสามารถใช้มันเพื่อย้ายบอลปืนใหญ่ได้ โปรดทราบว่าคุณจะต้องระมัดระวังเป็นพิเศษกับสิ่งกีดขวางที่เคลื่อนเข้าไปในเส้นทางของลูกกระสุนปืนใหญ่ของคุณแล้ว

มีสถานการณ์ที่คล้ายกันมากมาย หากคุณกำลังสร้างเกมแบบรอบแล้วก็มีแนวโน้มที่จะมีวิธีแก้ปัญหาแบบปิดที่มีอยู่มากกว่านั้นเมื่อสร้างเกม RTS เนื่องจากคุณทราบพารามิเตอร์ทั้งหมดล่วงหน้าและสามารถพูดด้วยความมั่นใจว่าพวกเขาจะไม่เปลี่ยนแปลง ตัวอย่างเช่นในเส้นทางนั้น)

โปรดทราบว่ามีเทคนิคในการต่อสู้แล้วความไม่ถูกต้องเชิงตัวเลขของการรวมแบบก้าว ตัวอย่างเช่นคุณสามารถติดตามข้อผิดพลาดสะสมและใช้คำที่แก้ไขเพื่อเก็บข้อผิดพลาดในการตรวจสอบเช่นการสรุป Kahan


8

ในกรณีที่ลูกบอลกระดอนง่ายการหาวิธีแก้ปัญหาแบบปิดง่าย ๆ อย่างไรก็ตามระบบที่ซับซ้อนมากขึ้นมักจะต้องการการแก้สมการเชิงอนุพันธ์สามัญ (ODE) ต้องใช้เครื่องมือแก้ปัญหาเชิงตัวเลขเพื่อจัดการทั้งหมดยกเว้นกรณีที่ง่ายที่สุด

แน่นอนว่ามีตัวแก้ตัวเลข ODE สองชั้น: ชัดเจนและโดยปริยาย ตัวแก้อย่างชัดแจ้งให้การประมาณรูปแบบปิดสำหรับสถานะถัดไปของคุณในขณะที่ตัวแก้แบบนัยจำเป็นต้องมีการแก้สมการเพื่อทำเช่นนั้น สิ่งที่คุณอธิบายสำหรับลูกบอลกระดอนของคุณเป็นจริงแก้ ODE โดยปริยายไม่ว่าคุณจะรู้หรือไม่!

นักแก้ปัญหาโดยนัยมีข้อได้เปรียบในการใช้ขั้นตอนเวลาที่มีขนาดใหญ่กว่ามาก สำหรับอัลกอริทึมการตีกลับของลูกบอลการจับเวลาของคุณอาจมีขนาดใหญ่เท่ากับระยะเวลาจนถึงการชนครั้งต่อไป (ซึ่งจะเปลี่ยนฟังก์ชันของคุณ) สิ่งนี้จะทำให้โปรแกรมของคุณทำงานได้เร็วขึ้นมาก อย่างไรก็ตามโดยทั่วไปเราไม่สามารถหาวิธีแก้ปัญหาที่ดีสำหรับ ODE ที่เราสนใจได้เมื่อเราทำไม่ได้เราจะถอยกลับไปหาการบูรณาการที่ชัดเจน

ข้อได้เปรียบที่ยิ่งใหญ่ที่ฉันเห็นด้วยการรวมที่ชัดเจนคือ gotchas เป็นที่รู้จักกันดี คุณสามารถเปิดตำราเรียนได้ตั้งแต่ '60s และอ่านสิ่งที่คุณต้องรู้เกี่ยวกับนิสัยใจคอเล็ก ๆ น้อย ๆ ที่เกิดขึ้นกับเทคนิคการรวมตัวเป็นพิเศษ ดังนั้นผู้พัฒนาจึงเรียนรู้ทักษะเหล่านี้เพียงครั้งเดียวและพวกเขาไม่จำเป็นต้องเรียนรู้อีกเลย หากคุณทำการรวมโดยนัยกรณีการใช้งานแต่ละกรณีจะแตกต่างกันเล็กน้อยโดยมี gotchas แตกต่างกันเล็กน้อย เป็นการยากที่จะนำสิ่งที่คุณเรียนรู้จากงานหนึ่งไปใช้กับงานถัดไป


1

pos (t) = v (t) * t

ใช้ได้เฉพาะเมื่อ pos (0) = 0 และ v (t) = k

คุณไม่สามารถเกี่ยวข้องกับตำแหน่งโดยไม่มีความรู้เกี่ยวกับเงื่อนไขเริ่มต้นและฟังก์ชั่นความเร็วทั้งหมดดังนั้นสมการนี้จึงเป็นการประมาณของอินทิกรัล

pos (t) = อินทิกรัลของ v (t) dt จาก 0 ถึง t

แก้ไข _________

นี่เป็นข้อพิสูจน์เล็ก ๆ น้อย ๆ ต่อความคิดเห็น (สมมติว่า pos (0) = 0)

ให้ v (t) = 4

eqn 1: pos (t) = 4 * t (ถูกต้อง)

eqn 2: pos (t) = c + 4 * t จาก 0 ถึง t = 4 * t (ถูกต้อง)

ให้ 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) จะต้องไม่เปลี่ยนแปลงตลอดเวลา
Kyy13

ฉันจะต้องนั่งกับเรื่องนี้และหาสาเหตุว่าทำไมมันเป็นเรื่องจริง ... upvoting ตอนนี้ :) ฉันโพสต์ตัวอย่างโค้ดในคำถามในกรณีที่สิ่งต่าง ๆ เปลี่ยน
davidkomer

ไม่มีปัญหาการปรับปรุงอีกครั้งกับคำพูดที่ดีกว่า :)
Kyy13
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.