czech english

VanJee Lidar

WLR-719C - four line

WLR-719C je 4-paprskový lidar od čínské firmy VanJee. Jedná se venkovní variantu používanou u donáškových robotů. Lidar je otočný a pokrýva celých 360 stupňů. Cenově je do 1000 USD. Blog update: 10/3/2024 — Zapojení a WAGO spojky

VanJee Lidar WLR-719C

Obsah



Blog

3. listopadu 2023 — Vánoce v listopadu

Dnes dorazil FedEx balíček. Chvíli jsem u sebe neměl telefón a málem to Santa vzdal … prý že adresa neni v Google maps, tak jako by nebyla. Teď jsem to zkoušel a už chápu … ono to neřekne, že přesnou adresu to nenalezlo, ale ukáže to úplně jinam. No nic, paní řidička byla ochotna se zase vrátit a balíček (cca 20x20x20cm) mi předala. Co je uvnitř? Dva všesměrové lidary WLR-719C.
Na první pohled dost připomínají TiM lidary od německé firmy SICK, ale tady by měly pokrýt všech 360 stupňů a hlavně detekovat překážky/díry ve čtyřech směrech:
Koukám, že už je to rok, co Jirka posílal takové šílené video

4. listopadu 2023 — První data?

Mno, včera jsem to ani nezapnul. Jako mohl jsem si to nastudovat dříve a trošku se připravit … prostě ten lidar je spíše na 24V a já tady mám tak leda 12V baterku z traktůrku. Ono sice píšou operating voltage is 12-28V DC, ale ještě v té samé větě je nominal operating voltage is 24V DC, nominal operating current is 0.25A, nominal power is 6W. Asi není úplně ideální začínat na hranici povoleného rozmezí, ale … když tu baterku více nabiju, tak bude mít třeba 14V a rozjede se to?
Hmm, tak zas úplně triviální to není. Nastavil jsem pevnou IP adresu, abych si po Ethernetu mohl povídat s 192.168.0.2 (default). Dobrá zpráva je:
(osgar) md@md-ThinkPad-P50:~/git/osgar$ ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=255 time=0.384 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=255 time=0.418 ms
64 bytes from 192.168.0.2: icmp_seq=3 ttl=255 time=0.408 ms
Také krabička po chvíli od připojení na baterku začala „vrnět”, tj. snad úplně cihla to není.
No není nad „přítele na telefonu”. Posli '\xFF\xAA\x00\x1E\x00\x00\x00\x00\x00\x00\x01\x01\x19\x0C\x00\x00\x00\x00\x00 \x00\x00\x00\x05\x03\x00\x00\x00\x00\x00\x00\x00\x0D\xEE\xEE' UDP packet na port 6050 a cti, co ti prijde zpatky. O parsovani te ale preci ochudit nemuzu!
(osgar) md@md-ThinkPad-P50:~/git/osgar$ python -m osgar.record -duration 10 
                      config/test-vanjee-lidar.json -note "port 6050, trigger from Jirka, in run()"
2023-11-04 19:29:25,123 root             WARNING  Environment variable OSGAR_LOGS is not set - using working directory
2023-11-04 19:29:25,124 __main__         INFO     /home/md/git/osgar/test-vanjee-lidar-231104_182925.log
2023-11-04 19:29:25,144 __main__         INFO     SIGINT handler installed
2023-11-04 19:29:35,176 __main__         ERROR      vanjee_udp: maximum delay of 0:00:10.031742 at 0:00:10.052223

(osgar) md@md-ThinkPad-P50:~/git/osgar$ python -m osgar.logger /home/md/git/osgar/test-vanjee-lidar-231104_182925.log 
 k           name   bytes | count | freq Hz
--------—
 0            sys  130460 | 1591 | 158.3Hz
 1     vanjee.raw      36 |    1 |   0.1Hz
 2     vanjee.xyz       0 |    0 |   0.0Hz
 3    vanjee.scan       0 |    0 |   0.0Hz
 4 vanjee_udp.raw 2198431 | 1586 | 157.8Hz

Total time 0:00:10.052477
Za mne dobrý! Myslím, že můžu v klidu vypnout počítač (v sobotu mám typicky „odvykačku” ) … co ty pakety obsahují tedy až zítra.
p.s. pokud by někoho zajímaly detaily, tak viz https://github.com/robotika/osgar/compare/feature/vanjee-lidar

5. listopadu 2023 — Parsování dat

Tak jo, venku je tma, tak hurá na bitíky … Upravil jsem původní callback z
def on_raw(self, data):
    pass
na
def on_raw(self, data):
    assert len(data) == 0, len(data)
a pak pustil přehrávání logu:
(osgar) md@md-ThinkPad-P50:~/git/osgar$ python -m osgar.replay -module vanjee 
                                                test-vanjee-lidar-231104_182925.log
original args: b"['/home/md/git/osgar/osgar/record.py', '-duration', '10', 'config/test-vanjee-lidar.json',
                  '-note', 'port 6050, trigger from Jirka, in run()']"
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 24, in run
    self.update()
  File "/home/md/git/osgar/osgar/node.py", line 36, in update
    handler(data)
  File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 17, in on_raw
    assert len(data) == 0, len(data)
AssertionError: 34
maximum delay: 0:00:00
… což takto malý paket jsem opravdu nečekal. Asi je to odpověď na ten magic packet?
Tak znova replay a změna očekávané hodnoty na 34:
File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 17, in on_raw
    assert len(data) == 34, len(data)
AssertionError: 1384
… to už vypadá spíše jako point cloud data.
OK, tak teď už na
assert len(data) in [34, 1384], len(data)
projde celá 10s nahrávka ze včerejška. The effective length of the WLR-719C data packet is 1380 bytes … hmm, skoro.
File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 20, in on_raw
    assert data[:2] == b'\xFF\xAB', data[:2].hex()
AssertionError: ffaa
tj. na začátku je SoF, Start of frame (to FFAB jsem tam dal úmyslně, aby to selhalo a vypsalo to očekávane FFAA)
length = struct.unpack_from('<H', data, 2)
        assert length == 42, length
…
  File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 22, in on_raw
    assert length == 42, length
AssertionError: (25605,)
hmm, nečekané, tj. obrácený endians?
length = struct.unpack_from('>H', data, 2)
        assert length == 42, length
…
  File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 22, in on_raw
    assert length == 42, length
AssertionError: (1380,)
… lepší, jen jsem zapomněl si vzít 0tý prvek a ta délka tedy snad už odpovídá tomu the effective length.
frame = struct.unpack_from('>H', data, 4)[0]
… to už pěkně jede od 1 dále.
assert data[6:10] == bytes.fromhex('00000000'), data[6:10].hex()
…
  File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 24, in on_raw
    assert data[6:10] == bytes.fromhex('00000000'), data[6:10].hex()
AssertionError: 000007f9
… tak to už očekávané není. Vycházím z PDFka stažitelného v download sekci výrobce. A pro případ, že by to zmizelo, tak zde je očekávaný začátek paketu:
úvodní část paketu
úvodní část paketu
… prostě rezervovaná data jsou jiná, což si nemůžeme moc stěžovat … od toho jsou rezervovaná. A mění se:
assert data[6:10] == bytes.fromhex('000007f9'), data[6:10].hex()
AssertionError: 000007fa
Další bajty …
assert data[11:14] == bytes.fromhex('02 000C'), data[11:14].hex()
AssertionError: 02190c
… jako s assertama na real-time robotovi je „trošku” problém, ale zatím mi to přijde jako nejrychlejší způsob porovnání co říká dokumentace a co leze ze zařízení. Tj. asi nějaký nový device type?
bank, motor_speed = struct.unpack_from('>BH', data, 18)
assert 1 <= bank <= 16, bank
assert 38000 <= motor_speed <= 39300, motor_speed
… banky, jak slibovali (ne že bych tušil co že to je) a rychlosti motoru jsou proměnné — časem asi budu muset zvednout, resp. assert zrušit.
Ještě tam nejsme, ale blíží se to …
druhá část paketu
druhá část paketu
Už to taková zábava není … asi chápu Jirku, že preferuje, když dokumentace je generovaná stejně tak s parsery pro všechny možné programovací jazyky. No nic, ověřil jsem ještě EEEE na konci a teď je na čase se zakousnout do té největší časti (jj, checksum by to asi také chělo ověřit). NTP bych si nechal někdy na jindy.
1350 bajtů co má nést informaci o 450 bodech = 3 bajty na bod. 10 circles/second; 7200 points/circle; Scanning data -10°, -5°, 0°, 0.3° in sequence; 24 bytes per point, 1-byte reserved + 7-byte intensity + 16-byte distance. … to zní opravdu drsně. Tak alespoň sedí, že 450 bodů krát 16 bank je těch 7200 bodu na otočku.
... every 3 bytes corresponds to a single point cloud information. It outputs point cloud data at -10°, -5°, 0° and 0.3° in cycle, where the lower 7 bits of the first byte represent the intensity value, and the last two bytes represent the distance … aha, tak oni si také pletou bity a bajty, fajn. Tj. nikoliv 24 bajtů, ale pouze 24 bitu = 3 bajty a rezervovaný je jen jeden bit u intenzity.
points = struct.unpack_from('>' + 'BH' * 450, data, 21)
assert 0, points[:20]
…
  File "/home/md/git/osgar/osgar/drivers/vanjee.py", line 35, in on_raw
    assert 0, points[:20]
AssertionError: (4, 808, 16, 980, 10, 0, 4, 111, 0, 0, 17, 976, 0, 0, 16, 0, 0, 0, 17, 971)
… jako není to obrázek v lidarview, co jsem měl původně v plánu, ale timeout 2 hodiny právě nastal a asi bych si dal večeři a pokračování zítra (??? … ono je to pracovní den a večer je DARPA DTC kick-off, takže tomu dávám jen 30%).

6. listopadu 2023 — Lidarview

Dnes jenom rychlovka. Ty banky 1 až 16 vypadají jako pouze rozdělení velkého scanu na bloky, tj. je třeba je slepit dohromady a pak pracovat s celým scanem. Trošku mne zmátlo, že to „řežou v půlce” — ty body jdou za sebou podle jednotlivých vrstev pro -10, -5, 0 a +0.3 stupně. Prostě 450 úplně není dělitelné 4 (vrstvami). Slepené je to OK.
Když teď Jakub nově oprášil OSGAR driver replay, který simuluje v běžícím systému data z původní nahrávky, tak jsem mohl i doplnit vanjee.scan, který na začátku implementován nebyl.
{
  "version": 2,
  "robot": {
    "modules": {
      "vanjee": {
          "driver": "vanjee",
          "in": ["raw"],
          "out": ["raw", "scan"],
          "init": {}
      },
      "vanjee_udp": {
          "driver": "replay",
          "in": ["raw"],
          "out": ["raw"],
          "init": {
              "filename": "/home/md/git/osgar/test-vanjee-lidar-231104_182925.log",
              "pins": {"vanjee_udp.raw":  "raw"}
          }
      }
    },
    "links": [["vanjee_udp.raw", "vanjee.raw"],
              ["vanjee.raw", "vanjee_udp.raw"]
      ]
  }
}
A když jsem restartoval celý počítač, abych si zase mohl pustit lidarview, tak jsem dostal:
p.s. to restartování mne hrozně irituje, ale vždy mi nějakou dobu trvá si vzpomenout, co že je to za problém :-(
(osgar) md@md-ThinkPad-P50:~/git/osgar$ python -m osgar.tools.lidarview
   /home/md/git/osgar/test-replay-vanjee-lidar-231106_100810.log –lidar vanjee.scan
X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  152 (GLX)
  Minor opcode of failed request:  3 (X_GLXCreateContext)
  Value in failed request:  0x0
  Serial number of failed request:  91
  Current serial number in output stream:  92

10. březen 2024 — Zapojení a WAGO spojky

Číňan měl pravdu, že jsem s „VanJee blogem” moc nepostoupil. To ale neznamená, že jsem si s lidarem vůbec nehrál! Nějaký čas jsem s ním jezdil na robotu Eduro a zkoušel ICP (viz průvodce scan matching). Pak se ale ukázalo, že pro dostatečné vykrytí prostoru před robotem stejně potřebuji zapojit kameru a tak se pozornost přesunula na OAK-D Pro. Včera jsem lidar konečně přidělal na Pata a dnes se snažil narychlo nasbírat nějaká data venku:
Už jsem za tu dobu zapomněl, co je ten žlutý kabel, tak pro příště vytrhávám z dokumentace:
  • Negative pole of the power supply is black (wire 1)
  • Positive pole of the power supply is red (wire 2)
  • Chassis ground is yellow (wire 3)
Toto byla také moje první zkušenost s WAGO spojkami. Ostatní je používají, tak jen varování, že jsou dva druhy — WAGO 2273 - na tuhé dráty (ty nechcete) a dále WAGO 221, které jednoduše zaklapnete. Pokud si chcete dělat elektriku, tak jsem při tom narazil na celkem koukatelné video: Základní práce s Wago svorkami, kontrolní otvory bez rozebrání a tipy (Elektrika pro začátečníky)
A jak vypadají dnešní data? No nijak, protože když jsem zapojil Ethernetový kabel lidaru, tak jsem ztratil wifinu. Ano, je to mým nastavením na počítači, ale dohledávat skript na změnu IP od Jirky nebyl čas. :-( Tak snad příští týden bude už datová sada kompletní.