Inhoudsopgave:

Nauwkeurige Wiimote Light Gun voor Raspberry PI - Ajarnpa
Nauwkeurige Wiimote Light Gun voor Raspberry PI - Ajarnpa

Video: Nauwkeurige Wiimote Light Gun voor Raspberry PI - Ajarnpa

Video: Nauwkeurige Wiimote Light Gun voor Raspberry PI - Ajarnpa
Video: Вуди Норрис изобретает поразительные вещи 2024, November
Anonim
Nauwkeurige Wiimote Light Gun voor Raspberry PI
Nauwkeurige Wiimote Light Gun voor Raspberry PI
Nauwkeurige Wiimote Light Gun voor Raspberry PI
Nauwkeurige Wiimote Light Gun voor Raspberry PI

Normaal gesproken is de Wii-afstandsbediening die als lichtpistool wordt gebruikt niet nauwkeurig genoeg voor retro-games zoals NES Duck Hunt, omdat de Wii-afstandsbediening in feite niet het punt op de tv selecteert waarop hij is gericht. Het kan niet! De Wii-afstandsbediening heeft een infraroodcamera aan de voorkant die de lijn van infrarood-LED's in de sensorbalk ziet, maar hij kan niet weten hoe ver (of in welke richting) de tv van de bar is of hoe groot de tv is. Emulators en games omzeilen dit door een dradenkruis of andere richtindicatoren te tonen, maar dat is geen nauwkeurige schietervaring.

Om de Wii-afstandsbediening te laten werken als een nauwkeurig lichtpistool waarmee je kunt kijken om een doel op een tv te selecteren, zijn vier infrarood-LED's nodig die zijn gerangschikt in een bekend vierhoekig patroon (geen rechte lijn) in hetzelfde vlak als de tv. De Wii-afstandsbediening ziet dan de vier LED's en het camerabeeld kan worden gebruikt om een homografie te berekenen waarmee we kunnen achterhalen waar de camera naar wijst.

De hardware voor dit project is eenvoudig. Er zijn vier infrarood-LED's in eenvoudige 3D-geprinte behuizingen die aan de boven- en onderkant van de tv-behuizing kunnen worden gelijmd en op een USB-oplader kunnen worden aangesloten. En voor het geval je geen Wii-pistoolbehuizing hebt, heb ik een eenvoudig 3D-geprint handvat en vizieren die je aan de Wii-afstandsbediening kunt bevestigen (hoewel ik om plastic te besparen de mijne een hybride heb gemaakt tussen hout en 3D-geprint plastic).

De op python gebaseerde software was moeilijker te maken dan de hardware en is momenteel alleen voor Linux. Het kalibreert de LED's en de Wii-afstandsbediening en gebruikt vervolgens homografieberekeningen om een absolute muis te emuleren die vrij goed werkt in Retroarch's fceumm NES-emulator (en waarschijnlijk enkele andere emulators) op mijn Raspberry PI 3B+.

Benodigdheden

  • Wii-afstandsbediening
  • Vier 940nm 5mm infrarood LED's
  • Oude USB-kabel met een werkende type A-stekker
  • Raspberry PI 3 of andere Linux-computer met Bluetooth-ondersteuning
  • 3D-printer en filament (optioneel)

Stap 1: Infrarood LED-ketting

Infrarood LED-ketting
Infrarood LED-ketting
Infrarood LED-ketting
Infrarood LED-ketting

Koop een oude USB-kabel met een werkende mannelijke A-aansluiting (meestal breken de oplaadkabels van mijn telefoon aan het micro-USB-uiteinde, dus ik heb overgebleven kabels met een werkende mannelijke A-aansluiting). Eigenlijk is het zelfs OK als de datakabels kapot zolang de elektriciteitskabels werken. Snijd het andere uiteinde af. In theorie zou de rode kabel +5V moeten zijn en de zwarte zou geaard moeten zijn, maar controleer dit met een multimeter (stekker in een oplader, en controleer dan de spanning tussen de rode en zwarte draden).

Omdat infrarood-LED's een spanningsval van 1,2-1,3 V hebben, heb ik er zojuist vier in serielus aan de USB-kabel gesoldeerd. Zorg ervoor dat de draden die u soldeert lang genoeg zijn zodat u LED's aan de onderkant van de tv en twee aan de bovenkant kunt plaatsen, met een behoorlijke hoeveelheid horizontale ruimte tussen de LED's (ongeveer 10 inch of zo).

