Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Autonome tank

Een veel goedkoper alternatief toevoegen aan de Carter en Kaya-ontwerpreferentie met behulp van een Lego EV3-set.

In dit project zal ik de constructie documenteren van een rupsvoertuig gemaakt met Lego Technic-onderdelen en -motoren, verbeterd met LiDAR en bestuurd door een Jetson Nano-bord met de nieuwste Isaac SDK. Ga naar Deel 8 of 10 voor een volledige demo van de autonome navigatie.

Het project bestaat uit de braakliggende componenten:

  • Een NVIDIA Jetson Nano dev board – voert de Isaac Robot Engine uit
  • Een EV3-steen  – bestuurt de motoren (meegeleverd in de EV3 31313 Robot Kit )
  • Onderstel met rupsbanden - gemaakt met Lego Technic-onderdelen en twee grote motoren (alles wat nodig is wordt geleverd in de EV3 31313 Robot Kit )
  • YDLIDAR x4 LiDAR
  • Pixy2 Camera voor zicht

Waarom Isaac SDK en niet ROS?

  • Er zijn zoveel tutorials voor ROS (Robot Operating System) maar bijna geen voor Isaac (behalve die van de SDK zelf)
  • Lijkt een betere keuze te zijn voor Jetson Nano (is gemaakt voor deze familie van hardware)
  • Geavanceerde robotica-algoritmen van planning tot perceptie, de meeste zijn GPU-versneld . Dit is een belangrijk onderdeel. Zonder GPU-versnelling verschilt Jetson Nano op geen enkele manier van een Raspberry Pi 4-bord
  • IsaacSim Unity3D is fotorealistischer dan Gazebo, wat de resultaten zal verbeteren die van simulatie naar realiteit gaan

