เทคนิคการหมุนที่ดีขึ้นแบบก้าวกระโดด (2022)
(thenumb.at)- การหมุนแบบ 3D มีจุดแข็งต่างกันไปตามรูปแบบการแทนค่า ดังนั้น rotation matrix จึงสะดวกสำหรับการแปลงจุด แต่การ interpolation, composition และการหาค่าเฉลี่ยต้องใช้เครื่องมือแยกต่างหาก
- Euler angles จัดการได้ง่ายสำหรับมนุษย์ แต่อาจเกิดปัญหา gimbal lock, ความเร็วเชิงมุมไม่คงที่ และ linear interpolation ที่พลาดเส้นทางสั้นที่สุด
- unit quaternion ให้การ interpolation ตามเส้นทางสั้นที่สุดด้วยความเร็วคงที่ผ่าน slerp แต่ไม่ใช่ vector space จึงไม่ค่อยเป็นธรรมชาติสำหรับการเขียนโดยตรง, scalar multiplication และการหาค่าเฉลี่ย
- exponential/logarithmic map เชื่อม vector แบบ axis/angle กับ rotation matrix เพื่อสร้างการ interpolation ตามเส้นทางสั้นที่สุดใน 2D และ 3D ในรูป
R(t) = exp(t log(R1 R0^-1)) R0 - ค่าเฉลี่ยของการหมุนหลายรายการอาจเกิด catastrophic cancellation ได้หากใช้เพียงค่าเฉลี่ย axis/angle แบบง่าย ๆ ส่วน Karcher mean จะค้นหาการหมุนที่ทำให้ผลรวมกำลังสองของระยะเชิงมุมน้อยที่สุดแบบวนซ้ำ จึงให้ผลลัพธ์ที่สอดคล้องกว่า
ข้อดีข้อเสียของแต่ละวิธีแทนค่าการหมุน
- การหมุนแบบ 3D มีหลายรูปแบบการแทนค่า และตัวเลือกที่เหมาะสมจะต่างกันไปตามว่าต้องการทำการแปลง, การเขียน/สร้าง, การ interpolation หรือการหาค่าเฉลี่ย
-
Rotation matrix
- การแทนค่าด้วยพีชคณิตเชิงเส้นที่ตรงที่สุดคือ orthonormal 3x3 matrix ที่มีดีเทอร์มิแนนต์เป็นบวก
- คอลัมน์ทั้งสามของ rotation matrix แสดงว่าแกน x, y, z หลังการหมุนย้ายไปอยู่ที่ใด
- การแปลงจุดทำได้ด้วยการคูณเมทริกซ์ และสามารถ compose กับ linear transformation อื่น ๆ ได้ด้วยการคูณเมทริกซ์เช่นกัน
- เหตุผลที่ใช้ rotation matrix เวลาวาดบนหน้าจอ คือการย้ายจุดจาก world-space ไปยัง screen ต้องใช้การคูณเมทริกซ์เพียงครั้งเดียว
- rotation matrix ไม่ใช่ vector space ดังนั้นการบวก rotation matrix สองตัวเข้าด้วยกันจะไม่ยังคงได้ rotation matrix
- หากทำ linear interpolation ระหว่าง rotation matrix สองตัว อาจมี scaling ปนเข้ามานอกเหนือจากการหมุน
-
Euler angles
- Euler angles ระบุการหมุนสามครั้งรอบแกน x, y, z และเรียกอีกอย่างว่า pitch, yaw, roll
- ลำดับการใช้การหมุนย่อยทั้งสามขึ้นอยู่กับธรรมเนียมที่ใช้ โดยตัวอย่างนี้ใช้ลำดับ x, y, z
- มนุษย์เข้าใจง่ายและมักใช้ในการเขียน/สร้างการหมุน แต่การ interpolation แบบง่ายอาจให้ผลลัพธ์ที่ไม่ต้องการ
- gimbal lock ซึ่งเกิดจากการหมุนย่อยตัวหนึ่งทำให้แกนหมุนอีกสองแกนขนานกัน ถือเป็น singularity
- ที่ singularity ไม่ว่าจะเปลี่ยนมุมใดในสองมุมที่ถูกล็อก ก็สามารถสร้างการหมุนผลลัพธ์เดียวกันได้
- หากเส้นทาง interpolation ไปถึง singularity จำนวนองศาอิสระในการแทนค่าตำแหน่งปัจจุบันจะเพิ่มขึ้น และเมื่อเลือกการแทนค่าใด ๆ เพื่อไปต่อ การ interpolation ของผลลัพธ์อาจไม่ต่อเนื่อง
- เนื่องจากมุมย่อยแต่ละมุมมีสมบัติเป็น cyclic การทำ linear interpolation จึงไม่ได้เลือกเส้นทางสั้นที่สุดระหว่างการหมุนสองตัวเสมอไป
- หากเส้นทางไม่ผ่าน singularity การ interpolation จะราบรื่น และถ้าไม่จำเป็นต้องแทนค่า “straight up” กับ “straight down” ก็สามารถเลี่ยงข้อจำกัดนี้ได้
-
Quaternions
- unit quaternion ถูกใช้เป็นเครื่องมือมาตรฐานสำหรับ composition และ interpolation ของการหมุน
- spherical linear interpolation หรือ slerp เลือกเส้นทางสั้นที่สุดด้วยความเร็วคงที่ระหว่าง quaternion สองตัว
- unit quaternion ก็ไม่ใช่ vector space เช่นกัน มนุษย์เขียน/สร้างโดยตรงได้ยาก และการคำนวณ interpolation อาจมีต้นทุน
- ยังขาดแนวคิดที่เป็นธรรมชาติเกี่ยวกับ scalar multiplication หรือค่าเฉลี่ย
- quaternion เป็น double-cover ของปริภูมิการหมุน ดังนั้นในบางกรณี
Q(1)อาจไปที่-Q1
-
Axis/angle
- การหมุนแบบ axis/angle แทนค่าด้วย vector 3D จำนวนจริง
- ทิศทางของ vector ระบุแกนหมุน ส่วนขนาดระบุมุมหมุนรอบแกนนั้น
- เขียนเป็น
θuโดยuเป็น unit vector และθเป็นมุมหมุน - เนื่องจากเป็น vector 3D จึงเป็น vector space ทำให้บวก, scaling และ interpolation ได้
- หากทำ linear interpolation ระหว่างการหมุนแบบ axis/angle สองตัว จะให้การเคลื่อนที่ที่ราบรื่นและมีความเร็วเชิงมุมคงที่ได้
- อย่างไรก็ตาม ขึ้นอยู่กับว่าจะระบุการหมุนเป้าหมายด้วยการแทนค่า axis/angle แบบใด linear interpolation อาจไม่ได้เลือกเส้นทางสั้นที่สุด
- เช่นเดียวกับ quaternion, vector แบบ axis/angle ก็เป็น double-cover ของปริภูมิการหมุน
Exponential map และ logarithmic map
- หากสามารถแปลงไปมาระหว่างรูปแบบการแทนค่าการหมุนต่าง ๆ ให้เหมาะกับวัตถุประสงค์ได้ ก็จะใช้จุดแข็งของแต่ละรูปแบบร่วมกันได้
- เนื่องจากการแปลงสุดท้ายต้องใช้ rotation matrix จึงให้เมทริกซ์เป็น canonical form
- exponential map คือฟังก์ชันที่รับอ็อบเจ็กต์การหมุนแล้วคืนค่า rotation matrix ที่เทียบเท่ากัน
- logarithmic map คือฟังก์ชันคู่กันที่รับ rotation matrix แล้วแปลงกลับเป็นอ็อบเจ็กต์การหมุน
- ในที่นี้จะกล่าวถึง map
expและlogที่แปลงไปมาระหว่าง rotation matrix กับ vector แบบ axis/angle
สัญชาตญาณเริ่มต้นจาก axis/angle แบบ 2D
- ใน 2D แกนหมุนมีเพียงแกนเดียวที่ชี้ออกนอกระนาบ ดังนั้นการหมุนแบบ axis/angle จึงแทนค่าได้ด้วยมุม
θเพียงค่าเดียว - จุด 2D
pที่ถูกหมุนไปθเป็นpθสามารถเขียนได้ดังนี้pθ = p cosθ + Jp sinθJคือเมทริกซ์ที่หมุน vector 2D ไป 90 องศา
Jคือ[[0, -1], [1, 0]]และเนื่องจากJ² = -Iการใช้สองครั้งจึงเป็นการหมุน 180 องศา- เมื่อขยายสมการนี้ จะได้ rotation matrix มาตรฐานของ 2D คือ
[[cosθ, -sinθ], [sinθ, cosθ]]
Exponential map และ logarithmic map ใน 2D
- เช่นเดียวกับที่
iในสูตร Euler ของจำนวนเชิงซ้อนe^(iθ) = cosθ + i sinθทำหน้าที่เป็น quarter turn ในสมการเมทริกซ์ 2D นั้นJก็ทำหน้าที่เดียวกัน - เมื่อนำเมทริกซ์
A = θJใส่ใน Taylor series ของฟังก์ชัน exponential จะสามารถทำการคำนวณเดียวกันได้ด้วยการบวกเมทริกซ์, การคูณเมทริกซ์ และ scaling - ผลลัพธ์จากการขยายจะปรากฏ Taylor series ของ
sinθและcosθแล้วได้สมการต่อไปนี้e^(θJ) = [[cosθ, -sinθ], [sinθ, cosθ]]
- ดังนั้น exponential map ใน 2D จะแปลงมุม
θไปเป็น rotation matrix ที่สอดคล้องกัน - logarithmic map นิยามเป็นอินเวอร์สของ exponential map
- หาก
R = exp(θJ)แล้วlog(R) = θJ - สามารถกู้คืนได้ด้วย
θ = atan2(R21, R11)
- หาก
- exponential map ไม่ใช่ injective
- เนื่องจาก
exp(θJ) = exp((θ + 2π)J)การเพิ่มอีกหนึ่งรอบก็ยังได้ rotation matrix เดิม - logarithmic map จึงนิยามให้คืนค่า มุมที่เล็กที่สุด ที่สอดคล้องกับ rotation matrix นั้น
atan2เป็นตัวทำให้คำนิยามนี้เกิดขึ้นจริง
- เนื่องจาก
Interpolation บนฐาน exp/log
- สามารถทำ linear interpolation อย่างง่ายระหว่างมุมหมุน 2D สองค่า
θ0,θ1แล้วค่อยสร้าง rotation matrix ได้ - แต่ถ้า
θ0และθ1อยู่ห่างกันมากกว่าπจะไม่สะท้อนสมบัติ cyclic ของมุมและเลือกเส้นทางที่ยาว - interpolation บนฐาน exp/log คำนวณการหมุนสำหรับเคลื่อนที่โดยตรงจาก rotation matrix สองตัว
R0,R1R1 R0^-1คือการหมุนที่ย้อนR0ก่อน แล้วค่อยใช้R1log(R1 R0^-1)ให้มุมที่เล็กที่สุดจากR0ไปยังR1- จากนั้น scale การหมุน axis/angle นี้ด้วย
tแล้วแปลงกลับเป็นเมทริกซ์ด้วยexp
- สูตร interpolation สุดท้ายเป็นดังนี้
R(t) = exp(t log(R1 R0^-1)) R0R(0) = R0,R(1) = R1
- ใน 2D จะตรวจสอบผลต่างของมุมโดยตรงก็ได้ แต่วิธีนี้ generalize ไปยัง 3D และมิติใด ๆ ได้โดยไม่ต้องแก้ไข
Axis/angle แบบ 3D และ skew-symmetric matrix
- ใน 3D ก็สามารถ exponentiate
θuแบบ axis/angle เพื่อสร้าง rotation matrix ได้ - หัวใจสำคัญคือการหาการแปลงแบบ quarter turn ที่มี unit vector
uเป็นแกน - cross product
u × pถูกนิยามเป็น vector ที่ตั้งฉากกับระนาบที่สร้างโดยuและpแต่ก็สามารถตีความได้ว่าเป็น quarter turn ของp⊥ซึ่งเป็นการฉายpลงบนระนาบที่ตั้งฉากกับu - สามารถสร้างเมทริกซ์
ûที่ให้ผลลัพธ์เหมือนu × pได้û = [[0, -uz, uy], [uz, 0, -ux], [-uy, ux, 0]]ûp = u × p
- เนื่องจาก
ûᵀ = -ûดังนั้นûจึงเป็น skew-symmetric matrix Jใน 2D ก็เป็น skew-symmetric และแทน cross product แบบ 2D จึงสืบต่อโครงสร้างเดียวกัน- ผลบวกและ scalar multiplication ของ skew-symmetric matrix ก็ยังเป็น skew-symmetric ดังนั้นสมบัติ vector space ของ axis/angle จึงคงอยู่ในรูปแบบเมทริกซ์นี้ด้วย
- เอกลักษณ์
û^(k+2) = -û^kมาจากการตีความทางเรขาคณิตว่า การใช้ cross product สามครั้งจะทำให้p⊥quarter turn สามครั้ง ซึ่งเท่ากับ negative quarter turn
Exponential map แบบ 3D: Rodrigues’ formula
- จากการหมุน axis/angle
θuสร้างθûแล้ว exponentiate จะได้ rotation matrix แบบ 3D - ใช้ Taylor series และ
û^(k+2) = -û^kจะได้สมการต่อไปนี้e^(θû) = I + sin(θ)û + (1 - cos(θ))û²
- สมการนี้รู้จักกันในชื่อ Rodrigues’ formula
- หาก
θ = 0จะได้e^(0û)p = pทำให้จุดคงเดิม - หาก
θ = π/2จะได้u × p + p∥ซึ่งเป็น quarter rotation - หาก
θ = πจะได้-p⊥ + p∥ซึ่งเป็น half rotation - เมทริกซ์นี้เป็น orthonormal
- ตรวจสอบเงื่อนไข
AᵀA = Iด้วยûᵀ = -ûและû^(k+2) = -û^k
- ตรวจสอบเงื่อนไข
- ดีเทอร์มิแนนต์เป็น 1 เมื่อ
θ = 0และไม่มีกรณีที่ดีเทอร์มิแนนต์เป็น 0 อีกทั้งexpต่อเนื่องกับθและûจึงไม่อาจเป็นลบได้ - ดังนั้น
exp(θû)จึงเป็น rotation matrix แบบ 3D
Logarithmic map แบบ 3D
- exponential map แบบ 3D ก็ไม่ใช่ injective เช่นกัน ดังนั้น logarithmic map แบบ 3D จึงนิยามให้คืนค่าการหมุนแบบ axis/angle ที่มี ขนาดเล็กที่สุด ซึ่งสอดคล้องกับเมทริกซ์ที่ให้มา
- จาก
R = exp(θû) = I + sin(θ)û + (1 - cos(θ))û²เมื่อหา trace จะได้มุมหมุน- trace คือผลรวมของสมาชิกบนแนวทแยง
tr(I) = 3- เนื่องจาก
ûเป็น skew-symmetric ผลรวมแนวทแยงจึงเป็น 0 tr(û²) = -2- ดังนั้น
tr(R) = 1 + 2cosθ θ = arccos((tr(R) - 1) / 2)
- แกนหมุนกู้คืนได้โดย antisymmetrize
RR - Rᵀ = 2 sin(θ)ûû = (R - Rᵀ) / (2 sinθ)u = 1/(2 sinθ) [R32 - R23, R13 - R31, R21 - R12]ᵀ
- เพียงเท่านี้ logarithmic map ทั้งหมดที่แปลงจาก rotation matrix แบบ 3D กลับไปเป็น axis/angle ก็เสร็จสมบูรณ์
ผลลัพธ์ของ interpolation แบบ 3D
- ใน 3D ก็ใช้สูตร interpolation เดียวกับ 2D ได้โดยตรง
R(t) = exp(t log(R1 R0^-1)) R0
- interpolation นี้คงข้อดีของการหมุนแบบ axis/angle ไว้ พร้อมเลือก เส้นทางสั้นที่สุด เสมอ
- ตัวอย่างเดียวกันอาจดูไม่ราบรื่นเมื่อใช้ Euler angles
ค่าเฉลี่ยของการหมุนหลายตัว
- หากใช้ quaternion จะได้ interpolation ที่ดี ดังนั้นปัญหา interpolation จึงแก้ได้แม้ไม่ใช้คณิตศาสตร์เมทริกซ์แบบ exp/log
- งานหนึ่งที่ทำได้ง่ายกว่าด้วยการหมุนแบบ axis/angle คือการหา ค่าเฉลี่ย ของ rotation matrix หลายตัว
- วิธีที่ง่ายที่สุดคือแปลงแต่ละเมทริกซ์เป็น axis/angle จากนั้นหาค่าเฉลี่ยของ vector แล้วแปลงกลับ
- วิธีนี้ใช้ได้ แต่อาจสร้างพฤติกรรมที่ไม่เป็นธรรมชาติ
- โดยเฉพาะเมื่อรวม vector แบบ axis/angle อาจเกิด catastrophic cancellation
- ตัวอย่างคือกรณีหาค่าเฉลี่ย
[π, 0, 0]กับ[-π, 0, 0]แล้วได้ 0 - สองค่านี้เป็นการหมุนที่เทียบเท่ากัน แต่ผลเฉลี่ย 0 ไม่สามารถแทนการหมุนทั้งสองได้
- ตัวอย่างคือกรณีหาค่าเฉลี่ย
Karcher mean
- ค่าเฉลี่ยของจุดบนระนาบสามารถมองได้ว่าเป็นจุดที่ทำให้ผลรวมระยะกำลังสองไปยังทุกจุดมีค่าน้อยที่สุด
- ขั้นตอนการหาโดย iterative optimization เป็นดังนี้
- เลือกค่าประมาณเริ่มต้น
x̄ ∈ R² - คำนวณ translation
ui = xi - x̄จากแต่ละจุดไปยังค่าประมาณ - หาค่าเฉลี่ย vector
u = (1/n) Σ ui - เคลื่อนไปในทิศทางค่าเฉลี่ยด้วย
x̄ = x̄ + τu - ทำซ้ำตราบใดที่
|u| > ε
- เลือกค่าประมาณเริ่มต้น
- แนวคิดเดียวกันนี้สามารถนำไปใช้กับการหมุน
R0, ..., Rnได้- เลือกการหมุนประมาณเริ่มต้น
R̄ ∈ R^(3×3) - สำหรับแต่ละเมทริกซ์ คำนวณ axis/angle
ui = log(Ri R̄^-1)จากค่าประมาณไปยังการหมุนนั้น - หาค่าเฉลี่ย vector
u = (1/n) Σ ui - เคลื่อนไปในทิศทางการหมุนเฉลี่ยด้วย
R̄ = exp(τu) R̄ - ทำซ้ำตราบใดที่
|u| > ε
- เลือกการหมุนประมาณเริ่มต้น
- ผลลัพธ์ของอัลกอริทึมนี้คือ Karcher mean
- Karcher mean คือการหมุนที่ทำให้ระยะเชิงมุมกำลังสองไปยังการหมุนอื่นทั้งหมดมีค่าน้อยที่สุด
- ไม่ได้รับผลจาก catastrophic cancellation จึงลู่เข้าไปยังการหมุนกึ่งกลางที่ไม่ใช่ 0 เสมอ
- ผลลัพธ์ของค่าเฉลี่ย axis/angle แบบง่ายกับ Karcher mean มักคล้ายกัน แต่ Karcher mean ให้พฤติกรรมที่สอดคล้องกว่า
ความสัมพันธ์ระหว่าง Quaternion กับ exp/log
- ส่วนนี้ตั้งอยู่บนพื้นฐานความรู้เรื่อง quaternion
- เช่นเดียวกับที่การ exponentiate จำนวนเชิงซ้อนเทียบเท่ากับการ exponentiate เมทริกซ์ skew-symmetric แบบ 2D การ exponentiate quaternion ก็เทียบเท่ากับการ exponentiate เมทริกซ์ skew-symmetric แบบ 3D
- ใน 2D เราสร้าง pure-imaginary complex number
iθจากการหมุน axis/angleθแล้ว exponentiatee^(iθ) = cosθ + i sinθ- ผลลัพธ์คือจำนวนเชิงซ้อนที่เมื่อคูณกับจุดแล้วจะหมุนจุดไป
θ - เนื่องจาก norm เป็น 1 เสมอ การหมุนแบบ 2D จึงแทนค่าได้ด้วย unit-norm complex number
- ใน 3D สามารถสร้าง pure-imaginary quaternion
q = ux i + uy j + uz kจาก vector การหมุน axis/angleu - ใช้กฎการคูณของ quaternion จะได้
q² = -||q||² = -θ²ซึ่งคล้ายกับเอกลักษณ์ที่ใช้กับ skew-symmetric matrix - ผลลัพธ์จากการ exponentiate เป็นดังนี้
e^q = cosθ + (q/θ) sinθ- แทบเหมือนสมการ 2D เพียงแต่ imaginary axis ไม่ได้มีแกนเดียว แต่มีสามแกน
- การหมุน axis/angle แบบ 3D ถูกแปลงเป็น unit-norm quaternion
- หากไม่ต้องใช้ rotation matrix, exponential map ของ quaternion เป็นตัวเลือกที่คำนวณง่าย
- logarithmic map ของ quaternion ก็เรียบง่ายเช่นกัน
θ = arccos(Re(q))u = Im(q) / sinθ
- หากต้องการหมุนจุด
pด้วย quaternionqให้คำนวณ conjugationq p q^-1- แทนจุดด้วย pure-imaginary quaternion
p = px i + py j + pz k - ในทางเทคนิค conjugation จะหมุนรอบแกน
uเป็นมุม2θดังนั้นตั้งแต่แรกให้กำหนด|u| = θ/2ก็พอ
- แทนจุดด้วย pure-imaginary quaternion
อ่านเพิ่มเติม
- สำหรับสื่อเรียนรู้ quaternion สามารถดู quaternions ของ eater.net
- เหตุผลที่ geometric algebra เป็นธรรมชาติกว่า อธิบายไว้ใน บทความของ Marc ten Bosch
- หากเรียนรู้ SO(3) ซึ่งเป็นโครงสร้างพีชคณิตของการหมุนแบบ 3D จะเข้าใจความสัมพันธ์ระหว่าง axis/angle, quaternion และ double-cover ได้ดีขึ้น
- มีวิดีโอที่เกี่ยวข้องคือ วิดีโออธิบายความสัมพันธ์ระหว่าง SO(3), SU(2), quaternion และ axis/angle ด้วยภาพ
- หน้า Wikipedia ของ SO(3) ครอบคลุม axis/angle, topology, SU(2), quaternion และการเชื่อมโยงกับ Lie algebra
- vector space ของ skew-symmetric matrix ประกอบเป็น so(3) ซึ่งเป็น Lie algebra ที่สอดคล้องกับ
SO(3)
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ความสอดคล้องระหว่าง Lie group/Lie algebra เป็นหนึ่งในแนวคิดที่เจ๋งที่สุดที่อยากให้ได้เรียนในโรงเรียน มันคือ exponential map และ logarithm map ที่บทความพูดถึง แต่ปรากฏในรูปแบบที่นำกลับมาใช้ซ้ำได้ดีกว่ามาก
ถ้าจับวัตถุนามธรรมที่อยากจัดการ เช่น การหมุน 3D โดยไม่ต้องไปติดกับรายละเอียดของพิกัด นั่นคือ Lie group และถ้าจากตรงนั้นอนุมานการแทนด้วยพิกัดที่ทำงานได้ดีออกมา ก็จะได้ Lie algebra ที่สอดคล้องกัน
จากนั้นวิธีแปลงไปมาระหว่างพิกัดกับวัตถุนามธรรม วิธีประกอบกัน ฯลฯ ก็แทบจะได้มาฟรี ๆ และในกรณีที่พบบ่อยในงานวิศวกรรม การ interpolate และการหาค่าเฉลี่ยก็จัดการได้ค่อนข้างสมเหตุสมผล
ถ้าสามารถแสดงปัญหาเป็นการประกอบกันของ Lie group ได้ ก็แค่หาว่า algebra แต่ละตัวคืออะไร จะช่วยประหยัดงานจำนวนมากที่ถ้าทำเองตรง ๆ คงใช้เวลานาน
ในที่นี้วัตถุต้องมีแนวคิดเรื่องการเปลี่ยนแปลงแบบ smooth และโครงสร้างเพิ่มเติมเล็กน้อย และในกระบวนการแปลงไปมาอาจมีปัญหาเรื่อง connected component ด้วย แต่นั่นก็เป็นเหตุผลที่ทำให้หยิบผลลัพธ์ที่รู้กันอยู่แล้วมาใช้ได้สะดวก
สัปดาห์อันยาวนานใกล้จะจบลงแล้ว และการใช้สไลเดอร์เพื่อ หมุนวัว ก็เป็นช่วงพักที่ต้องการพอดี
เป็นความไม่พอใจมานานที่ซอฟต์แวร์ 3D จำนวนมากไม่ใช้ อินเทอร์เฟซ Arcball สำหรับการหมุน
ผลิตภัณฑ์ของ Autodesk อย่าง 3DSmax และ Maya ใช้ แต่ Blender กับ OpenSCAD ไม่ใช้ และตอนทำงานที่ Roblox ก็โน้มน้าว PM ไม่สำเร็จ เพราะผู้ใช้ก็ยังพอทนกับวิธีเดิมได้
Arcball อิงกับ quaternion และใช้ฟังก์ชัน exponential ในการ interpolate สามารถทำการหมุนใด ๆ ก็ได้ด้วยการลากครั้งเดียว ไม่มี gimbal lock และมีคุณสมบัติว่าถ้าลากเป็นวงปิด จะกลับไปยังตำแหน่งเริ่มต้น
พิสูจน์ทางคณิตศาสตร์ได้จากข้อเท็จจริงที่ว่า unit quaternion เป็น double cover ของ SO(3) คล้ายกับที่ unit complex number แทนการหมุนบนวงกลมได้อย่างพอดี
implementation อ้างอิงของ quaternion/Arcball ที่ลองจับได้เอง: https://romankogan.net/math/arcball_js/index.html
โค้ดเป็น Java ที่มีคอมเมนต์เยอะ และรันไลบรารี Processing บน JavaScript ผ่าน ProcessingJS
มือและร่างกายเข้าใจ quaternion ได้ก่อนสมอง ดังนั้นถ้าสร้างซอฟต์แวร์ 3D ก็อยากให้ใช้วิธีนี้
Arcball: http://courses.cms.caltech.edu/cs171/assignments/hw3/hw3-not...
quaternion สำหรับการหมุน: https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotati...
Arcball ใน Processing: https://romankogan.net/math/arcball_js/index.html
ตอนนี้ดูจากมือถืออยู่ และ https://asliceofrendering.com/camera/2019/11/30/ArcballCamer... ช่วยให้เข้าใจ Arcball ได้ดี
ในบริบทนี้ไม่ค่อยเข้าใจว่าทำไมถึงชอบ quaternion กันขนาดนั้น เมทริกซ์ ก็ไม่ได้ดูสัญชาตญาณน้อยกว่า quaternion เลย
เมทริกซ์กระทำกับเวกเตอร์ และการหมุนก็กระทำกับเวกเตอร์เหมือนกัน เลยสงสัยว่าจะมีอะไรเป็นธรรมชาติกว่าการมองการหมุนเป็นเมทริกซ์
matrix exponential ก็เข้าใจได้เป็นสัญชาตญาณถ้าเชื่อมกับสมการเชิงอนุพันธ์สามัญ คำตอบของ
dx/dt = Axคือexp(t A)และถ้า A เป็น antisymmetric การเปลี่ยนแปลงของ x จะตั้งฉากกับ x เสมอ จึงเป็นการหมุนที่ไม่เปลี่ยนความยาวLie group/Lie algebra ทำให้เรื่องนี้ทั่วไปขึ้นมาก แต่แก่นคือการสร้างการเปลี่ยนแปลงที่ตั้งฉากอย่างต่อเนื่องเพื่อก่อให้เกิดการหมุน และ exponential map อธิบายกระบวนการนั้น ภาพแบบนี้รู้สึกเป็นเรขาคณิตและเป็นสัญชาตญาณกว่ามาก
ข้อดีของ quaternion คือจัดการด้วยกระดาษกับปากกาได้ง่ายกว่าการคำนวณการคูณเมทริกซ์แบบเดียวกันด้วยมือ
ส่วนตัวมองว่ามันเป็นสัญชาตญาณในความหมายคล้ายจำนวนเชิงซ้อน ตอนแรกก็แปลก แต่ตอนนี้รู้สึกว่าใช้และให้เหตุผลได้ง่ายกว่าทางเลือกอื่น ๆ ที่รู้จัก
คุณสมบัตินี้สำคัญมากในงานกราฟิก เช่น แอนิเมชันหรือการคำนวณเฟรมตามเส้นโค้ง spline แบบ 3D
คล้ายกับการจัดการการหมุน 2D ด้วยจำนวนเชิงซ้อน เมื่อคูณจำนวนเชิงซ้อนสองตัว การหมุนก็ถูกประกอบกัน และใน 2D จะอยู่ในรูปของการบวก argument เข้าด้วยกัน เช่นเดียวกัน เมื่อคูณ quaternion สองตัว ก็ประกอบการหมุน 3D ได้ และมีประสิทธิภาพกว่าการคูณเมทริกซ์ 3x3 มาก
เพื่อให้เห็นภาพ สัญชาตญาณคือ quaternion มีความเกี่ยวข้องใกล้ชิดกับการแทนแบบแกน-มุม ซึ่งเหมือนกับ Lie algebra so(3)
จากมุมมองที่ว่ามันกระทำกับเวกเตอร์ ให้มองการกำหนดพารามิเตอร์ของการหมุนหลายแบบเป็น implementation ของคุณสมบัติ
Rotationนามธรรมเดียวกันก็พอ ไม่ว่าภายในจะ implement ด้วยเมทริกซ์, quaternion, Euler vector, Euler angle หรือ Gibbs vector การหมุนก็กระทำกับเวกเตอร์และประกอบกันด้วยวิธีเดียวกันควอเทอร์เนียนหน่วยเป็นกรุ๊ปลี และถ้าต้องการสิ่งที่บวกเข้าด้วยกันได้ตามใจ ควรดูพีชคณิตลีของควอเทอร์เนียนทั้งหมด ซึ่งแทนความเร็วเชิงมุมของการหมุน เทียบได้กับการแทนความเร็วเชิงมุมแบบแกน-มุม
การเปรียบเทียบควอเทอร์เนียนหน่วยกับแกน-มุมเป็นการเทียบข้ามหมวดหมู่นิดหน่อย โดยควรเปรียบเทียบควอเทอร์เนียนหน่วยกับเมทริกซ์การหมุน และเปรียบเทียบควอเทอร์เนียนทั้งหมดกับแกน-มุมมากกว่า
ข้อดีของการใช้ควอเทอร์เนียนคือคำนวณแผนที่เอ็กซ์โปเนนเชียลได้ง่าย แต่เมื่อใช้ควอเทอร์เนียนก็แทบไม่จำเป็นต้องใช้เมทริกซ์การหมุน สามารถคำนวณการหมุนด้วย
pqp^-1ได้เหมือนในบทความผมคิดว่าวิธีที่ง่ายที่สุดในการเข้าใจควอเทอร์เนียนคืออ่านเรื่องพีชคณิตเชิงเรขาคณิต แม้การคิดค้นควอเทอร์เนียนจะใช้เวลาหลายร้อยปี แต่ถ้าเข้าใจพีชคณิตเชิงเรขาคณิตที่เรียบง่ายอย่างน่าทึ่ง ก็สามารถคิดควอเทอร์เนียนขึ้นมาใหม่ได้ในไม่กี่นาที
บทความที่เคยเห็นว่าเป็นบทนำที่ดีเมื่อหลายปีก่อน: https://crypto.stanford.edu/~blynn/haskell/ga.html
แม้จะผ่านรูปแบบทางการต่าง ๆ ของพีชคณิตเชิงเรขาคณิต สุดท้ายเพื่อแทนปริภูมิ SO(3)/SE(3) ก็ยังต้องใช้โรเตอร์และมอเตอร์ ซึ่งไอโซมอร์ฟิกกับควอเทอร์เนียนและควอเทอร์เนียนคู่ตามลำดับ
แต่ถ้าเป็นจุดประสงค์นั้น ผมยังคิดว่าเมทริกซ์การหมุน 3x3 และเมทริกซ์แปลง 4x4 ที่ใช้ร่วมกับแผนที่เอ็กซ์โปเนนเชียลมีประโยชน์กว่ามาก ควอเทอร์เนียนใช้พื้นที่เก็บน้อยกว่าและคูณกันเองได้เร็วกว่า แต่ตอนแปลงจุด เมทริกซ์เร็วกว่า และประสิทธิภาพรวมก็ขึ้นอยู่กับสถานการณ์
สิ่งเจ๋งอย่างหนึ่งที่ได้เรียนในมหาวิทยาลัยคือ ถ้านิยามตัวดำเนินการ
+ใหม่ให้เหมาะกับเมทริกซ์และปริมาณการเปลี่ยนแปลงในปริภูมิเวกเตอร์ และนิยามตัวดำเนินการ-ใหม่ให้เหมาะกับเมทริกซ์สองตัว ก็สามารถใส่เมทริกซ์การหมุนเข้าไปใน สถานะของ Kalman filter ได้เลยแบบนี้จะประมาณค่าการหมุนได้โดยไม่ต้องกังวลเรื่อง gimbal lock
https://openslam-org.github.io/MTK
+บนปริภูมิสัมผัสเป็นเรื่องค่อนข้างพบบ่อย ไม่ใช่แค่ใน Kalman filter แต่ในงาน optimization แบบไม่เชิงเส้นโดยรวมด้วย ไลบรารี Ceres ก็รองรับLocalParameterizationสำหรับเรื่องนี้ดีมากจริง ๆ และไม่ได้ดีแค่ส่วนย่อย ๆ
โดยเฉพาะชอบตรงที่วิธีเหล่านี้สุดท้ายคำนวณออกมาเป็น เมทริกซ์การหมุนมาตรฐาน ถ้าต้องหมุนเวกเตอร์หนึ่งล้านตัว ก็ทำการคำนวณที่น่าสนใจแค่ครั้งเดียว จากนั้นก็ปล่อยให้ไปป์ไลน์การคูณเมทริกซ์ที่ปรับแต่งมาอย่างสูงทำงานต่อ
เป็นบล็อกที่ยอดเยี่ยม แต่พอกดดูโปรไฟล์ผู้เขียนเพื่ออ่านบทความอื่น แล้วเห็นประโยคว่า “เริ่มรู้จักการเขียนโปรแกรมครั้งแรกตอนอายุ 9 ขวบราวปี 2010”
ผมอายุ 13 ในปี 2010 และกำลังพยายามยัดคณิตศาสตร์กับวิทยาศาสตร์ระดับมัธยมต้นเข้าหัว
ทุกครั้งที่เห็นบทความกราฟิกคอมพิวเตอร์เจ๋ง ๆ ก็รู้สึก ด้อยค่าอย่างรุนแรง เหมือนคนเขียนอายุน้อยกว่าผมและมีพรสวรรค์กว่ามาก
แต่ก็ไม่ค่อยรู้จะแนะนำว่าควรทำอย่างไรเหมือนกัน แค่เพราะผมชอบมันจริง ๆ เลยทำต่อเนื่องมาเรื่อย ๆ ถึงอย่างนั้น การฝึกอย่างมีโครงสร้างก็น่าจะได้ผลอยู่
ระหว่างหาวิธีหาค่าเฉลี่ยของการหมุนหลาย ๆ แบบ ก็ไปเจอ https://mathweb.ucsd.edu/~sbuss/ResearchWeb/spheremean/paper...
วิธีในบทความนี้ดูง่ายกว่าบทความวิชาการนั้นมาก อย่างน้อยก็สำหรับระดับคณิตศาสตร์ของผม
ค่าเฉลี่ยเป็นสิ่งที่ทำได้ด้วยการบวก และในการบวก ลำดับการรวมไม่สำคัญ แต่การหมุนไม่เป็นไปตามสมบัติการสลับที่ ดังนั้นแนวคิดค่าเฉลี่ยที่เราเข้าใจตามปกติจึงใช้ตรง ๆ ไม่ได้
ลองถือโทรศัพท์แล้วหมุนหน้าจอออกไปจากตัว 180° จากนั้นหมุนตามเข็มนาฬิกา 90° เมื่อเทียบกับพื้น กล้องจะหันไปทางซ้าย แต่ถ้าทำการหมุนสองแบบเดียวกันในลำดับย้อนกลับ กล้องจะหันไปทางขวา
สำหรับ “ค่าเฉลี่ย” ของการหมุนสองแบบนี้ ไม่มีคำตอบเดียวว่ากล้องควรหันไปทางไหน ขึ้นอยู่กับสมบัติที่ต้องการจากค่าเฉลี่ย
https://news.ycombinator.com/item?id=40333541
สัญชาตญาณหลักคือ การบวกคือการเลื่อนขนาน ส่วนการคูณคือการหมุน ดังนั้นสำหรับค่าเฉลี่ยของการเลื่อนขนานใช้ค่าเฉลี่ยเลขคณิตได้ และสำหรับค่าเฉลี่ยของการหมุนใช้ ค่าเฉลี่ยเรขาคณิต ได้
กว่าจะตระหนักว่าในคณิตศาสตร์ก็สร้าง นามธรรม ขึ้นมา คล้ายกับเวลานึกถึง abstraction ในวิศวกรรมซอฟต์แวร์ ก็ใช้เวลานาน
ตอนเด็ก ๆ ผมสับสนว่าทำไมต้องสร้างจำนวนจินตภาพขึ้นมา และเมทริกซ์มีความหมายอะไรกันแน่
ต่อมาถึงได้รู้ว่าการแทนเหล่านี้ถูกออกแบบขึ้นมา ถ้าสร้างสิ่งที่เรียกว่าจำนวนจินตภาพขึ้นมา การคำนวณบางอย่างจะง่ายขึ้น และถ้าเขียนสมการเชิงเส้นเป็นเมทริกซ์ ก็ให้เหตุผลได้ง่ายกว่าการเขียนทุกอย่างขยายออกมามาก
ฟังดูเหมือนชัดเจนอยู่แล้ว แต่ไม่มีใครเคยบอกผมแบบนี้
ปริภูมิเวกเตอร์ ริง ปริภูมิเมตริก และ category ก็เช่นกัน คณิตศาสตร์เต็มไปด้วยอินเทอร์เฟซในฐานะ design pattern
อย่างไรก็ตาม อินเทอร์เฟซในคณิตศาสตร์ใกล้เคียงกับ type class มากกว่าการสืบทอดในโปรแกรมมิง เพราะเซต/ไทป์เดียวกันสามารถเป็นกรุ๊ปได้หลายแบบ