ฉันจะกลับด้านของควอเทอร์เนียนเพียงแกนเดียวได้อย่างไร

ฉันสร้างวัตถุสองชิ้นใน Unity3D ซึ่งเป็นตัวแทนของต้นแขน (แม่) และแขนท่อนล่าง (ลูก) รวมเข้ากับข้อต่อของตัวละคร การหมุนของวัตถุเหล่านี้ขับเคลื่อนด้วยควอเทอร์เนียน 2 อันซึ่งฉันรวบรวมจาก IMU ซึ่งอยู่ที่ต้นแขนและต้นแขนส่วนล่าง ฉันปรับเทียบควอเทอร์เนียนทั้งสอง วัตถุประสงค์ของฉันคือเห็นภาพการงอ/ยืดข้อศอก

Q ในชื่อบ่งบอกว่าเป็นควอเทอร์เนียน QImu ระบุว่าเป็น Quaternion จาก IMU Qstart ระบุว่าเป็นการวางแนวเริ่มต้นเริ่มต้นของ IMU

// upperarm script attached to upperarm object
if (Input.GetKeyDown(KeyCode.Space))
        {
            QstartUpperArm = QimuUpperArm;
        }

        transform.localRotation = QstartUpperArm * Quaternion.Inverse(QimuUpperArm);
// lowerarm script attached to lowerarm object
if (Input.GetKeyDown(KeyCode.Space))
        {
            QstartLowerArm = QimuLowerArm;
        }

        QimuLowerArm = QstartLowerArm * Quaternion.Inverse(QimuLowerArm);
transform.localrotation = Quaternion.Inverse(Qstart2 * Quaternion.Inverse(Qimu2)) * Qimu1new;

วัตถุต้นแขนหมุนตรงตามที่คาดไว้ อย่างไรก็ตาม วัตถุท่อนล่างมีแกน y หนึ่งอันที่กลับด้าน แกนอื่นปกติดี ฉันจะเปลี่ยนเครื่องหมายของแกนเดียวนี้โดยใช้ Quaternion ได้อย่างไร


person pvand    schedule 15.07.2019    source แหล่งที่มา
comment
หมุนรอบแกนตั้งฉาก 180 องศา น่าเสียดายที่คุณไม่สามารถลบล้างแกนเดียวได้โดยไม่ต้องใช้สเกลลบหรือเปลี่ยนความถนัดของทั้งระบบ   -  person Leo Bartkus    schedule 15.07.2019
comment
คุณช่วยอธิบายเพิ่มเติมอีกหน่อยได้ไหมว่าแกน y ของคุณหมายถึงอะไรกลับด้าน? คุณกำลังบอกว่ามันหมุนไปในทิศทางที่ผิดรอบแกน y เฉพาะที่ของต้นแขนใช่หรือไม่? เราอาจต้องใช้รูปภาพหรือวิดีโอเพื่อให้เห็นภาพสิ่งที่เกิดขึ้นที่นี่   -  person Ruzihm    schedule 15.07.2019
comment
นี่เป็นการถ่ายภาพในความมืดโดยไม่รู้ว่าเกิดอะไรขึ้น... ลองวิธีนี้: Quaternion reversedY = Quaternion.Inverse(Qstart2 * Quaternion.Inverse(Qimu2)) * Qimu1new; transform.localrotation = Quaternion.Euler(Vector3.Scale(reversedY, new Vector3(1f, -1f, 1f) ) );   -  person Ruzihm    schedule 15.07.2019
comment
@pvand แจ้งให้เราทราบหากใช้งานได้   -  person Ruzihm    schedule 16.07.2019
comment
ฉันพบบางสิ่งทางออนไลน์ที่มีปัญหาคล้ายกัน วิธีแก้ไขคือ: Vector3 myEulerAngles = QimuLowerArm.eulerAngles; Quaternion invertedRotation = Quaternion.Euler(myEulerAngles.x, -myEulerAngles.y, myEulerAngles.z); transform.localRotation = invertedRotation; ดังนั้นฉันเดาว่าวิธีแก้ปัญหาของคุณก็คล้ายกัน   -  person pvand    schedule 16.07.2019


คำตอบ (1)


คุณไม่ควรทำสิ่งนี้โดยตรงใน Quaternion ดูเหมือนว่าคุณกำลังสับสน Quaternion (ซึ่งมี 4 องค์ประกอบ x,y,z,w) กับการแทนค่าปริภูมิออยเลอร์ใน x,y,z

คุณสามารถลองใช้สิ่งที่ต้องการ

var invertedRotation = Quaternion.Euler(Vector3.Scale(QimuLowerArm.eulerAngles, Vector3.up * -1));

ขึ้นอยู่กับการหมุนที่คุณต้องกลับด้าน (ไม่เห็นสิ่งนี้ชัดเจนในรหัสของคุณ)

  • eulerAngles ส่งคืนการแสดงออยเลอร์ของ Quaternion

  • Vector3.Scale คูณเป็น Vector3 องค์ประกอบ ในกรณีนี้ภายใน Vector3.up * -1 == new Vector3(0, -1, 0);

  • Quaternion.Euler สร้าง Quaternion สำหรับการหมุนมุมออยเลอร์ที่กำหนด เราต้องทราบที่นี่ว่าการหมุนจะใช้ตามลำดับ x แล้วก็ z แล้วก็ y แต่เนื่องจากคุณกำลังกลับค่าอันหลัง มันควรจะไม่เป็นไร


อีกทางเลือกหนึ่ง (ไม่แน่ใจ) คือ

  • ลบล้างส่วนประกอบแกนตาม
  • ลบล้างองค์ประกอบ w

ฉันยังคงไม่ทำสิ่งนี้โดยตรงในควอเทอร์เนียนเพราะลำดับมีความสำคัญมาก แต่ทำเช่น

var invertedRotation = new Quaternion (QimuLowerArm.x, - QimuLowerArm.y, QimuLowerArm.z, -QimuLowerArm.w);
person derHugo    schedule 15.07.2019
comment
วิธีแก้ปัญหาแบบแรกได้ผล เมื่อใดก็ตามที่ฉันจับต้นแขนในการหมุนครั้งเดียวกัน อย่างไรก็ตาม ถ้าฉันเริ่มหมุนต้นแขน แขนท่อนล่างจะเริ่มหมุนเหนือแกนที่ฉันเพิ่งกลับด้าน กล่าวอีกนัยหนึ่ง ฉันเริ่มงอเมื่อหมุนวัตถุต้นแขนไปด้านข้าง... - person pvand; 15.07.2019