मैं दो 2D वैक्टर के बीच कोण और उचित मोड़ दिशा की गणना कैसे कर सकता हूं?


26

मैं कुछ आंदोलन एआई पर काम कर रहा हूं जहां कोई बाधा नहीं है और आंदोलन एक्सवाई विमान तक ही सीमित है। मैं दो वैक्टरों की गणना कर रहा हूं, v , जहाज 1 का सामना करने की दिशा, और w , जहाज 1 की स्थिति से जहाज 2 की ओर इशारा करते हुए वेक्टर।

मैं तो सूत्र का उपयोग करके इन दो वैक्टरों के बीच के कोण की गणना कर रहा हूं

arccos((v · w) / (|v| · |w|))

मेरे पास समस्या यह है कि arccosकेवल 0 ° और 180 ° के बीच मान लौटाता है। इससे यह निर्धारित करना असंभव हो जाता है कि मुझे दूसरे जहाज का सामना करने के लिए बाएं या दाएं मुड़ना चाहिए या नहीं।

क्या ऐसा करने के लिए इससे अच्छा तरीका है?


1
यदि आप एकता का उपयोग कर रहे हैं, तो देखें Mathf.DeltaAngle()
रसेल बोरोगोव

जवाबों:


22

2d क्रॉस-उत्पाद का उपयोग करना बहुत तेज़ है। कोई महंगा ट्रिगर फ़ंक्शन शामिल नहीं है।

b2Vec2 target( ... );
b2Vec2 heading( ... );

float cross = b2Cross( target, heading );

if( cross == -0.0f )
   // turn around

if( cross == 0.0f )
  // already traveling the right direction

if( cross < 0.0f)
  // turn left

if( cross > 0.0f)
  // turn right

यदि आपको अभी भी वास्तविक कोणों की आवश्यकता है तो मैं उपयोग करने की सलाह देता हूं atan2atan2आपको किसी भी वेक्टर का पूर्ण कोण देगा। किसी भी वैक्टर के बीच सापेक्ष कोण प्राप्त करने के लिए, उनके पूर्ण कोणों को शांत करें और सरल घटाव का उपयोग करें।

b2Vec2 A(...);
b2Vec2 B(...);

float angle_A = std::atan2(A.y,A.x);
float angle_B = B.GetAngle(); // Box2D already figured this out for you.

float angle_from_A_to_B = angle_B-angle_A;
float angle_from_B_to_A = angle_A-angle_B;

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

2
हाँ, जब वैक्टर और कोणों के बीच रूपांतरण होता है, तो atan2 () सबसे निश्चित रूप से आपका मित्र होता है।
ब्लूस्क्रान

1
धन्यवाद! मैंने पाया है कि मुझे वास्तव में कोण की आवश्यकता नहीं है, 2 डी क्रॉस उत्पाद को हथियाना मेरी आवश्यकताओं के लिए काफी सरल है।
454

2
इसके अलावा आपका if( cross == -0.0f )बनाम if( cross == 0.0f )चेक बेहद नाजुक लगता है।
बोबोबो नोव

1
@bobobobo, एक भौतिकी इंजन के साथ यह सिर्फ एक दिशा लेने और स्थानांतरित करने का विकल्प नहीं हो सकता है। जादुई रूप से मोड़ने से भौतिक इंजनों के खराब होने का कारण बन सकता है। इसके अलावा जादुई रूप से घूर्णन एनीमेशन के लिए भयानक लगता है। तो हां, आप इसे बाएं या दाएं की धारणा के बिना हल कर सकते हैं , लेकिन एक पॉलिश समाधान को अक्सर इन की आवश्यकता होती है।
deft_code

10

2 डी क्रॉस उत्पाद (यानी क्रॉस उत्पाद वेक्टर के जेड घटक) के आर्क्सिन का उपयोग करें। वह आपको -90 से 90 देगा जो आपको बताएगा कि बाएं या दाएं जाना है या नहीं।

सावधान रहें क्योंकि A क्रॉस B, B क्रॉस A के समान नहीं है।

एक और रणनीति (लेकिन शायद आगे के रूप में सीधे नहीं) atan2 का उपयोग कर दो वैक्टर के "हेडिंग" की गणना करना है और फिर यह पता लगाना है कि क्या ए को एक्स डिग्री पर जाने के लिए बाएं या दाएं पर जाने की जरूरत है ताकि वाई डिग्री पर इंगित किया जा सके।


