De auteur beschrijft de ontwikkeling van een eigen stereo vision board gebaseerd op de Rockchip RV1103 SoC. Het project omvat zowel hardware- als software-engineering:
- Hardware: Er is een vierlaags PCB ontworpen met MIPI CSI-2 ondersteuning. De auteur reflecteert op enkele ontwerpfouten, zoals onjuiste gatmaten voor lenzen en te dunne traces.
- Software: Met Buildroot is een Linux-omgeving opgezet. Het opstartproces volgt een specifieke volgorde: BootROM → TPL → SPL → U-Boot → Linux.
- Softwarestack: De beeldata wordt ontsloten via Video4Linux2 (V4L2), terwijl de propriëtaire Rockchip Video Engine wordt gebruikt voor hardware-acceleratie.
- Stereovisie: Het board maakt gebruik van een SAD-engine (Sum of Absolute Differences) voor stereo block matching. Door het vergelijken van horizontale verschuivingen tussen twee camerabeelden kan het systeem dieptewaarden berekenen.
Het uiteindelijke doel is om dit board te integreren in robotica-projecten voor navigatie en obstakelvermijding, met toekomstige plannen voor de implementatie van SLAM en YOLO.
Ik heb een Stereo Vision Board gebouwd voor Hardware Hackers
Ontwerpfase en visie
Mijn visie is om dit board te integreren in robotica-projecten, zoals een Arduino die obstakelvermijding of navigatie nodig heeft. Zodra het board is opgestart, verzendt het gegevens via een seriële verbinding. Daarnaast kan het onafhankelijk worden gebruikt, met alle functionaliteiten die je van een Linux-board mag verwachten.
Systeemoverzicht
De PCB
Voor dit project volstond een goedkope vierlaags printplaat (PCB). De lagen zijn als volgt ingedeeld:
- Top Layer: Traces met gecontroleerde impedantie voor USB, MIPI en Ethernet, aangevuld met sommige signaal- en stroomlijnen.
- Inner L1: Solide ground (massa).
- Inner L2: Signaal/stroom.
- Bottom Layer: Signaal/stroom.
Het board was bij de eerste poging grotendeels correct, maar er waren enkele problemen:
- Er was de verkeerde SoC besteld, wat zorgde voor een uitdagende vervanging.
- De gaten voor de lensbevestigingen waren geboord op 1,8 mm in plaats van 2,2 mm.
- De 1k weerstanden waren te klein om de LED's mooi te laten branden.
- De 0,9 V trace was te dun, hoewel deze wel leek te werken.
Kernel, Bootloader en OS
Voor een opstartbaar besturingssysteem met drivers, een bootloader en een kernel heb ik Buildroot gebruikt. Buildroot combineert deze elementen in een sdcard.img, die op een SD-kaart wordt geflasht en vervolgens in het board wordt geplaatst om op te starten.
Omdat niet alles voor dit project 'upstream' beschikbaar is, zijn de Rockchip MIPI-drivers, hardware-accelerators en enkele andere cruciale componenten afkomstig uit de BSP (Board Support Package) van de leverancier. Buildroot ondersteunt kernels die buiten de standaardboom ('out-of-tree') vallen.
Het opstartproces van deze chip verloopt in verschillende fasen:
- (Bootloader) BootROM: Laadt de TPL en voert deze uit. Dit bevindt zich in ROM en maakt gebruik van SRAM (kleiner, geen hoofdgeheugen).
- (Bootloader) TPL (Tertiary Program Loader): Stelt de DRAM-controller in. Dit is een binair bestand van Rockchip.
- (Bootloader) SPL (Secondary Program Loader): Laadt U-Boot; dit is gebundeld met het U-Boot-project.
- (Bootloader) U-Boot: De hoofdbootloader die de kernel laadt en over diverse geavanceerde functies beschikt.
- (Kernel) Linux.
- (OS) Init System: Start de diverse services.
Na een eenvoudige configuratie in Buildroot had ik toegang tot een shell via de seriële poort. Uiteindelijk ben ik overgestapt op SSH, waarbij de USB-C-poort als Ethernet-adapter fungeert.
De Softwarestack
Het minimale levensvatbare product (MVP) van de software moet communiceren met de kernel om beeldata op te halen, de camera te besturen en de hardware-accelerators te gebruiken.
Kernel Space
De drivers worden abstracter naarmate ze hoger in de stack staan, terwijl ze lager in de stack hardware-specifiek zijn. Dit betekent dat een gebruikersapplicatie kan communiceren met een node die is aangemaakt door V4L2, zonder dat deze rekening hoeft te houden met specifieke cameracommandos.
Er zijn SoC-specifieke drivers voor de randapparatuur van de SoC (zoals I2C, CSI, etc.). Hierdoor hoeft de cameradriver (in dit geval de OV9281) niet te weten op welke SoC hij draait.
User Space
De data stroomt uiteindelijk naar Video4Linux2, dat onze camera's ontsluit via diverse nodes: /dev/videoX. Elke camera toont 11 video-nodes:
video0: Normale videocapture.
video1-3: Overige stream-ID's.
video4-7: Scalers.
video8-10: Hulpfuncties.
De camerabesturing verloopt via /dev/v4l-subdevX. Deze nodes worden gebruikt om de belichting en diverse camerafuncties in te stellen.
De "Rockchip Video Engine" is ontsloten via /dev/rve. Er wordt gebruikgemaakt van de propriëtaire librve.a om met de engine te communiceren en diverse hardwarematige video-acceleratietaken in te plannen.
De gebruikersapplicatie
De applicatie voert de volgende stappen uit:
- Configureert de camera's via
/dev/v4l-subdevX.
- Haalt de beeldata op via
/dev/videoX.
- Voedt deze data aan de
/dev/rve node.
Stereoscopisch zicht en de SAD-engine
De Rockchip Video Engine bevat een SAD-engine (Sum of Absolute Differences). Dit is een hardware-acceleratorblok dat direct op de Rockchip SoC draait.
SAD vormt de kern van de stereoscopische visie. Een grijswaardenbeeld kan worden weergegeven als een matrix, waarbij elk element een getal van 0 tot 255 is. Stel dat we twee beelden hebben van elk 2 × 2 pixels. De SAD kan als volgt worden berekend:
| Beeld 1 | Beeld 2 | Absolute verschillen |
| [10 20] | [10 20] | [0 0] |
| [30 40] | [30 40] | [0 0] |
SAD = 0 + 0 + 0 + 0 = 0
In dit geval kunnen we concluderen dat de twee beelden identiek zijn. In de praktijk vergelijken we geen kleine beelden, maar breken we twee grote beelden op in een groot aantal kleinere beelden, zogenaamde patches, en passen we dit proces overal toe. Hierdoor ontstaat een genormaliseerde SAD per patch (waarbij 0 identiek betekent).
Stereo Block Matching
SAD-gebaseerde stereo block matching gebruikt hetzelfde principe, maar vergelijkt een verticale kolom van patches na een horizontale verschuiving (shift). Onze twee beelden komen van twee aparte camera's, die horizontaal van elkaar gescheiden zijn door een afstand die we de baseline noemen.
We houden één beeld vast, verschuiven het andere beeld en proberen overeenkomstige blokken te vinden. Wanneer de blokken matchen, is dit een dieptewaarde:
- Een match bij een zeer vroege verschuiving duidt op een object dat ver weg is.
- Een match bij een latere verschuiving duidt op een object dat dichterbij is.
Wat is de volgende stap?
Ik zou graag een aantal van deze apparaten verkopen om feedback te verzamelen. Indien er voldoende interesse is (meer dan 20 aanmeldingen), zal ik een nieuwe serie van 10 boards bestellen inclusief alle correcties.
Mocht het project voldoende tractie krijgen, dan zullen de volgende fasen bestaan uit software-optimalisaties, beeldverbeteringen en de implementatie van SLAM en YOLO.
Ik heb een Stereo Vision Board gebouwd voor Hardware Hackers
Ontwerpfase en visie
Mijn visie is om dit board te integreren in robotica-projecten, zoals een Arduino die obstakelvermijding of navigatie nodig heeft. Zodra het board is opgestart, verzendt het gegevens via een seriële verbinding. Daarnaast kan het onafhankelijk worden gebruikt, met alle functionaliteiten die je van een Linux-board mag verwachten.
Systeemoverzicht
De PCB
Voor dit project volstond een goedkope vierlaags printplaat (PCB). De lagen zijn als volgt ingedeeld:
- Top Layer: Traces met gecontroleerde impedantie voor USB, MIPI en Ethernet, aangevuld met sommige signaal- en stroomlijnen.
- Inner L1: Solide ground (massa).
- Inner L2: Signaal/stroom.
- Bottom Layer: Signaal/stroom.
Het board was bij de eerste poging grotendeels correct, maar er waren enkele problemen:
- Er was de verkeerde SoC besteld, wat zorgde voor een uitdagende vervanging.
- De gaten voor de lensbevestigingen waren geboord op 1,8 mm in plaats van 2,2 mm.
- De 1k weerstanden waren te klein om de LED's mooi te laten branden.
- De 0,9 V trace was te dun, hoewel deze wel leek te werken.
Kernel, Bootloader en OS
Voor een opstartbaar besturingssysteem met drivers, een bootloader en een kernel heb ik Buildroot gebruikt. Buildroot combineert deze elementen in een sdcard.img, die op een SD-kaart wordt geflasht en vervolgens in het board wordt geplaatst om op te starten.
Omdat niet alles voor dit project 'upstream' beschikbaar is, zijn de Rockchip MIPI-drivers, hardware-accelerators en enkele andere cruciale componenten afkomstig uit de BSP (Board Support Package) van de leverancier. Buildroot ondersteunt kernels die buiten de standaardboom ('out-of-tree') vallen.
Het opstartproces van deze chip verloopt in verschillende fasen:
- (Bootloader) BootROM: Laadt de TPL en voert deze uit. Dit bevindt zich in ROM en maakt gebruik van SRAM (kleiner, geen hoofdgeheugen).
- (Bootloader) TPL (Tertiary Program Loader): Stelt de DRAM-controller in. Dit is een binair bestand van Rockchip.
- (Bootloader) SPL (Secondary Program Loader): Laadt U-Boot; dit is gebundeld met het U-Boot-project.
- (Bootloader) U-Boot: De hoofdbootloader die de kernel laadt en over diverse geavanceerde functies beschikt.
- (Kernel) Linux.
- (OS) Init System: Start de diverse services.
Na een eenvoudige configuratie in Buildroot had ik toegang tot een shell via de seriële poort. Uiteindelijk ben ik overgestapt op SSH, waarbij de USB-C-poort als Ethernet-adapter fungeert.
De Softwarestack
Het minimale levensvatbare product (MVP) van de software moet communiceren met de kernel om beeldata op te halen, de camera te besturen en de hardware-accelerators te gebruiken.
Kernel Space
De drivers worden abstracter naarmate ze hoger in de stack staan, terwijl ze lager in de stack hardware-specifiek zijn. Dit betekent dat een gebruikersapplicatie kan communiceren met een node die is aangemaakt door V4L2, zonder dat deze rekening hoeft te houden met specifieke cameracommandos.
Er zijn SoC-specifieke drivers voor de randapparatuur van de SoC (zoals I2C, CSI, etc.). Hierdoor hoeft de cameradriver (in dit geval de OV9281) niet te weten op welke SoC hij draait.
User Space
De data stroomt uiteindelijk naar Video4Linux2, dat onze camera's ontsluit via diverse nodes: /dev/videoX. Elke camera toont 11 video-nodes:
video0: Normale videocapture.
video1-3: Overige stream-ID's.
video4-7: Scalers.
video8-10: Hulpfuncties.
De camerabesturing verloopt via /dev/v4l-subdevX. Deze nodes worden gebruikt om de belichting en diverse camerafuncties in te stellen.
De "Rockchip Video Engine" is ontsloten via /dev/rve. Er wordt gebruikgemaakt van de propriëtaire librve.a om met de engine te communiceren en diverse hardwarematige video-acceleratietaken in te plannen.
De gebruikersapplicatie
De applicatie voert de volgende stappen uit:
- Configureert de camera's via
/dev/v4l-subdevX.
- Haalt de beeldata op via
/dev/videoX.
- Voedt deze data aan de
/dev/rve node.
Stereoscopisch zicht en de SAD-engine
De Rockchip Video Engine bevat een SAD-engine (Sum of Absolute Differences). Dit is een hardware-acceleratorblok dat direct op de Rockchip SoC draait.
SAD vormt de kern van de stereoscopische visie. Een grijswaardenbeeld kan worden weergegeven als een matrix, waarbij elk element een getal van 0 tot 255 is. Stel dat we twee beelden hebben van elk 2 × 2 pixels. De SAD kan als volgt worden berekend:
| Beeld 1 | Beeld 2 | Absolute verschillen |
| [10 20] | [10 20] | [0 0] |
| [30 40] | [30 40] | [0 0] |
SAD = 0 + 0 + 0 + 0 = 0
In dit geval kunnen we concluderen dat de twee beelden identiek zijn. In de praktijk vergelijken we geen kleine beelden, maar breken we twee grote beelden op in een groot aantal kleinere beelden, zogenaamde patches, en passen we dit proces overal toe. Hierdoor ontstaat een genormaliseerde SAD per patch (waarbij 0 identiek betekent).
Stereo Block Matching
SAD-gebaseerde stereo block matching gebruikt hetzelfde principe, maar vergelijkt een verticale kolom van patches na een horizontale verschuiving (shift). Onze twee beelden komen van twee aparte camera's, die horizontaal van elkaar gescheiden zijn door een afstand die we de baseline noemen.
We houden één beeld vast, verschuiven het andere beeld en proberen overeenkomstige blokken te vinden. Wanneer de blokken matchen, is dit een dieptewaarde:
- Een match bij een zeer vroege verschuiving duidt op een object dat ver weg is.
- Een match bij een latere verschuiving duidt op een object dat dichterbij is.
Wat is de volgende stap?
Ik zou graag een aantal van deze apparaten verkopen om feedback te verzamelen. Indien er voldoende interesse is (meer dan 20 aanmeldingen), zal ik een nieuwe serie van 10 boards bestellen inclusief alle correcties.
Mocht het project voldoende tractie krijgen, dan zullen de volgende fasen bestaan uit software-optimalisaties, beeldverbeteringen en de implementatie van SLAM en YOLO.