Meer precies om de LED-lus te maken:

  • soldeer de minkant (kathode, kortere poot, met platte rand) van de eerste LED aan de +5V USB-draad
  • voeg de pluskant van de eerste LED (anode, langere poot, met ronde rand) toe aan de minkant van de tweede LED
  • herhaal om de tweede LED met de derde en de derde met de vierde samen te voegen
  • sluit vervolgens de pluskant van de vierde LED met een draad aan op de USB-aarddraad.

Om de zaken netter te maken, kunt u krimpkous gebruiken wanneer u de verbindingen maakt. Gebruik anders isolatietape om kortsluiting te voorkomen.

Zorg ervoor dat u geen kortsluiting heeft. Sluit hem vervolgens aan op een USB-oplader en controleer of hij infrarood licht uitstraalt door met een telefooncamera naar de LED's te kijken. (Veel telefooncamera's zijn infraroodgevoelig.)

Stap 2: Bevestig aan tv

Bevestig aan tv
Bevestig aan tv
Bevestig aan tv
Bevestig aan tv
Bevestig aan tv
Bevestig aan tv

Bevestig nu twee van de LED's aan de onderkant van de tv en twee aan de bovenkant. De horizontale afstand moet ongeveer tien centimeter zijn. Als het te veel is, heb je misschien problemen met het gezichtsveld van de Wii-afstandsbediening om ze allemaal vast te leggen. Maar als ze te dichtbij zijn, zegt mijn geometrische intuïtie dat je een lagere precisie hebt.

Voor het testen heb ik de LED's afgeplakt met elektrische tape en voor een permanente verbinding heb ik vier nette kleine LED-clips ontworpen en afgedrukt (bestanden zijn hier) die ik warm op de tv heb geplakt. U moet de LED's zo dicht mogelijk bij het vlak van het tv-scherm plaatsen, zonder dat de rand ze verduistert van de locatie waar u gaat fotograferen.

Stap 3: Software installeren

Momenteel is de software alleen voor Linux. De volgende setup is ontworpen voor de Raspberry PI 3 met Raspbian Stretch. Voor andere Linux-systemen zijn enkele wijzigingen vereist. Op eerdere modellen heb je een Bluetooth-dongle nodig en deze moet je ook vanaf een opdrachtregel uitvoeren:

sudo get-apt bluetooth installeren

Stap A: udev

Maak vervolgens een bestand in /etc/udev/rules.d/wiimote.rules dat de enkele regel bevat:

KERNEL=="uinput", MODE="0666"

U kunt dat bijvoorbeeld doen met een teksteditor of door het volgende op de opdrachtregel te typen:

sudo sh -c 'echo KERNEL==\"uinput\", MODE=\"0666\" > /etc/udev/rules.d/wiimote.rules'

En start udev opnieuw:

sudo /etc/init.d/udev herstart

Stap B: cwiid

Vervolgens heb je mijn aangepaste cwiid-pakket nodig. Hier wordt het een beetje harig, want idealiter zou je het op je Raspberry PI moeten bouwen, maar ik moet bekennen dat ik uit het oog ben verloren welke pakketten je moet installeren om het te laten werken. Er zijn drie mogelijkheden om dit te doen.

Optie B1: Zelf bouwen

cd ~

git clone https://github.com/arpruss/cwiid-1 autoconf./configure make -C libcwiid sudo make -C libcwiid install make -C python sudo make -C python install

Helaas is de kans groot dat je een heleboel dingen mist die nodig zijn om dit te bouwen, en./configure zal klagen. Je kunt alle dingen bekijken waar het over klaagt en sudo apt install op ze allemaal uitvoeren.

Optie B2: Mijn binaire bestanden gebruiken

cd ~

wget https://github.com/arpruss/cwiid-1/releases/download/0.0.1/cwiid-rpi.tar.gz tar zxvf cwiid-rpi.tar.gz cd cwiid sudo make install

Stap C: Python-bibliotheken

Krijg ten slotte ondersteuningsmateriaal voor mijn lightgun python-script:

sudo pip3 installeer uinput numpy pygame opencv-python

sudo apt-get install libatlas-base-dev sudo apt-get install libjasper-dev sudo apt-get install libqtgui4 sudo apt-get install python3-pyqt5

Stap D: lightgun.py

Haal ten slotte mijn lightgun python-script op:

cd ~

git clone

Als alles goed is gegaan, heb je nu ~/lightgun.py waarmee je de lightgun kunt kalibreren.

Stap 4: Kalibratie Deel I: De camera centreren

Kalibratie Deel I: De camera centreren
Kalibratie Deel I: De camera centreren
Kalibratie Deel I: De camera centreren
Kalibratie Deel I: De camera centreren
Kalibratie Deel I: De camera centreren
Kalibratie Deel I: De camera centreren

Kalibratie kent twee aspecten. De eerste is om het midden van de camera op elke Wiimote te kalibreren. Hiervoor moet je de camera gebruiken om twee foto's te maken van de LED's rond je tv-scherm, één met de afstandsbediening met de goede kant naar boven en de andere ondersteboven.

Om te voorkomen dat je op de knoppen drukt wanneer je de Wii-afstandsbediening op de voorkant legt, en om de Wii-afstandsbediening een consistente hoogte te geven, kun je het kalibratiehulpmiddel dat ik hier heb opgenomen in 3D printen. Je hebt eigenlijk dingen nodig die 10,5 mm dik zijn en die je onder de Wii-afstandsbediening kunt leggen als deze op de voorkant ligt. Ik heb eigenlijk wat schrootmultiplex gebruikt om op plastic te besparen.

Schakel uw LED's in en zorg ervoor dat uw Raspberry PI of andere computer op de tv wordt weergegeven. Sluit een toetsenbord aan (dit werkt niet via ssh) of gebruik VNC. Voer dan uit:

python3 ~/lightgun/lightgun.py -M

Als alles goed gaat, krijg je een schermvullend scherm waarin je wordt gevraagd op 1+2 op de Wii-afstandsbediening te drukken. Doe dat. De lampjes op de Wii-afstandsbediening knipperen en lampjes 1 en 4 blijven branden. Je ziet ook een kleine groene rechthoek aan de bovenkant van het scherm, met het uitzicht vanaf de camera van de Wii-afstandsbediening. Richt de Wii-afstandsbediening op de LED's en als alles goed gaat, zie je de vier LED's, genummerd van 1 tot en met 4.

Nu moet je een stevig oppervlak vinden met een scherpe rand, zoals een salontafel, die je naar het tv-scherm kunt richten en waarmee de Wii-afstandsbediening alle LED's kan zien terwijl de Wii-afstandsbediening tegen de rand is uitgelijnd. Begin met het uitlijnen van de Wii-afstandsbediening met de goede kant naar boven, met de kant van de afstandsbediening uitgelijnd tegen de oppervlakterand, en zorg ervoor dat alle vier de LED's zichtbaar zijn. Druk dan op SPACE op je toetsenbord (of bevestig een Nunchuck en druk op C als dat handiger is). Je wordt dan gevraagd om de Wii-afstandsbediening te draaien. Zorg er nu voor dat het 10,5 mm boven uw oppervlak staat, met behulp van het kalibratiehulpmiddel of iets anders, en zo dicht mogelijk bij dezelfde locatie als voorheen (bijvoorbeeld uitgelijnd tegen dezelfde rand van uw oppervlak). Druk nogmaals op SPATIE.

Als alles goed gaat, gaat u nu naar de LED-kalibratiestap. Ja, dit is ingewikkeld! Maar je krijgt een heel precies lichtgeweer. Dat is gewoon de prijs.

Opmerking: als je net als ik een Wii onder de tv hebt, moet de Wii om twee redenen worden uitgeschakeld: ten eerste, als de Wii is ingeschakeld, maakt deze verbinding met de Wiimote en ten tweede zullen de infrarood-LED's van de sensorbalk interfereren met dit project. Om soortgelijke redenen is het een goed idee om de LED's rond de tv los te koppelen terwijl je de Wii gebruikt.

Stap 5: Kalibratie Stap II: LED's

Kalibratie Stap II: LED's
Kalibratie Stap II: LED's
Kalibratie Stap II: LED's
Kalibratie Stap II: LED's

Nu moet je de software vertellen waar de LED's zich aan de rand van de tv bevinden. U ziet een kalibratiescherm met vier pijlen, één geselecteerd (helder) en drie grijs, rond de rand van de tv. U gebruikt +/- om over te schakelen om te wijzigen welke pijl u aanpast.

Doe dit voor elk van de vier pijlen rond de rand:

  1. druk links/rechts op de Wiimote om de pijlen te verplaatsen totdat ze zo precies mogelijk naar de corresponderende LED wijzen;
  2. druk omhoog/omlaag op de Wiimote om de lengte van de pijl te wijzigen totdat de lengte van de pijl overeenkomt met de afstand tussen de LED en de rand van het tv-scherm; met andere woorden, de lengte van de pijl moet gelijk zijn aan de afstand van de punt van de pijl tot de LED.

Zodra je vier pijlen correct zijn (en misschien zelfs eerder) zie je een rood dradenkruis wanneer je de Wiimote op het scherm richt. U kunt controleren of dit is waar het moet zijn. (Vergeet niet dat je ver genoeg weg moet zijn zodat de Wiimote alle LED's kan zien. Het is ook belangrijk dat er geen andere infraroodbronnen in het gezichtsveld zijn. Ik had ooit problemen vanwege zonlicht dat weerkaatste op een schroefkop op de TV-standaard.)

Ten slotte is er een vijfde pijl, die alleen verschijnt als je op + drukt vanaf de vierde LED-pijl of - vanaf de eerste (en deze heeft standaard een lengte van nul, dus het is maar een pixel). Deze pijl bepaalt hoe ver boven de camera van de Wii-afstandsbediening het schot wordt geregistreerd. Het probleem is dit: je kijkt langs de bovenkant van de Wii-afstandsbediening. Maar de camera bevindt zich eigenlijk op enige afstand onder dat oppervlak, in het midden van de zwarte rechthoek aan de voorkant van de Wii-afstandsbediening. Als we de opnamen zouden registreren waar de camera naar wijst, zouden ze ongeveer 8 mm onder het bovenoppervlak van de Wii-afstandsbediening worden geregistreerd. U kunt dit controleren door op te merken dat als u langs het bovenoppervlak kijkt, het midden van het dradenkruis door de camera wordt verborgen.

Je kunt hiermee leven, of je kunt deze vijfde pijl laten groeien om de schoten softwarematig uit te lijnen met de bovenkant van de Wii-afstandsbediening, of je kunt de 3D-afdrukbare bestanden voor de ijzeren vizieren aanpassen om dit te compenseren (maar de compensatie werkt alleen voor een bepaalde afstand tot de TV). Zelf ben ik voor de software uitlijning gegaan.

Druk op HOME op de Wii-afstandsbediening om de kalibratie af te sluiten en alle gegevens op te slaan in de map ~/.wiilightgun.

Stap 6: Test en gebruik

Testen en gebruiken
Testen en gebruiken
Testen en gebruiken
Testen en gebruiken
Testen en gebruiken
Testen en gebruiken

U wilt nu waarschijnlijk uw lichtpistool proberen. Voer gewoon een terminalemulator (of een script) uit:

python3 ~/lightgun/lightgun.py -t

U moet tegelijkertijd op de 1+2-knoppen drukken en daarna, als alles goed gaat, zolang lightgun.py actief is, zal de lightgun een absolute muis met twee knoppen emuleren. De triggerknop is muisknop 1, en de A-knop is muisknop 2. Druk op ctrl-c om af te sluiten.

U hoeft nu alleen nog maar uw emulators en/of games te configureren om met een absolute muis te werken. Helaas zal dat niet altijd even gemakkelijk zijn.

Een leuk ding dat je zou kunnen proberen, is mijn mod van iminurnamez's duck-duck-shoot:

cd ~

git clone https://github.com/arpruss/duck-duck-shoot cd duck-duck-shoot python play_game.py

Voor NES-spellen gebruik ik de libretro fceumm-kern in Retroarch. Ga naar het menu Opties en configureer de Zapper als touchscreen. (Het configureren als muis werkt niet echt, omdat fceumm een relatieve beweging verwacht in plaats van een muis met absolute positie.)

Als je je games start met een script, kun je het gedeelte dat de game of emulator start, bewerken om te zeggen:

python3 ~/lightgun/lightgun.py -t -B 30 "opdracht om het spel te starten"

Vervolgens kun je tijdens de eerste 30 seconden van de uitvoering van het spel (vandaar de optie -B 30), je lightgun aansluiten door 1+2 ingedrukt te houden.

Overigens kan het lightgun.py-script ook worden gebruikt voor algemene Wii-afstandsbedieningen met Retroarch. Voeg gewoon de -o-optie toe en de lightgun-functies worden uitgeschakeld en in plaats daarvan werkt de Wii-afstandsbediening horizontaal, met de drie knoppen respectievelijk 1, 2 en B. Er zijn andere Retroarch-gerelateerde functies in lightgun.py's mappings die je zult ontdekken door de code te lezen. De min-toets werkt bijvoorbeeld als een shift en samen met de dpad-bedieningselementen voor opslaan en laden (omhoog/omlaag = wijzigingsnummer opslaan; links=herstellen; rechts=opslaan).

Stap 7: pistoolhandvat en richten

Pistoolhandvat en richten
Pistoolhandvat en richten
Pistoolhandvat en richten
Pistoolhandvat en richten
Pistoolhandvat en richten
Pistoolhandvat en richten

Je kunt de Wii-afstandsbediening op zichzelf gebruiken als een pistool, door langs de bovenkant te kijken. Je kunt er ook een van de commerciële geweerhulzen voor kopen. Maar omdat de originele Wii-afstandsbediening niet als een zichtbaar geweer kon worden gebruikt, hebben de behuizingen meestal geen ijzeren vizieren, en ijzeren vizieren verbeteren de nauwkeurigheid aanzienlijk.

Ik ontwierp een eenvoudig driedelig 3D-printbaar systeem: een opschuifbare handgreep die net achter de trekker zit (dus het lijkt een beetje op een Star Trek Original Series-faser), en opschuifbare vizieren. Afdrukbare bestanden zijn hier. Als je op plastic wilt besparen ten koste van sloophout, kun je ook doen wat ik deed en in plaats van het hele handvat af te drukken, alleen het deel af te drukken dat de Wiimote vasthoudt, en een houten stuk uitsnijden en vastschroeven.

Om te zien, richt je je ogen op de bezienswaardigheden. Lijn de hobbel van het voorste vizier uit tussen de hobbels van het achterste vizier, zodat de luchtruimte op een van beide gelijk is en alle drie de hobbels even hoog uitsteken. Lijn vervolgens het midden van het doel uit met de bovenkant van de hobbels.

Let op: De hoogte van de hobbels is enigszins ongelijk, waarbij de hobbel van het voorste vizier iets lager is, om de hoogte van de vizierbobbels zelf te compenseren als je er langs kijkt op een afstand van 2,5 meter (mijn afstand tot tv). Als u een aanzienlijk andere afstand tot de tv heeft, kunt u die in de OpenSCAD-bestanden plaatsen. Deze aanpassing kan hoe dan ook onder de printertoleranties liggen. Als je de verticale aanpassing in de software niet hebt gedaan, kun je ook wat meer aanpassingen aan de bezienswaardigheden in de software toevoegen door extraSightAdjust in te stellen op iets rond -8 (in millimeters).

Stap 8: Kalibratie III (optioneel): fijnafstelling

Als u nog meer precisie wilt, kunt u het volgende uitvoeren:

python3 ~/lightgun/lightgun.py -d

(voor demo) en kijk goed of de vizieren op één lijn liggen met het dradenkruis. Als dat niet het geval is, sluit u af en bewerkt u handmatig ~/.wiilightgun/wiimotecalibration, en past u de x- en y-coördinaten van het cameracentrum enigszins aan om de waarneming aan te passen. Mijn pistool schoot bijvoorbeeld iets naar rechts, dus ik veranderde uiteindelijk de x-coördinaat van 529 in 525. De nummers van iedereen zullen waarschijnlijk anders zijn.

Stap 9: Bijlage: het algoritme

Bijlage: het algoritme
Bijlage: het algoritme

De muisemulatiecode werkt ongeveer als volgt.

  • Procesknop indrukken.
  • Ontvang gegevens van de camera en pas deze aan voor kalibratie van de cameracentrering.
  • Als er minder dan drie LED's zichtbaar zijn in de camera:

    Laatste muispositie behouden

  • Als er drie of vier LED's zichtbaar zijn:

    • Gebruik de gegevens van de Wiimote-versnellingsmeter om de Wiimote-oriëntatie te krijgen en te bepalen welk LED-camerabeeld overeenkomt met welke fysieke LED.
    • Als er vier LED's zichtbaar zijn:

      • Bereken homografie tussen LED-camerabeelden en LED-locaties (in schermcoördinaten).
      • Gebruik homografie om te berekenen welke schermlocatie overeenkomt met het midden van het gezichtsveld van de camera.
      • Voer de Y-aanpassing uit om het midden van de virtuele geweerloop onder de zichtlijn aan te passen. Dit is een ietwat onhandig algoritme, maar het werkt.
      • Stel de muispositie in op de aangepaste schermlocatie.
    • Als er drie LED's zichtbaar zijn:

      • Gebruik OpenCV om het P3P-probleem tussen de LED-camerabeelden en de fysieke LED-locaties op te lossen. Dit genereert maximaal vier oplossingen.
      • Indien succesvol:

        • Als we een eerdere succesvolle locatieberekening hebben, kies dan de oplossing waarbij de ontbrekende LED zich het dichtst bij de laatst waargenomen of berekende positie van die LED bevindt.
        • Als we geen eerdere succesvolle locatieberekening hebben, kies dan de oplossing die de koers van de versnellingsmeter het beste voorspelt.
        • Gebruik de beste oplossing om te berekenen waar de vierde LED moet komen.
        • Doe de rest zoals in de behuizing met vier leds.
      • Indien niet succesvol:

        Laatste muispositie behouden

Aanbevolen: