ዝርዝር ሁኔታ:

Raspberry Pi እና OpenCV ን በመጠቀም የራስ ገዝ ሌይን-ማቆያ መኪና 7 ደረጃዎች (ከስዕሎች ጋር)
Raspberry Pi እና OpenCV ን በመጠቀም የራስ ገዝ ሌይን-ማቆያ መኪና 7 ደረጃዎች (ከስዕሎች ጋር)

ቪዲዮ: Raspberry Pi እና OpenCV ን በመጠቀም የራስ ገዝ ሌይን-ማቆያ መኪና 7 ደረጃዎች (ከስዕሎች ጋር)

ቪዲዮ: Raspberry Pi እና OpenCV ን በመጠቀም የራስ ገዝ ሌይን-ማቆያ መኪና 7 ደረጃዎች (ከስዕሎች ጋር)
ቪዲዮ: HIKVISION: Как настроить IP-камеру 2024, ሀምሌ
Anonim
Raspberry Pi እና OpenCV ን በመጠቀም የራስ ገዝ ሌይን-ማቆያ መኪና
Raspberry Pi እና OpenCV ን በመጠቀም የራስ ገዝ ሌይን-ማቆያ መኪና

በዚህ ትምህርት ሰጪዎች ውስጥ የራስ ገዝ ሌይን የሚጠብቅ ሮቦት ይተገበራል እና በሚከተሉት ደረጃዎች ያልፋል።

  • የመሰብሰቢያ ክፍሎች
  • የሶፍትዌር ቅድመ ሁኔታዎችን መጫን
  • የሃርድዌር ስብሰባ
  • የመጀመሪያ ሙከራ
  • ሌይን መስመሮችን መለየት እና የመክፈቻ ሲቪን በመጠቀም የመመሪያውን መስመር ማሳየት
  • የፒዲ መቆጣጠሪያን በመተግበር ላይ
  • ውጤቶች

ደረጃ 1 - የመሰብሰቢያ ክፍሎች

የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች
የመሰብሰቢያ ክፍሎች

ከላይ ያሉት ሥዕሎች በዚህ ፕሮጀክት ውስጥ ጥቅም ላይ የዋሉትን ሁሉንም ክፍሎች ያሳያሉ-

  • አርሲ መኪና - የእኔን ያገኘሁት በአገሬ ከሚገኝ የአከባቢ ሱቅ ነው። በ 3 ሞተሮች (2 ለትሮትል እና 1 ለመንዳት) የታጠቀ ነው። የዚህ መኪና ዋነኛው ኪሳራ መሪው በ “መሪ መሪ” እና “ሙሉ መሪ” መካከል የተገደበ መሆኑ ነው። በሌላ አገላለጽ ፣ ከ servo-steering RC መኪኖች በተቃራኒ በተወሰነ ማዕዘን ላይ መምራት አይችልም። ለ Raspberry pi የተነደፈ ተመሳሳይ የመኪና ኪት ከዚህ ማግኘት ይችላሉ።
  • Raspberry pi 3 ሞዴል ለ+ይህ ብዙ የማቀነባበሪያ ደረጃዎችን የሚይዝ የመኪናው አንጎል ነው። እሱ በ 1.4 ጊኸ በሰዓት ባለ ባለአራት ኮር 64 ቢት አንጎለ ኮምፒውተር ላይ የተመሠረተ ነው። የእኔን ያገኘሁት ከዚህ ነው።
  • Raspberry pi 5 mp የካሜራ ሞዱል - 1080p @ 30 fps ፣ 720p @ 60 fps ፣ እና 640x480p 60/90 ቀረፃን ይደግፋል። እንዲሁም በቀጥታ ወደ እንጆሪ ፓይ ውስጥ ሊሰካ የሚችል ተከታታይ በይነገጽን ይደግፋል። ለምስል ማቀናበሪያ ትግበራዎች ምርጥ አማራጭ አይደለም ነገር ግን ለዚህ ፕሮጀክት በቂ ነው እንዲሁም በጣም ርካሽ ነው። የእኔን ያገኘሁት ከዚህ ነው።
  • የሞተር አሽከርካሪ - የዲሲ ሞተሮችን አቅጣጫዎች እና ፍጥነቶች ለመቆጣጠር ያገለግላል። በ 1 ቦርድ ውስጥ የ 2 ዲሲ ሞተሮችን መቆጣጠርን ይደግፋል እና 1.5 ሀን መቋቋም ይችላል።
  • የኃይል ባንክ (አስገዳጅ ያልሆነ) - የራስበሪ ፒን ለብቻው ለማብራት የኃይል ባንክን (በ 5 ቮ ፣ 3 ሀ ደረጃ የተሰጠው) ተጠቅሜያለሁ። አንድ ደረጃ ወደታች መለወጫ (የባንክ መቀየሪያ 3A የውጤት ፍሰት) ከ 1 ምንጭ የራስቤሪ ፓይ ኃይልን ለመጠቀም ጥቅም ላይ መዋል አለበት።
  • 3 ዎች (12 ቮ) የ LiPo ባትሪ - ሊቲየም ፖሊመር ባትሪዎች በሮቦቲክ መስክ ባከናወኑት ምርጥ አፈፃፀም ይታወቃሉ። የሞተር ነጂውን ለማንቀሳቀስ ያገለግላል። የእኔን ከዚህ ገዛሁ።
  • ወንድ ወደ ወንድ እና ሴት ወደ ሴት ዝላይ ሽቦዎች።
  • ባለ ሁለት ጎን ቴፕ - በ RC መኪናው ላይ ያሉትን ክፍሎች ለመጫን ያገለግላል።
  • ሰማያዊ ቴፕ - ይህ የዚህ ፕሮጀክት በጣም አስፈላጊ አካል ነው ፣ መኪናው በመካከላቸው የሚነዳበትን ሁለት ሌይን መስመሮችን ለመሥራት ያገለግላል። የፈለጉትን ማንኛውንም ቀለም መምረጥ ይችላሉ ፣ ግን በዙሪያው ባለው አካባቢ ካሉ ቀለሞች የተለዩ ቀለሞችን እንዲመርጡ እመክራለሁ።
  • የዚፕ ትስስር እና የእንጨት አሞሌዎች።
  • ሾፌር ሾፌር።

ደረጃ 2: RasCberry Pi ላይ OpenCV ን መጫን እና የርቀት ማሳያ ማቀናበር

Raspberry Pi ላይ OpenCV ን መጫን እና የርቀት ማሳያ ማቀናበር
Raspberry Pi ላይ OpenCV ን መጫን እና የርቀት ማሳያ ማቀናበር

ይህ እርምጃ ትንሽ የሚረብሽ እና የተወሰነ ጊዜ ይወስዳል።