Waarom Lego-onderdelen?

  • Ik heb er veel 🙂
  • De onderdelen zijn van hoge kwaliteit (goede servo's)
  • Ik heb geen 3D-printer (vroeg een vriend om een ​​Jetson Nano-hoes te printen die compatibel is met Lego, maar dat is het enige deel dat 3D is geprint)
  • Geen solderen nodig

Het kiezen van dit pad brengt enkele uitdagingen met zich mee:

  • Lego-hardware wordt niet ondersteund door Isaac SDK. Er bestaan ​​slechts twee referentierobots:Carter en Kaya. Zelfs de JetBot wordt niet ondersteund.
  • Isaac SDK kan met slechts een beperkt aantal hardwarecomponenten werken
  • Compilatie voor 3 doelen (x86-64, arm64 en armv5tejl)
  • Niet alles is open-source

DEEL 1:Aan de slag

1. Isaac SDK

  • Doorloop de stappen die hier worden beschreven
  • Probeer enkele van de voorbeelden uit de Isaac SDK uit te voeren om te controleren of alles werkt
  • Zorg ervoor dat u de SDK-versie 2019.3 gebruikt!!!

2. Spraakherkenning (optioneel)

  • Installeer CUDA 10.0, CUDNN 7.6.3 en TensorRT 6.0
  • Installeer TensorFlow 1.15.0 (hardware versneld)

3. Ev3dev-afbeelding

Download en flash de nieuwste afbeelding voor EV3 (ev3dev-stretch) op een microSD- of microSDHC-kaart. Het MicroSDXC-formaat wordt niet ondersteund door de EV3-steen.

4. ARM cross-compiler voor ev3dev

$ sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi 

Dit onderdeel was vooral moeilijk om correct in te stellen. Ubuntu 18.04 (hostcomputer en Jetson Nano) gebruikt GLIBC_2.28 terwijl ev3dev Debian stretch en GLIBC_2.24 gebruikt. Alles wat gecompileerd was met de standaard arm-linux-gnueabi-g++ compilerconfiguratie was afhankelijk van GLIBC_2.28 en zal niet draaien op EV3. Statisch koppelen werkte niet omdat iets complexers dan een hallo wereld segfaults veroorzaakte. De oplossing die ik vond was om alles dynamisch te koppelen, behalve de wiskundebibliotheek. U kunt meer informatie vinden in het jetson-ev3/toolchain/CROSSTOOL-bestand. Een andere oplossing is om een ​​docker-image van Debian 9 te gebruiken.

5. Jetson + EV3-werkruimte

$ git clone https://github.com/andrei-ace/jetson-ev3.git 
  • Bewerk jetson-ev3/WORKSPACE en stel het pad in naar Isaac SDK.
local_repository(
name ="com_nvidia_isaac",
path ="/home/andrei/ml/isaac"
)
  • Bewerk jetson-ev3/toolchain/CROSSTOOL en stel het pad in naar de map waar dit bestand zich bevindt.
# edit met je pad naar de toolchain
linker_flag:"-L/home/andrei/ml/jetson-ev3/toolchain"

6. Verbind Jetson Nano met EV3

In het volgende deel zal ik veel Linux-commando's posten. Omdat er drie systemen bij betrokken zijn, zal ik ze precies zo posten als ze er in mijn terminal uit zouden zien, wat betekent:

[email protected]:~/ml/jetson-ev3$ #this wordt uitgevoerd op mijn pc
[email protected]:~$ #this is on Jetson Nano
[email protected]:~$ $ #this in op EV3

De IP's van mijn Jetson Nano zijn 192.168.0.173 (Ethernet) en 192.168.0.218 (WiFi), dus wanneer je een commando ziet dat deze waarden gebruikt, vervang ze dan door die van jou.

Ik heb een USB A-naar-minikabel gebruikt om het Jetson-bord met de EV3-steen te verbinden met behulp van deze stappen.

Probeer te ssh vanaf het Jetson-bord:

[email protected]:~$ ssh [email protected] 

Het standaardwachtwoord is maker.

7. De pingpong-tutorial

Isaac heeft een tutorial waarin een heel eenvoudige Codelet wordt uitgelegd. Ik raad aan om eerst deze tutorial te doen. Het laat je kennismaken met de concepten die nodig zijn om een ​​app te bouwen die op Isaac draait.

Ga nu naar de map jetson-ev3/apps/ev3/ping_pong/. Dit is een aangepaste versie van de vorige tutorial, met een twist, we sturen de ping naar de EV3-steen.

De meeste bestanden zijn bekend uit de vorige tutorial. We gebruiken Cap'n Proto RPC voor gesprekken tussen Jetson en EV3. Cap'n Proto wordt veel gebruikt voor communicatie tussen verschillende Isaac-componenten, dus het is logisch om het hier te gebruiken. Hiervoor hebben we enkele nieuwe bestanden nodig:

  • jetson-ev3/apps/ev3/ping_pong/ping.capnp – dit definieert een interface tussen een client, die op de Isaac Robot Engine draait, en een server, die op EV3 draait.
  • jetson-ev3/apps/ev3/ping_pong/PongEv3Server.cpp dit is de server die op de EV3-steen draait
  • jetson-ev3/apps/ev3/ping_pong/Pong.cpp dit is gewijzigd om de Pong-server op EV3 aan te roepen

Compileer de ev3_pong-server:

[email protected]:~/ml/jetson-ev3$ bazel build --config=ev3dev //apps/ev3/ping_pong:ev3_pong 

Kopieer het naar EV3 met scp eerst naar Jetson en vervolgens naar EV3.

Bouw en implementeer het pingpong-voorbeeld voor Jetson:

[email protected]:~/ml/jetson-ev3$ /engine/build/deploy.sh --remote_user  -p //apps/ev3/ping_pong:ping_pong-pkg -d jetpack43 -h  

Meer informatie over het implementeren en uitvoeren van uw apps op Jetson vindt u hier.

Voer beide apps uit:

[email protected]:~$ ./ev3_pong ev3dev.local:9999
[email protected]:~/deploy/andrei/ping_pong-pkg$ . /apps/ev3/ping_pong

Als alles werkte, zou je de berichten moeten horen die door de Ping-component zijn verzonden naar de luidspreker van de EV3.

8.Een motor besturen van Isaac

Zelfde principes, alleen wat complexer. Ik heb nog een van de Isaac's tutorials gebruikt om met een EV3-motor te werken:

De tutorial maakt gebruik van een Segway RMP-basis. Omdat ik er geen heb liggen of $ 10000 om er een te kopen, heb ik een driver gemaakt die in plaats daarvan de EV3-motoren zal besturen. De code is hier.

De server die draait op EV3 is hier en kan worden gebouwd en uitgevoerd met de volgende opdracht:

[email protected]:~/ml/jetson-ev3$ bazel build --config=ev3dev //packages/ev3/ev3dev:ev3_control_server
[e-mail beschermd]:~$ ./ev3_control_server ev3dev.local:9000

Ik heb de virtuele joystick van Sight gebruikt, zoals hier wordt uitgelegd.

9.DifferentialBase voor EV3

Ev3ControlServer-server reageert op 2 oproepen:

  • command(cmd :Control) – neemt lineaire en hoeksnelheden als parameters en bestuurt beide motoren om de gevraagde snelheden te bereiken
  • staat() -> (staat:Dynamiek); – geeft de echte lineaire en hoeksnelheden van de robot terug

De kinematica wordt hier en hier in meer detail uitgelegd.

Ik heb de proportionele_control_cpp-voorbeeldapp gebruikt om de robot 1 m te laten rijden en de odometriegegevens (lineaire en hoeksnelheden) van de EV3 in roterende pulsen (tachotellingen) per seconde te rapporteren. Met behulp van de berekende reisafstand (door Isaac) en het meten van de werkelijke afstand, bedacht ik een constante om de gerapporteerde waarden aan te passen zodat ze overeenkomen met de echte resultaten. Dit werkte goed en de resultaten waren vele malen reproduceerbaar en niet alleen in rechte lijnen. U kunt deze waarden ook berekenen door de straal van het wiel (of het spoor in ons geval) te gebruiken.

Deel 2:De robot bouwen

De basis lijkt erg op Lego's EV3 Track3r, een van de officiële modellen voor de EV3-kit:https://www.lego.com/biassets/bi/6124045.pdf

De case voor Jetson Nano komt hier vandaan: https://github.com/3D-printable-lego-technic/PELA-blocks

Deel 3:Isaac Apps

Een Isaac-app bestaat uit drie hoofdonderdelen:

  • graph – nodes:dit deel definieert alle componenten die de app maken. Een knoop kan ook een andere grafiek zijn die in een ander bestand is gedefinieerd. Het “voice_detection”-knooppunt uit het voorbeeld is een subgrafiek.
  • grafiek – randen:dit deel definieert de stroom van berichten tussen knooppunten. Een rand heeft een bron en een doel. Het gedetecteerde commando van het "voice_detection"-knooppunt (subgrafiek) wordt bijvoorbeeld verzonden naar een component die doelen genereert.
  • configuratie – dit deel configureert de knooppunten van de grafiek

Voorbeeld app:

{
"name":"voice_control",
"modules":[
"//apps/ev3/voice_control:voice_control_goal_generator",
"@com_nvidia_isaac//packages/navigation",
"@com_nvidia_isaac//packages/planner"
],
"config_files":[
" apps/ev3/voice_control/model/isaac_vcd_model.metadata.json"
],
"config":{
"2d_ev3.ev3_hardware.ev3":{
"isaac.Ev3Driver ":{
"adres":"ev3dev.local",
"poort":9000
}
},
"navigation.imu_odometry.odometry":{
"DifferentialBaseWheelImuOdometry":{
"use_imu":false
}
},
"commander.robot_remote":{
"isaac.navigation.RobotRemoteControl ":{
"angular_speed_max":0.6,
"linear_speed_max":0.3
}
},
"websight":{
"WebsightServer":{
"webroot":"external/com_nvidia_isaac/packages/sight/webroot",
"ui_config":{
"windows":{
"Spraakopdrachtdetectie":{
"renderer":"plot" ,
"verduistert":{
"breedte":400,
"hoogte":200
},
"kanalen":[
{
"name":"voice_control/voice_detection.voice_command_detector/isaac.audio.VoiceCommandConstruction/voice_command_id",
"active":true
}
]
}
}
}
}
},
"navigation.shared_robot_model":{
"SphericalRobotShapeComponent":{
"circles":[
{ "center":[0.0, 0.0], "radius":0.075 },
{ "center":[0.02, 0.03464], "radius":0.055 },
{ "center":[0.02, -0.03464], "radius":0.055 },
{ "center":[-0.04, 0.0], "radius":0.055 },
{ "center":[0.0525, 0.09093 ], "radius":0.035 },
{ "center":[0.0525, -0.09093], "radius":0.035 },
{ "center":[-0.105, 0.0], "radius ":0.035 }
]
}
},
"navigation.control.lqr":{
"isaac.planner.DifferentialBaseLqrPlanner":{
"manual_mode_channel":"commander.robot_remote/isaac.navigation.RobotRemoteControl/manual_mode"
}
},
"navigation.control.control":{
"isaac.planner.DifferentialBaseControl":{
"manual_mode_channel":"commander.robot_remote/isaac.navigation.RobotRemoteControl/manual_mode"
}
}
},
"graph":{
"nodes":[
{
"name":"voice_control_components",
"componenten":[
{
"name":"message_ledger",
"type":"isaac::alice::MessageLedger"
},
{
"name":"goal_generator",
"type":"isaac::VoiceControlGoalGenerator"
}
]
},
{
"name":"voice_detection",
"subgraph":"apps/ev3/voice_control/voice_command_detection.subgraph.json"
},
{
"name":"2d_ev3",
"subgraph":"apps/ev3/2d_ev3.subgraph.json"
},

{
"name":"navigatie",
"subgraph":"@com_nvidia_isaac//packages/navigation/apps/differential_base_navigation.subgraph.json"
},
{
"name":"commander",
"subgraph":"@com_nvidia_isaac//packages/navigation/ apps/differential_base_commander.subgraph.json"
}
],
"edges":[
{
"source":"voice_detection.subgraph/interface/detected_command" ,
"target":"voice_control_components/goal_generator/detected_command"
},
{
"source":"voice_control_components/goal_generator/goal",
"target" :"navigation.subgraph/interface/goal"
},
{
"source":"2d_ev3.subgraph/interface/base_state",
"target":"navigation. subgraph/interface/state"
},
{
"source":"navigation.subgraph/interface/command",
"target":"commander.subgraph/interface/ control"
},
{
"source":"commander.subgraph/interface/command",
"target":"2d_ev3.subgraph/interface/base_command"
},
{
"source":"2d_ev3.subgraph/interface/flatscan",
"target":"navigation.subgraph/interface/flatscan_for_localization"
},
{
"bron":"2d_ev3.subgraph/interface/flatscan",
"doel":"navigatie. subgraph/interface/flatscan_for_obstacles"
}
]
}
}

Voorbeeld subgrafiek:

{
"modules":[
"@com_nvidia_isaac//packages/audio",
"@com_nvidia_isaac//packages/ ml:tensorflow"
],
"graph":{
"nodes":[
{
"name":"subgraph",
" componenten":[
{
"name":"message_ledger",
"type":"isaac::alice::MessageLedger"
},
{
"name":"interface",
"type":"isaac::alice::Subgraph"
}
]
},
{
"name":"audio_capture",
"componenten":[
{
"name":"ml",
"type":"isaac::alice ::MessageLedger"
},
{
"name":"isaac.audio.AudioCapture",
"type":"isaac::audio::AudioCapture"
}
]
},
{
"name":"voice_command_detector",
"componenten":[
{
" name":"ml",
"type":"isaac::alice::MessageLedger"
},
{
"name":"isaac.audio.VoiceCommandFeatureExtraction" ,
"type":"isaac::audio::VoiceCommandFeatureExtraction"
},
{
" name":"isaac.ml.TensorflowInference",
"type":"isaac::ml::TensorflowInference"
},
{
"name":"isaac. audio.VoiceCommandConstruction",
"type":"isaac::audio::VoiceCommandConstruction"
}
]
}
],
"edges" :[
{
"source":"audio_capture/isaac.audio.AudioCapture/audio_capture",
"target":"voice_command_detector/isaac.audio.VoiceCommandFeatureExtraction/audio_packets"
},
{
"source":"voice_command_detector/isaac.audio.VoiceCommandFeatureExtraction/feature_tensors",
"target":"voice_command_detector/isaac.ml.TensorflowInference/input_tensors"
},
{
"source":"voice_command_detector/isaac.ml.TensorflowInference/output_tensors",
"target":"voice_command_detector/isaac.audio.VoiceCommandConstruction/keyword_probabilities"
},
{
"source":"voice_command_detector/isaac.audio.VoiceCommandConstruction/detected_command",
"target":"subgraph/interface/detected _command"
}
]
},
"config":{
"audio_capture":{
"isaac.audio.AudioCapture":{
"sample_rate":16000,
"num_channels":1,
"audio_frame_in_milliseconds":100,
"ticks_per_frame":5
}
},
"voice_command_detector":{
"isaac.audio.VoiceCommandFeatureExtraction":{
"audio_channel_index":0,
"minimum_time_between_inferences":0.1
},
"isaac.ml.TensorflowInference":{
"model_file_path":"apps/ev3/voice_control/model/isaac_vcd_model.pb",
"config_file_path":"apps/ev3/voice_control/model/isaac_vcd_config. pb"
},
"isaac.audio.VoiceCommandConstruction":{
"command_list":[
"jetson",
"jetson left",
"jetson right"
],
"command_ids":[0, 1, 2],
"max_frames_allowed_after_keyword_detected":14
}
}
}
}

Een subgraaf kan in veel apps opnieuw worden gebruikt. In feite wordt de navigatiestack van de isaac gebruikt als een subgrafiek.

Deel 4:Isaac-apps uitvoeren op EV3

De driver (jetson-ev3/packages/ev3/BUILD) reageert op dezelfde opdrachten als de Segway RMP-basisdriver. Dat betekent dat het werkt met veel apps die werken op Kaya of Carter, waardoor het een derde optie is en veel goedkoper!

Ik heb een aantal apps aangepast die zijn gemaakt om de Carter- en Kaya-bots te laten zien:

  • joystick-app:deze bestuurt een DifferentialBase-robot met een joystick. Het heeft een LiDAR voor het genereren van lokale kaarten
  • gmapping gedistribueerd: ev3 en host van de Kaya-robot – hiermee kan een GMap worden gemaakt met behulp van de EV3-robot en YDLIDAR X4.
  • volledige navigatie - Ik heb subgrafieken toegevoegd voor hardware en 2D-navigatie voor de EV3-robot, zodat ze door andere apps net zo gemakkelijk kunnen worden gebruikt als Carter of Kaya.

Deel 5:Odometrie

Voor het rijden in de autonome modus is het belangrijk om een ​​goede kilometerstand te hebben. Dit wordt gebruikt om de positie van de robot in de tijd te schatten. Laten we het aanpassen met de ev3-app:

[email protected]:~/ml/jetson-ev3$ ./engine/build/deploy.sh --remote_user andrei -p //apps/ev3:ev3 -pkg -d jetpack43 -h 192.168.0.173

[email protected]:~$ brickrun ./ev3_control_server ev3dev.local:9000

[email protected]:~/deploy /andrei/ev3-pkg$ ./apps/ev3/ev3 --graph ./apps/assets/maps/map.graph.json --config ./apps/assets/maps/map.config.json

We moeten twee dingen inschatten:

  • lineaire snelheid
  • hoeksnelheid

De formules voor lineaire en hoeksnelheden zijn:

Het vinden van de hoeksnelheid is eenvoudig:is het verschil tussen de rechter en linker motor gedeeld door de basislengte.

Het vinden van de lineaire snelheid is iets ingewikkelder. We hebben 3 gevallen:

  • wanneer beide motorsnelheden gelijk zijn, is de lineaire snelheid gelijk aan de rechtersnelheid (en linkersnelheid)
  • wanneer de linker motorsnelheid tegengesteld is aan de rechter motorsnelheid, is de lineaire snelheid 0, zal de tank op zijn plaats draaien
  • wanneer de linker motorsnelheid 0 is (het geval dat rechts wordt beschreven). De lineaire snelheid is de helft van de juiste snelheid (het midden van de robot beweegt over een kleinere boog).

Experiment met hoeksnelheid:

We zullen de handmatige bediening gebruiken om de robot 360 graden op zijn plaats te draaien. Dit wordt gedaan door de linker- en rechtermotor met tegengestelde snelheden te bewegen. Als we de snelheden van beide motoren kennen, kunnen we de hoeksnelheid berekenen.

Laten we het proberen:

Experiment met hoek- en lineaire snelheden:

Ik rijd de tank rond en probeer hem op het einde weer op de startplaats te krijgen. De kilometertellergegevens moeten aan het einde zo dicht mogelijk bij 0 liggen als we de snelheden correct berekenen.

Deel 6:Alles samenbrengen

Ok, dus we zijn zo ver gekomen om alleen maar een dure RC-tank te hebben? Nee, we kunnen nu alle verschillende onderdelen van Isaac gebruiken. Bijvoorbeeld spraakopdrachten geven en de robot autonoom laten bewegen. Bekijk de voice_control voor een voorbeeld hiervan.

Het maakt gebruik van de audio- en machine learning-edelstenen van Isaac. Wat is een edelsteen? Zoals vermeld in de handleiding:"GEM's:een verzameling robotica-algoritmen van planning tot perceptie, de meeste GPU-versneld."

Ik heb mijn eigen RNN getraind volgens de stappen die in deze tutorial worden uitgelegd. Zorg er wel voor dat je veel gegevens hebt, vooral voor het geval van onbekende trefwoorden/stilte/willekeurige ruis.

Ik heb de mijne getraind om 3 woorden te herkennen:"jetson", "links" en "rechts". Je vindt het opgeslagen model hier. Met deze 3 woorden kunnen we 2 commando's samenstellen:“jetson left” en “jetson right”.

Het detectiegedeelte wordt hier beschreven, in zijn eigen subgrafiek, klaar voor gebruik en hergebruik.

Wat het eigenlijk doet, is naar de microfoon luisteren en als een van de commando's wordt opgepikt, wordt een voice_command_id uitgevoerd. Het gebruikt daarvoor de eerder getrainde RNN.

We kunnen dat gedetecteerde_commando nemen en doorgeven aan onze eigen Codelet:

{
"source":"voice_detection.subgraph/interface/detected_command",
"target":"voice_control_components/goal_generator/detected_command"
}

van de Codelet kunnen we een doel genereren en publiceren:

auto proto =rx_detected_command().getProto();
int id =proto.getCommandId();
auto goal_proto =tx_goal(). initProto();
goal_proto.setStopRobot(true);
goal_proto.setTolerance(0.1);
goal_proto.setGoalFrame("robot");
ToProto(Pose2d::Rotation( 90), goal_proto.initGoal());
tx_goal().publish();

Dit stelt een doel in om de robot 90 graden naar links te draaien. We kunnen verschillende doelen stellen in verschillende kaders. Het had kunnen zijn om naar een coördinaat in het kader "wereld" te gaan, zoals de coördinaten van de keuken. Het kan een Pose2::Translate(1.0, 0) zijn geweest in het frame van de robot om de robot 1 meter vooruit te brengen.

En van daaruit geven we het doel door aan de Global Planner.

{
"source":"voice_control_components/goal_generator/goal",
"target":"navigation.subgraph/interface/goal"
}

Waar alle magie gebeurt:

Helaas werkt het alleen in 10 W-modus, niet in 5 W, wat een beetje te veel is voor mijn batterij. In de 5W-modus duurt de inferentie te lang:

Ik heb geprobeerd met kleinere RNN's en verhoogd van 2 beschikbare cpu-cores (nvpmodel -m 1) naar 3 maar hielp niet veel. Het verminderde de tijd tot 30 ms voor de inferentie, nog steeds te lang voor nauwkeurige resultaten.

Deel 7:Mapping

Om een ​​kaart te maken, moeten we één instantie van Isaac op Jetson en één op de hostcomputer uitvoeren. Het in kaart brengen kost veel middelen, meer dan Jetson Nano aankan.

[email protected]:~/ml/jetson-ev3$ ./engine/build/deploy.sh --remote_user andrei -p //apps/ev3:gmapping_distributed_ev3 -pkg -d jetpack43 -h 192.168.0.218

[email protected]:~/deploy/andrei/gmapping_distributed_ev3-pkg$ ./apps/ev3/gmapping_distributed_ev3

[e-mail beschermd]:~/ml/jetson-ev3$ bazel run apps/ev3:gmapping_distributed_host

Vergeet niet het bestand apps/ev3/gmapping_distributed_host.app.json te wijzigen met je Jetson IP:

"tcp_subscriber":{
"isaac.alice.TcpSubscriber":{
"port":5000,
"host" :"192.168.0.218"
}
}

Bron:Autonome tank


Productieproces

  1. Autonoom rijden AI voor vuilniswagen van ezels
  2. Tankdag 23:bereik en lager
  3. JQR Quadruped Autonomous Robot
  4. Voorbereiden op een autonome toekomst
  5. CNC-gefreesd gevechtstankmodel
  6. Autonome robot opent deuren
  7. Autonome assembleurs monteren
  8. Wat is een reservetank?
  9. Veiligheidstips voor het lassen van brandstoftanks
  10. Hoe repareer ik een gaslek in mijn auto?
  11. De technologie van autonome voertuigen