जवाब देने के लिए धन्यवाद। भविष्य के ब्राउज़रों के लिए स्पष्ट होने के लिए, 2d क्रॉस उत्पाद के परिमाण के व्युत्क्रम साइन को 0 और 90 के बीच मान प्राप्त होगा। 2d क्रॉस उत्पाद के z- घटक के साइन को लेने से वांछित परिणाम मिलते हैं।
त्रुटि 454

@ 45r4, आप बिल्कुल सही हैं, मेरी पोस्ट ठीक कर दी।
तेतराड

1

जहाज को पुनर्निर्देशित करने के लिए वैक्टर का उपयोग करें । यह "स्टीयरिंग बिहेवियर" का काम है - आपको कोण की गणना करने की आवश्यकता नहीं है, बस आपके पास मौजूद वैक्टर का उपयोग करें। यह कम्प्यूटेशनल रूप से बहुत सस्ता है।

वेक्टर w(शिप 1 से शिप 2 तक की वेक्टर ) सभी आवश्यक जानकारी है। जहाज 1 के वेग वेक्टर या जहाज 1 के त्वरण वेक्टर (या सीधे हेडिंग वेक्टर) को संशोधित करें w

यहाँ छवि विवरण दर्ज करें

परिमाण कितनी दूर जहाज 1 बंद के पाठ्यक्रम से बाहर है (कितनी बुरी तरह से वी डब्ल्यू के साथ मेल नहीं खाता) का उपयोग करके पाया जा सकता है ( 1 - dot(v,w))

  • ( dot(v,w)अधिकतम जब vऔर wलाइन अप)
  • ( 1 - dot(v,w)) 0 देता है जब vऔर wपूरी तरह से प्रदान की है, खड़े कर रहे हैं vऔर wसामान्यीकृत कर रहे हैं)

0

सामान्य ज्यामिति के माध्यम से एक वेक्टर के पूर्ण कोण को खोजने का एक सरल तरीका है।

उदाहरण के लिए वेक्टर वी = 2 आई - 3 जे;

x गुणांक = 2 ​​का पूर्ण मूल्य;

y गुणांक का पूर्ण मूल्य = 3;

कोण = अतन (2/3); [कोण 0 से 90 के बीच में होगा]

क्वाड्रेंट एंगल के आधार पर बदला जाएगा।

अगर (x गुणांक <0 और y गुणांक> 0) तो कोण = 180-कोण;

अगर (x गुणांक <0 और y गुणांक <0) तो कोण = 180 + कोण;

अगर (x गुणांक> 0 और y गुणांक <0) तो कोण = 360-कोण;

अगर (x गुणांक> 0 और y गुणांक> 0) तो कोण = कोण;

पहले और दूसरे वैक्टर के कोण खोजने के बाद, दूसरे वेक्टर से पहले वेक्टर कोण को घटाएं। तब आपको दो वैक्टर के बीच निरपेक्ष कोण मिलेगा।


5
यह वास्तव में आपके लिए atan2 () फ़ंक्शन लागू करता है। :)
नाथन रीड 18

@NathanReed, हाँ, लेकिन क्या आप ट्रिगर ओवरहेड से बचने के लिए डॉट उत्पाद के साथ इस विधि का उपयोग नहीं कर सकते हैं?
jdk1.0

0

शायद मुझे थोड़ा अलग सवाल पोस्ट करना चाहिए और इसका जवाब खुद देना चाहिए; यह सबसे करीबी प्रश्न है जो मुझे मिला था।

मैं html कैनवास में 2 डी काम कर रहा हूं, जहां मेरे पास वैक्टर के बजाय रेडियन में रोटेशन कोण हैं। मुझे "चालू शीर्षक" (एच) से "लक्ष्य शीर्षक" (टी) तक पहुंचने के लिए "टर्न एंगल" (टा) की आवश्यकता थी।

यहाँ मेरा समाधान है:

var ta = t - h,
    ata = Math.abs(ta)
;
if (ta > Math.PI) ta = (ta / ata) * (Math.PI - ata)
return ta;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.