OpenCV (ክፍት ምንጭ የኮምፒውተር ራዕይ) ክፍት ምንጭ የኮምፒተር እይታ እና የማሽን መማሪያ ሶፍትዌር ቤተ -መጽሐፍት ነው። ቤተ -መጽሐፍቱ ከ 2500 በላይ የተመቻቹ ስልተ ቀመሮች አሉት። በእርስዎ raspberry pi ላይ openCV ን ለመጫን እና እንዲሁም Raspberry pi OS ን (አሁንም ካላደረጉ) ለመጫን ይህንን በጣም ቀጥተኛ መመሪያ ይከተሉ። እባክዎን ክፍት ሲቪውን የመገንባት ሂደት በደንብ በሚቀዘቅዝ ክፍል ውስጥ 1.5 ሰዓታት ያህል ሊወስድ እንደሚችል ልብ ይበሉ (የአቀነባባሪው የሙቀት መጠን በጣም ስለሚጨምር) ስለዚህ ጥቂት ሻይ ይበሉ እና በትዕግስት ይጠብቁ: ዲ.

ለርቀት ማሳያ ፣ እንዲሁም ከእርስዎ የዊንዶውስ/ማክ መሣሪያ የርቀት እንጆሪ ፓይዎን የርቀት መዳረሻን ለማቀናበር ይህንን መመሪያ ይከተሉ።

ደረጃ 3: ክፍሎችን በአንድ ላይ ማገናኘት

ክፍሎችን በአንድ ላይ ማገናኘት
ክፍሎችን በአንድ ላይ ማገናኘት
ክፍሎችን በአንድ ላይ ማገናኘት
ክፍሎችን በአንድ ላይ ማገናኘት
ክፍሎችን በአንድ ላይ ማገናኘት
ክፍሎችን በአንድ ላይ ማገናኘት

ከላይ ያሉት ሥዕሎች በራትቤሪ ፒ ፣ በካሜራ ሞዱል እና በሞተር ሾፌር መካከል ያለውን ግንኙነት ያሳያሉ። እባክዎን የተጠቀሙባቸው ሞተሮች እያንዳንዳቸው 0.35 ሀ በ 9 ቮ እንደሚወስዱ ያስተውሉ ይህም ለሞተር ሾፌሩ 3 ሞተሮችን በተመሳሳይ ጊዜ እንዲሠራ ያደርገዋል። እና የ 2 የሚንሸራተቱ ሞተሮችን ፍጥነት (1 የኋላ እና 1 ፊት) በትክክል በተመሳሳይ መንገድ መቆጣጠር ስለምፈልግ ፣ ከአንድ ወደብ ጋር አገናኘኋቸው። ባለሁለት ቴፕ በመጠቀም የሞተር አሽከርካሪውን በመኪናው በቀኝ በኩል አስቀመጥኩ። የካሜራ ሞዱሉን በተመለከተ ፣ ከላይ ያለው ምስል እንደሚያሳየው በመጠምዘዣ ቀዳዳዎች መካከል የዚፕ ማሰሪያ አስገባሁ። ከዚያ እኔ እንደፈለግኩ የካሜራውን አቀማመጥ ማስተካከል እንድችል ካሜራውን ከእንጨት አሞሌ ጋር እገጣጠማለሁ። በመኪናው መሃል ላይ ካሜራውን በተቻለ መጠን ለመጫን ይሞክሩ። ከመኪናው ፊት ያለው የእይታ መስክ በተሻለ ሁኔታ እንዲሻሻል ካሜራውን ከመሬት ቢያንስ 20 ሴ.ሜ እንዲያስቀምጡ እመክራለሁ። የ Fritzing schematic ከዚህ በታች ተያይ isል።

ደረጃ 4: የመጀመሪያ ሙከራ

የመጀመሪያ ሙከራ
የመጀመሪያ ሙከራ
የመጀመሪያ ሙከራ
የመጀመሪያ ሙከራ

የካሜራ ሙከራ;

አንዴ ካሜራ ከተጫነ ፣ እና ክፍት ሲቪ ቤተ -መጽሐፍት ከተገነባ ፣ የመጀመሪያ ምስላችንን ለመፈተሽ ጊዜው አሁን ነው! ከፒም ካም ፎቶ አንስተን እንደ “original.jpg” እናስቀምጠዋለን። በ 2 መንገዶች ሊከናወን ይችላል-

1. የተርሚናል ትዕዛዞችን መጠቀም

አዲስ ተርሚናል መስኮት ይክፈቱ እና የሚከተለውን ትዕዛዝ ይተይቡ

raspistill -o original.jpg

ይህ ጸጥ ያለ ምስል ወስዶ በ “/pi/original.jpg” ማውጫ ውስጥ ያስቀምጠዋል።

2. ማንኛውንም የፓይዘን IDE በመጠቀም (እኔ IDLE ን እጠቀማለሁ)

አዲስ ንድፍ ይከፍቱ እና የሚከተለውን ኮድ ይፃፉ

ማስመጣት cv2

ቪዲዮ = cv2. VideoCapture (0) እውነት ሆኖ ሳለ -ret, frame = video.read () frame = cv2.flip (frame, -1) # ምስሉን በአቀባዊ cv2.imshow ('original', frame) cv2. imwrite ('original.jpg', frame) key = cv2.waitKey (1) ቁልፍ ከሆነ == 27: video.release () cv2.destroyAllWindow ()

በዚህ ኮድ ውስጥ ምን እንደ ሆነ እንመልከት። የመጀመሪያው መስመር ሁሉንም ተግባሮቹን ለመጠቀም የእኛን ክፍትCV ቤተ -መጽሐፍት ማስመጣት ነው። የ VideoCapture (0) ተግባር በዚህ ተግባር ከተወሰነው ምንጭ የቀጥታ ቪዲዮን በዥረት መልቀቅ ይጀምራል ፣ በዚህ ሁኔታ 0 ነው ይህም ማለት raspi ካሜራ ማለት ነው። ብዙ ካሜራዎች ካሉዎት የተለያዩ ቁጥሮች መቀመጥ አለባቸው። video.read () እያንዳንዱ ፍሬም ከካሜራ ይመጣል እና “ፍሬም” በሚለው ተለዋዋጭ ውስጥ ያስቀምጠዋል። የተገላቢጦሽ (ካሜራ) ስላይድ (flip) ተግባሩ ምስሉን ከ y- ዘንግ (በአቀባዊ) ጋር ይገለብጣል። imshow () “ኦሪጅናል” በሚለው ቃል የሚመራውን ፍሬሞቻችንን ያሳያል እና ይፃፍ () ፎቶያችንን እንደ ኦሪጅናል-j.webp

ከ openCV ተግባራት ጋር ለመተዋወቅ ፎቶዎን በሁለተኛው ዘዴ እንዲሞክሩት እመክራለሁ። ምስሉ በ//pi/original.jpg”ማውጫ ውስጥ ተቀምጧል። ካሜራዬ ያነሳው የመጀመሪያው ፎቶ ከላይ ይታያል።

የሙከራ ሞተሮች;

የእያንዳንዱ ሞተር የማዞሪያ አቅጣጫን ለመወሰን ይህ እርምጃ አስፈላጊ ነው። በመጀመሪያ ፣ በሞተር አሽከርካሪ የሥራ መርህ ላይ አጭር መግቢያ እናድርግ። ከላይ ያለው ምስል የሞተር ሾፌሩን መቆንጠጥን ያሳያል። ያንቁ ፣ ግብዓት 1 እና ግቤት 2 ከሞተር ኤ መቆጣጠሪያ ጋር የተቆራኙ ናቸው። B ን ያንቁ ፣ ግቤት 3 እና ግቤት 4 ከሞተር ቢ ቁጥጥር ጋር የተቆራኙ ናቸው። የአቅጣጫ ቁጥጥር በ “ግቤት” ክፍል የተቋቋመ ሲሆን የፍጥነት መቆጣጠሪያ በ “አንቃ” ክፍል ተቋቁሟል። ለምሳሌ የሞተር ሀን አቅጣጫ ለመቆጣጠር ፣ ግቤት 1 ን ወደ ከፍተኛ (3.3 ቮ በዚህ መንገድ እንጆሪ ፓይ ስለምንጠቀም) እና ግቤት 2 ን ወደ LOW ያቀናብሩ ፣ ሞተሩ በተወሰነ አቅጣጫ ይሽከረከራል እና ተቃራኒ እሴቶችን በማቀናበር ወደ ግቤት 1 እና ግቤት 2 ፣ ሞተሩ በተቃራኒው አቅጣጫ ይሽከረከራል። ግብዓት 1 = ግቤት 2 = (ከፍተኛ ወይም ዝቅተኛ) ከሆነ ፣ ሞተሩ አይዞርም። ፒኖች የ Pulse Width Modulation (PWM) የግብዓት ምልክትን ከ Rasberry (ከ 0 እስከ 3.3 ቮ) ወስደው ሞተሮቹን በዚሁ መሠረት ያሂዱ። ለምሳሌ ፣ 100% PWM ምልክት ማለት በከፍተኛ ፍጥነት እየሰራን ነው እና 0% PWM ምልክት ማለት ሞተሩ አይሽከረከርም ማለት ነው። የሚከተለው ኮድ የሞተር አቅጣጫዎችን ለመወሰን እና ፍጥነታቸውን ለመፈተሽ ያገለግላል።

የማስመጣት ጊዜ

RPi. 23 # አካላዊ ፒን 16 በ 4 = 24 # አካላዊ ፒን 18 GPIO.setmode (GPIO. BCM) # GPIO.setup (በ 1 ፣ GPIO.out) GPIO.setup (በ 2 ፣ GPIO.out) GPIO ይልቅ የ GPIO ቁጥርን ይጠቀሙ። ማዋቀር (በ 3 ፣ GPIO.out) GPIO.setup (በ 4 ፣ GPIO.out) GPIO.setup (ስሮትል_ኤንቬል ፣ GPIO.out) GPIO.setup (steering_enable ፣ GPIO.out) # መሪ የሞተር መቆጣጠሪያ GPIO.output (በ 1 ፣ GPIO። ከፍተኛ) GPIO.output (በ 2 ፣ GPIO. LOW) መሪነት = GPIO. PWM (steering_enable ፣ 1000) # የመቀየሪያውን ድግግሞሽ ወደ 1000 Hz steering.stop () # ስሮትል ሞተርስ ቁጥጥር GPIO.output (በ3 ፣ GPIO. HIGH) GPIO.output (in4, GPIO. LOW) ስሮትል = GPIO. PWM (ስሮትል_ኤንቬል ፣ 1000) # የመቀየሪያውን ድግግሞሽ ወደ 1000 Hz ስሮትል.stop () ጊዜ ያዘጋጁ። % PWM ምልክት-> (0.25 * የባትሪ ቮልቴጅ) - የመንጃ ኪሳራ steering.start (100) # ሞተሩን በ 100% PWM ምልክት ይጀምራል -> (1 * የባትሪ ቮልቴጅ) - የአሽከርካሪ ኪሳራ ጊዜ። እንቅልፍ (3) ስሮትል።

ይህ ኮድ የሚንቀጠቀጡ ሞተሮችን እና መሪውን ሞተር ለ 3 ሰከንዶች ያካሂዳል ከዚያም ያቆማቸዋል። (የአሽከርካሪው ኪሳራ) በቮልቲሜትር በመጠቀም ሊወሰን ይችላል። ለምሳሌ ፣ የ 100% PWM ምልክት በሞተር ተርሚናል ላይ ሙሉውን የባትሪ ቮልቴጅን መስጠት እንዳለበት እናውቃለን። ነገር ግን ፣ PWM ን ወደ 100%በማቀናጀት ፣ አሽከርካሪው የ 3 ቮ ጠብታ እየፈጠረ መሆኑን እና ሞተሩ በ 12 ቮ ፋንታ 9 ቮ (በትክክል ምን እንደሚያስፈልገኝ!) አግኝቻለሁ። ኪሳራ መስመራዊ አይደለም ማለትም በ 100% የሚደርሰው ኪሳራ ከ 25 በመቶው በጣም የተለየ ነው። ከላይ ያለውን ኮድ ከሠራሁ በኋላ ውጤቶቼ እንደሚከተለው ነበሩ

የመወርወር ውጤቶች-በ in3 = HIGH እና in4 = LOW ከሆነ ፣ የሚገፋፉ ሞተሮች የሰዓት ጠቢብ (CW) ሽክርክሪት ይኖራቸዋል ማለትም መኪናው ወደፊት ይራመዳል። አለበለዚያ መኪናው ወደ ኋላ ይመለሳል።

የማሽከርከር ውጤቶች - በ1 = HIGH እና in2 = LOW ከሆነ ፣ የማሽከርከሪያ ሞተሩ በከፍተኛው ግራ ይሽከረከራል ማለትም መኪናው ወደ ግራ ይመራል። ያለበለዚያ መኪናው በትክክል ይራመዳል። ከአንዳንድ ሙከራዎች በኋላ ፣ የ PWM ምልክቱ 100% ካልሆነ (ማለትም ሞተሩ ሙሉ በሙሉ ወደ ቀኝ ወይም ሙሉ በሙሉ ወደ ግራ ይመራል) መሪ መሪው እንደማያዞር አገኘሁ።

ደረጃ 5 - የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት

የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት
የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት
የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት
የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት
የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት
የሌይን መስመሮችን መለየት እና የራስጌ መስመርን ማስላት

በዚህ ደረጃ የመኪናውን እንቅስቃሴ የሚቆጣጠር ስልተ ቀመር ይብራራል። የመጀመሪያው ምስል አጠቃላይ ሂደቱን ያሳያል። የስርዓቱ ግቤት ምስሎች ናቸው ፣ ውጤቱም ቴታ (የመሪ አንግል በዲግሪዎች) ነው። ያስተውሉ ፣ ሂደቱ በ 1 ምስል ላይ የተከናወነ ሲሆን በሁሉም ክፈፎች ላይ ይደገማል።

ካሜራ ፦

ካሜራው (320 x 240) ጥራት ያለው ቪዲዮ መቅረጽ ይጀምራል። በእያንዳንዱ ክፈፍ ላይ የማቀነባበሪያ ቴክኒኮችን ከተከተለ በኋላ የ fps ጠብታ ስለሚከሰት ጥራት ያለው የፍሬም መጠን (ኤፍፒኤስ) እንዲያገኙ ጥራቱን ዝቅ እንዲያደርጉ እመክራለሁ። ከዚህ በታች ያለው ኮድ የፕሮግራሙ ዋና ዑደት ሲሆን በዚህ ኮድ ላይ እያንዳንዱን እርምጃ ይጨምራል።

ማስመጣት cv2

nump ን እንደ np ቪዲዮ = cv2. VideoCapture (0) video.set (cv2. CAP_PROP_FRAME_WIDTH ፣ 320) # ስፋቱን ወደ 320 ፒ ቪድዮ ያዘጋጁ። እውነት: ረጥ ፣ ፍሬም = ቪዲዮ። () cv2. DestroyAllWindow ()

እዚህ ያለው ኮድ በደረጃ 4 የተገኘውን የመጀመሪያውን ምስል ያሳያል እና ከላይ ባሉት ምስሎች ውስጥ ይታያል።

ወደ HSV የቀለም ቦታ ይለውጡ

አሁን የቪዲዮ ቀረጻን ከካሜራ እንደ ክፈፎች ከወሰዱ በኋላ ቀጣዩ ደረጃ እያንዳንዱን ክፈፍ ወደ ሁዌ ፣ ሙሌት እና እሴት (ኤችኤስቪ) የቀለም ቦታ መለወጥ ነው። ይህን ማድረጉ ዋነኛው ጠቀሜታ በቀለሞች መካከል ባለው የብርሃን ደረጃ መለየት መቻል ነው። እና እዚህ የ HSV ቀለም ቦታ ጥሩ ማብራሪያ ነው። ወደ HSV መለወጥ የሚከናወነው በሚከተለው ተግባር ነው

def convert_to_HSV (ፍሬም) ፦

hsv = cv2.cvtColor (ፍሬም ፣ cv2. COLOR_BGR2HSV) cv2.imshow ("HSV" ፣ hsv) መመለስ hsv

ይህ ተግባር ከዋናው loop ተብሎ ይጠራል እና ፍሬሙን በ HSV ቀለም ቦታ ይመልሳል። በ HSV ቀለም ቦታ በእኔ የተገኘው ክፈፍ ከላይ ይታያል።

ሰማያዊ ቀለም እና ጠርዞችን መለየት;

ምስሉን ወደ ኤችኤስቪ ቀለም ቦታ ከለወጠ በኋላ እኛ የምንፈልገውን ቀለም ብቻ (ማለትም የሌይን መስመሮች ቀለም ስለሆነ ሰማያዊ ቀለም) ለመለየት ጊዜው አሁን ነው። ከኤችኤስቪ ክፈፍ ሰማያዊ ቀለምን ለማውጣት ፣ የተለያዩ ቀለሞች ፣ ሙሌት እና እሴት መገለጽ አለባቸው። በ HSV እሴቶች ላይ የተሻለ ሀሳብ እንዲኖርዎት እዚህ ይመልከቱ። ከአንዳንድ ሙከራዎች በኋላ ፣ ሰማያዊው የላይኛው እና የታችኛው ገደቦች ከዚህ በታች ባለው ኮድ ውስጥ ይታያሉ። እና በእያንዳንዱ ክፈፍ ውስጥ አጠቃላይ ማዛባትን ለመቀነስ ፣ ጠርዞች የሚገኙት የከረጢት ጠርዝ መመርመሪያን በመጠቀም ብቻ ነው። ስለ ካኒ ጠርዝ የበለጠ እዚህ ይገኛል። የአውራ ጣት ደንብ ከ 1: 2 ወይም ከ 1: 3 ጋር የ Canny () ተግባር መለኪያዎች መምረጥ ነው።

def dete_edges (ፍሬም) ፦

Lower_blue = np.array ([90, 120, 0] ፣ dtype = "uint8") # የታችኛው ሰማያዊ ቀለም ገደብ የላይኛው_blue = np.array ([150 ፣ 255 ፣ 255] ፣ dtype = "uint8") # የላይኛው ገደብ ሰማያዊ ቀለም ጭምብል = cv2.inRange (hsv ፣ bottom_blue ፣ upper_blue) # ይህ ጭንብል ሁሉንም ያጣራል ነገር ግን ሰማያዊ # የጠርዝ ጠርዞችን = cv2 መለየት። ካኒ (ጭምብል ፣ 50 ፣ 100)

ይህ ተግባር የ HSV የቀለም ቦታ ክፈፍ እንደ መለኪያ ከሚወስደው እና የጠርዙን ክፈፍ ከሚመልሰው ከዋናው loop ተብሎ ይጠራል። ያገኘሁት የጠርዝ ፍሬም ከላይ ይገኛል።

የፍላጎት ክልል (ROI) ይምረጡ ፦

በፍሬም 1 ክልል ላይ ብቻ ለማተኮር የፍላጎት ክልል መምረጥ ወሳኝ ነው። በዚህ ሁኔታ መኪናው በአከባቢው ውስጥ ብዙ እቃዎችን እንዲያይ አልፈልግም። እኔ ብቻ መኪናው ሌይን መስመሮች ላይ እንዲያተኩር እና ሌላ ማንኛውንም ነገር ችላ እንዲል እፈልጋለሁ። P. S: የማስተባበር ስርዓት (x እና y axes) የሚጀምረው ከላይኛው ግራ ጥግ ነው። በሌላ አነጋገር ነጥቡ (0 ፣ 0) የሚጀምረው ከላይኛው ግራ ጥግ ነው። y- ዘንግ ቁመቱ መሆን እና የ x ዘንግ ስፋት መሆን። ከታች ያለው ኮድ በማዕቀፉ የታችኛው ግማሽ ላይ ብቻ ለማተኮር የፍላጎት ክልልን ይመርጣል።

def ክልል_of_ ፍላጎት (ጠርዞች) ፦

ቁመት ፣ ስፋት = ጠርዞች። ቅርፅ # የጠርዙ ክፈፍ ጭንብል ቁመት እና ስፋት ያወጣል = np.zeros_like (ጠርዞች) # የጠርዙ ክፈፍ ተመሳሳይ ልኬቶች ያሉት ባዶ ማትሪክስ ያድርጉ # በማያ ገጹ ታችኛው ግማሽ ላይ ብቻ ያተኩሩ # መጋጠሚያዎቹን ይግለጹ 4 ነጥቦች (የታችኛው ግራ ፣ የላይኛው ግራ ፣ የላይኛው ቀኝ ፣ የታችኛው ቀኝ) ባለብዙ ጎን = np.array (

ይህ ተግባር የጠርዙን ፍሬም እንደ ልኬት ወስዶ 4 ቅድመ -ነጥቦችን የያዘ ባለ ብዙ ጎን ይሳሉ። እሱ ባለ ብዙ ጎን ውስጥ ባለው ላይ ብቻ ያተኩራል እና ከእሱ ውጭ ያለውን ሁሉ ችላ ይላል። የእኔ የፍላጎት ክልል ከላይ ይታያል።

የመስመር ክፍሎችን መለየት;

የሃው ትራንስ (ትራንስፎርሜሽን) ከጠርዝ ክፈፍ የመስመር ክፍሎችን ለመለየት ጥቅም ላይ ይውላል። የሂው ትራንስፎርሜሽን ማንኛውንም ቅርፅ በሂሳብ መልክ የመለየት ዘዴ ነው። በተወሰኑ ድምጾች መሠረት የተዛባ ቢሆንም እንኳ ማንኛውንም ነገር ማለት ይቻላል መለየት ይችላል። ለሃው ትራንስፎርሜሽን ታላቅ ማጣቀሻ እዚህ ይታያል። ለዚህ ትግበራ ፣ cv2. HoughLinesP () ተግባር በእያንዳንዱ ክፈፍ ውስጥ መስመሮችን ለመለየት ጥቅም ላይ ይውላል። ይህ ተግባር የሚወስዳቸው አስፈላጊ መለኪያዎች-

cv2. HoughLinesP (ፍሬም ፣ ሮ ፣ ቴታ ፣ ደቂቃ_መድረሻ ፣ ደቂቃ ፣ ርዝመት ፣ maxLineGap)

  • ፍሬም - መስመሮችን ለመለየት የምንፈልገው ክፈፍ ነው።
  • rho: በፒክሴሎች ውስጥ ያለው የርቀት ትክክለኛነት ነው (ብዙውን ጊዜ = 1 ነው)
  • theta: በራዲያኖች ውስጥ የማዕዘን ትክክለኛነት (ሁል ጊዜ = np.pi/180 ~ 1 ዲግሪ)
  • min_threshold: እንደ መስመር እንዲቆጠር ዝቅተኛ ድምጽ መስጠት አለበት
  • minLineLength: በፒክሰሎች ውስጥ ዝቅተኛው የመስመር ርዝመት። ከዚህ ቁጥር ያነሰ ማንኛውም መስመር እንደ መስመር አይቆጠርም።
  • maxLineGap: እንደ 1 መስመር እንዲታከም በ 2 መስመሮች መካከል በፒክሴሎች ውስጥ ያለው ከፍተኛ ክፍተት። (እየተጠቀምኩበት ያለው ሌይን መስመሮች ምንም ክፍተት ስለሌላቸው በእኔ ሁኔታ ውስጥ ጥቅም ላይ አይውልም)።

ይህ ተግባር የአንድ መስመር መጨረሻ ነጥቦችን ይመልሳል። ሁው ትራንስ በመጠቀም መስመሮችን ለመለየት የሚከተለው ተግባር ከዋናው ዑደትዬ ተጠርቷል-

def dete_line_segments (cropped_edges) ፦

rho = 1 theta = np.pi / 180 min_threshold = 10 line_segments = cv2. HoughLinesP (cropped_edges, rho, theta, min_threshold, np.array (), minLineLength = 5, maxLineGap = 0) lineline_segments

አማካይ ተዳፋት እና ጣልቃ ገብነት (m, b):

የመስመር ቀመር በ y = mx + b የተሰጠ መሆኑን ያስታውሱ። የመስመሩ ቁልቁለት የት ነው እና ለ-y-intercept ነው። በዚህ ክፍል ፣ ሁው ትራንስፎርምን በመጠቀም የተገኙት የመስመሮች ተዳፋት እና የተጠለፉ አማካዮች ይሰላሉ። ይህን ከማድረግዎ በፊት ፣ ከላይ የሚታየውን የመጀመሪያውን የፍሬም ፎቶ እንይ። የግራ መስመሩ ወደላይ የሚወጣ ይመስላል ስለዚህ አሉታዊ ተዳፋት አለው (የአስተባባሪውን ስርዓት መነሻ ነጥብ ያስታውሱ?)። በሌላ አነጋገር ፣ የግራ መስመር መስመር x1 <x2 እና y2 x1 እና y2> y1 አለው ይህም አዎንታዊ ቁልቁል ይሰጣል። ስለዚህ ፣ አዎንታዊ ተዳፋት ያላቸው ሁሉም መስመሮች የቀኝ መስመር ነጥቦች እንደሆኑ ይቆጠራሉ። በአቀባዊ መስመሮች (x1 = x2) ፣ ቁልቁል ማለቂያ የሌለው ይሆናል። በዚህ ሁኔታ ፣ ስህተት እንዳያገኝ ሁሉንም ቀጥ ያሉ መስመሮችን እንዘልላለን። ለዚህ ማወቂያ የበለጠ ትክክለኛነትን ለመጨመር እያንዳንዱ ክፈፍ በሁለት ክልሎች (በቀኝ እና በግራ) በ 2 የድንበር መስመሮች ተከፍሏል። ከትክክለኛው የድንበር መስመር የሚበልጡ ሁሉም ስፋት ነጥቦች (ኤክስ-ዘንግ ነጥቦች) ፣ ከቀኝ መስመር ስሌት ጋር የተቆራኙ ናቸው። እና ሁሉም ስፋት ነጥቦች ከግራ ወሰን መስመር ያነሱ ከሆኑ ፣ ከግራ ሌይን ስሌት ጋር የተቆራኙ ናቸው። የሚከተለው ተግባር ፍሬሙን በማቀነባበር እና የሃው ለውጥን በመጠቀም የተገኙትን የሌይን ክፍሎች ይወስዳል እና የሁለት መስመር መስመሮችን አማካይ ተዳፋት እና መጥለፍ ይመልሳል።

def አማካይ_ስሎፕ_አስተያየት (ፍሬም ፣ የመስመር_ ክፍሎች)

lane_lines = የ line_segments ምንም ካልሆነ ህትመት ("ምንም የመስመር ክፍል አልተገኘም") የ lane_lines ቁመት ፣ ስፋት ፣ _ = frame.shape left_fit = right_fit = ወሰን = left_region_boundary = ስፋት * (1 - ወሰን) right_region_boundary = በመስመር_ክፍል ውስጥ ለ line_segment ስፋት * ወሰን ለ x1 ፣ y1 ፣ x2 ፣ y2 በ line_segment: x1 == x2: ማተም (“ቀጥ ያሉ መስመሮችን መዝለል (ቁልቁለት = ወሰን የሌለው)”) ተስማሚ ቀጥል = np.polyfit ((x1 ፣ x2), (y1, y2) ፣ 1) ተዳፋት = (y2 - y1) / (x2 - x1) መቋረጥ = y1 - (ቁልቁል * x1) ቁልቁል ከሆነ <0: x1 <left_region_boundary and x2 right_region_boundary and x2> right_region_boundary: right_fit. append ((ተዳፋት ፣ መጥለፍ)) left_fit_average = np.average (left_fit, axis = 0) len (left_fit)> 0: lane_lines.append (make_points (frame, left_fit_average)) right_fit_average = np.average (right_fit, axis = 0) ከሆነ len (right_fit)> 0: lane_lines.append (make_points (ፍሬም ፣ right_fit_average)) # lane_lines የቀኝ እና የግራ መስመር መስመሮች መጋጠሚያዎችን ያካተተ ባለ 2-ዲ ድርድር ነው # ላን e_lines =

make_points () ለአማካይ_ስሎፔ_ኢንተርፕራይዝ () ተግባር የረድፍ መስመሮችን (ከስር እስከ ክፈፉ መሃል) የተገደቡ መጋጠሚያዎችን የሚመልስ ረዳት ተግባር ነው።

def make_points (ፍሬም ፣ መስመር) ፦

ቁመት ፣ ስፋት ፣ _ = የክፈፍ ቅርፅ ቁልቁለት ፣ ጣልቃ ገብነት = መስመር y1 = ከፍታው # ከፍታው የታችኛው ክፍል y2 = int (y1 / 2) # ቁልቁል ከሆነ = ከማዕቀፉ መሃል ላይ ነጥቦችን ያድርጉ == 0: ቁልቁል = 0.1 x1 = int ((y1 - መጥለፍ) / ቁልቁል) x2 = int ((y2 - መጥለፍ) / ቁልቁል) መመለስ

በ 0 መከፋፈልን ለመከላከል አንድ ሁኔታ ቀርቧል። ተዳፋት = 0 ማለት y1 = y2 (አግድም መስመር) ከሆነ ፣ ቁልቁለቱን በ 0. አቅራቢያ ያለውን እሴት ይስጡ ይህ በአልጎሪዝም አፈፃፀም ላይ ተጽዕኖ አያሳድርም እንዲሁም የማይቻል ጉዳይን ይከላከላል (በ 0 መከፋፈል)።

በፍሬሞቹ ላይ የሌይን መስመሮችን ለማሳየት የሚከተለው ተግባር ጥቅም ላይ ይውላል።

def display_lines (ክፈፍ ፣ መስመሮች ፣ line_color = (0, 255, 0) ፣ line_width = 6): # የመስመር ቀለም (ቢ ፣ ጂ ፣ አር)

line_image = np.zeros_like (ፍሬም) መስመሮች ከሌሉ በመስመሮች ውስጥ - ለ x1 ፣ y1 ፣ x2 ፣ y2 በመስመር ፦ cv2.line (line_image ፣ (x1 ፣ y1) ፣ (x2 ፣ y2) ፣ line_color ፣ line_width / line_image = cv2.addWeededed (ፍሬም ፣ 0.8 ፣ line_image ፣ 1 ፣ 1) ተመላሽ መስመር_ኢሜጅ

cv2.addWeighted () ተግባር የሚከተሉትን መለኪያዎች ይወስዳል እና ሁለት ምስሎችን ለማጣመር ጥቅም ላይ ይውላል ፣ ግን እያንዳንዳቸው ክብደትን በመስጠት።

cv2.addWeededed (ምስል 1 ፣ አልፋ ፣ ምስል 2 ፣ ቤታ ፣ ጋማ)

እና የሚከተለውን ቀመር በመጠቀም የውጤቱን ምስል ያሰላል

ውፅዓት = አልፋ * ምስል 1 + ቤታ * ምስል 2 + ጋማ

ስለ cv2.addWeighted () ተግባር ተጨማሪ መረጃ እዚህ ተገኝቷል።

የራስጌ መስመርን አስል እና አሳይ

ለሞተር ሞተሮቻችን ፍጥነቶችን ከመተግበራችን በፊት ይህ የመጨረሻው ደረጃ ነው። የርዕሱ መስመር መሪውን ሞተር የሚሽከረከርበትን አቅጣጫ የመስጠት እና የሚገፋፉትን ሞተሮች የሚሰሩበትን ፍጥነት የመስጠት ኃላፊነት አለበት። የርዕስ መስመርን ማስላት ንጹህ ትሪጎኖሜትሪ ፣ ታን እና አታን (ታን^-1) ትሪጎኖሜትሪክ ተግባራት ጥቅም ላይ ይውላሉ። አንዳንድ ከባድ ሁኔታዎች ካሜራው አንድ መስመር መስመር ብቻ ሲያገኝ ወይም ማንኛውንም መስመር በማይለይበት ጊዜ ነው። እነዚህ ሁሉ ጉዳዮች በሚከተለው ተግባር ውስጥ ይታያሉ

def get_steering_angle (ፍሬም ፣ ሌይን_ላይን) ፦

ቁመት ፣ ስፋት ፣ _ = ፍሬም። ቅርፅ ሌን (lane_lines) == 2: # ሁለት ሌይን መስመሮች ከተገኙ _ ፣ _ ፣ ግራ_x2 ፣ _ = ሌን_ላይን [0] [0] # ከግራ መስመር x2 ከ lane_lines ድርድር _ ፣ _ ማውጣት ፣ right_x2 ፣ _ = lane_lines [1] [0] # ሌን_ላይን ድርድር mid = int (ስፋት / 2) x_offset = (left_x2 + right_x2) / 2 - mid y_offset = int (ቁመት / 2) elif len (lane_lines) # ቀኝ x2 ን ያውጡ።) == 1: # አንድ መስመር ብቻ ከተገኘ x1 ፣ _ ፣ x2 ፣ _ = lane_lines [0] [0] x_offset = x2 - x1 y_offset = int (ቁመት / 2) elif len (lane_lines) == 0: # መስመር ካልተገኘ x_offset = 0 y_offset = int (ቁመት / 2) angle_to_mid_radian = math.atan (x_offset / y_offset) angle_to_mid_deg = int (angle_to_mid_radian * 180.0 / math.pi) steering_angle = angle_to_mid_de_mid_de

x_offset በመጀመሪያው ጉዳይ አማካይ ((ቀኝ x2 + ግራ x2) / 2) ከማያ ገጹ መሃል ምን ያህል ይለያል። y_offset ሁል ጊዜ ቁመት እንዲሆን ተወስዷል / 2. ከላይ ያለው የመጨረሻው ምስል የአርዕስት መስመር ምሳሌን ያሳያል። angle_to_mid_radians ከላይ ባለው ምስል ላይ ከሚታየው “theta” ጋር ተመሳሳይ ነው። Steering_angle = 90 ከሆነ ፣ ይህ ማለት መኪናው ከ “ቁመት / 2” መስመር ጋር ቀጥ ያለ የርዕስ መስመር አለው እና መኪናው ያለ መሪ መሪ ወደፊት ይራመዳል ማለት ነው። Steering_angle> 90 ከሆነ ፣ መኪናው ወደ ቀኝ መምራት አለበት ፣ አለበለዚያ ወደ ግራ መምራት አለበት። የርዕስ መስመሩን ለማሳየት የሚከተለው ተግባር ጥቅም ላይ ይውላል።

def display_heading_line (ፍሬም ፣ steering_angle ፣ line_color = (0 ፣ 0 ፣ 255) ፣ line_width = 5)

title_image = np.zeros_like (ፍሬም) ቁመት ፣ ስፋት ፣ _ = frame.shape steering_angle_radian = steering_angle / 180.0 * math.pi x1 = int (ስፋት / 2) y1 = ቁመት x2 = int (x1 - ቁመት / 2 / math.tan (steering_angle_radian)) y2 = int (ቁመት / 2) cv2.line (የርዕስ_ምስል ፣ (x1 ፣ y1) ፣ (x2 ፣ y2) ፣ line_color ፣ line_width) head_image = cv2.addWeighted (ፍሬም ፣ 0.8 ፣ አርዕስት ምስል ፣ 1 ፣ 1) ርዕስ_ምስል ተመለስ

ከላይ ያለው ተግባር የርዕሱ መስመር የሚወጣበትን ፍሬም እና መሪውን አንግል እንደ ግብዓት ይወስዳል። የርዕስ መስመሩን ምስል ይመልሳል። በእኔ ጉዳይ ውስጥ የተወሰደው የርዕስ መስመር ክፈፍ ከላይ ባለው ምስል ላይ ይታያል።

ሁሉንም ኮድ በአንድ ላይ ማዋሃድ;

ኮዱ አሁን ለመሰብሰብ ዝግጁ ነው። የሚከተለው ኮድ እያንዳንዱን ተግባር የሚጠራውን የፕሮግራሙን ዋና ዙር ያሳያል

ማስመጣት cv2

nump ን እንደ np ቪዲዮ = cv2. VideoCapture (0) video.set (cv2. CAP_PROP_FRAME_WIDTH ፣ 320) video.set (cv2. CAP_PROP_FRAME_HEIGHT ፣ 240) እውነት ሆኖ ሳለ - ret ፣ frame = video.read () frame = cv2.flip (ፍሬም ፣ -1) #ተግባሮችን በመጥራት hsv = ወደ_ኤችኤስቪ (ፍሬም) ጠርዞች = የመለወጫ_ኤድስ (hsv) roi = ክልል_ፍላጎት (ጠርዞች) የመስመር_ክፍሎች = detect_line_segments (roi) ሌን_ላይንስ = አማካይ_ስሎፕ_ኢንተርፕሽን (ፍሬም ፣ የመስመር_ ክፍሎች) ሌይን_ላይን_ላይን (መስመር) መስመሮች (መስመር) መስመሮች = get_steering_angle (ፍሬም ፣ ሌን_ላይንስ) ርዕስ_ኢሜጅ = የማሳያ_አይን_መመሪያ_ላይን (lane_lines_image ፣ steering_angle) ቁልፍ = cv2.waitKey (1) ቁልፍ ከሆነ == 27 ፦ ቪዲዮውን ይሰብሩ። መልቀቅ () cv2.destroyAllWindow ()

ደረጃ 6: የፒ.ዲ. መቆጣጠሪያን መተግበር

የፒ.ዲ. መቆጣጠሪያን በመተግበር ላይ
የፒ.ዲ. መቆጣጠሪያን በመተግበር ላይ

አሁን ለሞተር ሞተሮች ለመመገብ የእኛ የማሽከርከሪያ አንግል ዝግጁ ነን። ቀደም ሲል እንደተጠቀሰው ፣ የማሽከርከሪያ አንግል ከ 90 በላይ ከሆነ ፣ መኪናው ወደ ቀኝ መዞር አለበት አለበለዚያ ወደ ግራ መዞር አለበት። ማዕዘኑ ከ 90 በላይ ከሆነ መሪ መሪውን ወደ ቀኝ የሚያዞር ቀላል ኮድ ተግባራዊ አደረግሁ እና የማሽከርከሪያው አንግል በቋሚ የማወዛወዝ ፍጥነት ከ (10% PWM) ከ 90 በታች ከሆነ ግን ብዙ ስህተቶችን አግኝቻለሁ። ያገኘሁት ዋናው ስህተት መኪናው ወደ ማናቸውም መዞር ሲቀርብ ፣ የማሽከርከሪያው ሞተር በቀጥታ ይሠራል ነገር ግን የሚገፋፉ ሞተሮች ይጨናነቃሉ። የማዞሪያ ፍጥነቱን (20% PWM) ለመሆን ሞክሬ ነበር ነገር ግን ሮቦቱ ከመንገዶቹ በመውጣቱ አብቅቷል። የማሽከርከሪያው አንግል በጣም ትልቅ ከሆነ እና የማሽከርከሪያው አንግል ትልቅ ካልሆነ ከዚያ መኪናው ወደ 90 ዲግሪ ሲጠጋ (ቀጥ ብሎ ሲንቀሳቀስ) ፍጥነቱን ወደ መጀመሪያው እሴት ዝቅ የሚያደርግ ከሆነ የፍጥነቱን ፍጥነት ብዙ የሚጨምር ነገር ያስፈልገኝ ነበር። መፍትሄው የፒዲ መቆጣጠሪያን መጠቀም ነበር።

የፒአይዲ ተቆጣጣሪ የተመጣጠነ ፣ የተቀናጀ እና የመነሻ መቆጣጠሪያን ያመለክታል። ይህ ዓይነቱ የመስመር ተቆጣጣሪዎች በሮቦቶች ትግበራዎች ውስጥ በሰፊው ጥቅም ላይ ውለዋል። ከላይ ያለው ምስል የተለመደው የ PID ግብረመልስ መቆጣጠሪያ ዑደት ያሳያል። የዚህ ተቆጣጣሪ ዓላማ በአንዳንድ ሁኔታዎች መሠረት ተክሉን የሚያበሩ ወይም የሚያጠፉ “አብራ - አጥፋ” ተቆጣጣሪዎች ሳይሆን እጅግ በጣም ቀልጣፋ በሆነ መንገድ ወደ “setpoint” መድረስ ነው። አንዳንድ ቁልፍ ቃላት መታወቅ አለባቸው

  • Setpoint: የእርስዎ ስርዓት እንዲደርስበት የሚፈልጉት ተፈላጊ እሴት ነው።
  • ትክክለኛ እሴት - በአነፍናፊ የተገነዘበው ትክክለኛ እሴት።
  • ስህተት - በ setpoint እና በእውነተኛ እሴት መካከል ያለው ልዩነት (ስህተት = Setpoint - ትክክለኛ እሴት)።
  • ቁጥጥር የሚደረግበት ተለዋዋጭ - ከስሙ ፣ ለመቆጣጠር የሚፈልጉት ተለዋዋጭ።
  • Kp: የተመጣጠነ ቋሚ።
  • ኪ - የተዋሃደ ቋሚ።
  • Kd: የመነጨ ቋሚ።

በአጭሩ ፣ የፒአይዲ ቁጥጥር ስርዓት loop እንደሚከተለው ይሠራል

  • ተጠቃሚው ስርዓቱ እንዲደርስበት የሚያስፈልገውን የተቀመጠውን ነጥብ ይገልጻል።
  • ስህተቱ ይሰላል (ስህተት = setpoint - እውን)።
  • ፒ መቆጣጠሪያ ከስህተት እሴት ጋር ተመጣጣኝ የሆነ እርምጃን ያመነጫል። (ስህተት ይጨምራል ፣ የፒ እርምጃ እንዲሁ ይጨምራል)
  • እኔ ተቆጣጣሪው ስህተቱን በጊዜ ሂደት ያዋህዳል ፣ ይህም የስርዓቱን ቋሚ ሁኔታ ስህተት ያስወግዳል ነገር ግን ከመጠን በላይ መጠኑን ይጨምራል።
  • ዲ መቆጣጠሪያ በቀላሉ ለስህተቱ የጊዜ አመጣጥ ነው። በሌላ አነጋገር የስህተቱ ቁልቁለት ነው። ከስህተቱ አመጣጥ ጋር ተመጣጣኝ የሆነ እርምጃ ይወስዳል። ይህ ተቆጣጣሪ የስርዓቱን መረጋጋት ይጨምራል።
  • የመቆጣጠሪያው ውጤት የሦስቱ ተቆጣጣሪዎች ድምር ይሆናል። ስህተቱ 0 ከሆነ የመቆጣጠሪያው ውጤት 0 ይሆናል።

የፒአይዲ መቆጣጠሪያ ታላቅ ማብራሪያ እዚህ ይገኛል።

ወደ ሌይን ማቆያ መኪና ስመለስ ፣ የእኔ ቁጥጥር ያለው ተለዋዋጭ ፍጥነት እየገፋ ነበር (መሪው በቀኝ ወይም በግራ ሁለት ግዛቶች ብቻ ስላሉት)። የስህተት ለውጥ በጣም ትልቅ ከሆነ (ማለትም ትልቅ መዛባት) እና ይህ ስህተት ከተለወጠ መኪናውን ያዘገየዋል ምክንያቱም የ PD መቆጣጠሪያ ለዚህ ዓላማ ጥቅም ላይ ውሏል። ተቆጣጣሪ ፦

  • የተቀመጠውን ነጥብ ወደ 90 ዲግሪዎች ያቀናብሩ (ሁል ጊዜ መኪናው በቀጥታ እንዲንቀሳቀስ እፈልጋለሁ)
  • ከመካከለኛው የመለያየት አንግል አስልቷል
  • ማፈናቀሉ ሁለት መረጃዎችን ይሰጣል - ስህተቱ ምን ያህል ትልቅ ነው (የመዛባት መጠን) እና መሪ ሞተሩ የሚወስደው አቅጣጫ (የመለየት ምልክት)። ማዛባት አዎንታዊ ከሆነ ፣ መኪናው ወደ ቀኝ መምራት አለበት ፣ አለበለዚያ ወደ ግራ መምራት አለበት።
  • ማፈናቀል አሉታዊም ሆነ አዎንታዊ ስለሆነ የ “ስህተት” ተለዋዋጭ ተለይቶ የሚታወቅ እና ሁልጊዜ ከተለዋዋጭ ፍፁም እሴት ጋር እኩል ነው።
  • ስህተቱ በቋሚ Kp ይባዛል።
  • ስህተቱ የጊዜን ልዩነት ያካሂዳል እና በቋሚ Kd ይባዛል።
  • የሞተር ፍጥነቶች ተዘምነዋል እና ምልልሱ እንደገና ይጀምራል።

የሚንቀጠቀጡ ሞተሮችን ፍጥነት ለመቆጣጠር የሚከተለው ኮድ በዋናው ዑደት ውስጥ ጥቅም ላይ ውሏል።

ፍጥነት = 10 # የአሠራር ፍጥነት በ % PWM

# ተለዋዋጮች እያንዳንዱን loop lastTime = 0 lastError = 0 # PD ቋሚዎች Kp = 0.4 Kd = Kp * 0.65 እውነት ሆኖ ሳለ አሁን = time.time () # የአሁኑ ጊዜ ተለዋዋጭ dt = now - lastTime deviation = steering_angle - 90 # ተመጣጣኝ ወደ ማዕዘን_to_mid_deg ተለዋዋጭ ስህተት = abs (deviation) ከሆነ መዛባት -5: # ባለ 10 ዲግሪ የስህተት ክልል ልዩነት = 0 ስህተት = 0 GPIO.output (በ 1 ፣ GPIO. LOW) GPIO.output (በ 2 ፣ GPIO). LOW) steering.stop () elif deviation> 5: # መቀዛቀዝ አዎንታዊ ከሆነ GPIO.output (in1, GPIO. LOW) GPIO.output (in2, GPIO. HIGH) steering.start (100) elif deviation < -5: መዛባት አሉታዊ ከሆነ GPIO.output (in1, GPIO. HIGH) GPIO.output (in2, GPIO. LOW) steering.start (100) derivative = kd * (ስህተት - lastError) / dt proportional = kp * ስህተት PD = int (ፍጥነት + የመነሻ + ተመጣጣኝ) spd = abs (PD) spd> 25 ከሆነ spd = 25 throttle.start (spd) lastError = ስህተት lastTime = time.time ()

ስህተቱ በጣም ትልቅ ከሆነ (ከመካከለኛው ያለው ልዩነት ከፍተኛ ነው) ፣ የተመጣጠነ እና የመነሻ እርምጃዎች ከፍተኛ ናቸው። ስህተት ወደ 0 ሲቃረብ (ከመካከለኛው ማነጣጠሉ ዝቅተኛ ነው) ፣ የመነሻው እርምጃ በተቃራኒው ይሠራል (ተዳፋት አሉታዊ ነው) እና የስርዓቱን መረጋጋት ለመጠበቅ የመወዛወዝ ፍጥነት ዝቅተኛ ይሆናል። ሙሉ ኮዱ ከዚህ በታች ተያይ isል።

ደረጃ 7 ውጤቶች

ከላይ ያሉት ቪዲዮዎች ያገኘሁትን ውጤት ያሳያሉ። እሱ ተጨማሪ ማስተካከያ እና ተጨማሪ ማስተካከያዎችን ይፈልጋል። እኔ በአውታረ መረቡ ላይ ያለው የቪዲዮ ዥረት ከፍተኛ መዘግየት ስለነበረበት እና አብሮ ለመስራት በጣም ተስፋ አስቆራጭ ስለነበረ የ raspberry pi ን ከኤልሲዲ ማሳያ ማያ ገጽ ጋር አገናኘው። ትራኩን ለመሳል የአረፋ ሰሌዳዎችን እጠቀም ነበር።

ይህንን ፕሮጀክት የተሻለ ለማድረግ የእርስዎን ምክሮች ለመስማት እጠብቃለሁ! አንዳንድ አስተማሪዎች ለእርስዎ አዲስ መረጃ ለመስጠት በቂ እንደነበሩ ተስፋ አደርጋለሁ።

የሚመከር: