13.1.9. A Csatornák nézet#

A képkocka-puffer azt mutatja, amit a kamera lát; a Csatornák nézet azt, amit a szkript mér és eldönt. A szkript nevesített értékeket tesz közzé a hibakeresési protokollon keresztül – egy hőmérsékletet, egy észlelésszámot, egy mikrofon-hullámformát, egy repülésiidő-mélységtérképet, vagy egy vezérlőt, amelyet a felhasználó számára módosíthatóvá akar tenni –, az IDE pedig mindegyiket élőben jeleníti meg widgetként, grafikonként vagy térképként a képkocka-puffer alatti ablaktáblában. Semmit sem kell a képre rajzolni vagy a terminálból kiszedni. A kamera oldalán ez néhány sor a protocol.CBORChannel-lel; az IDE oldalán pedig a ablaktábla-választó Csatornák bejegyzése.

The Channels view showing a thermal camera script's controls channel: FPA and AUX temperature readouts with their unit, Measurement and High Temp toggles, Temp Min and Temp Max sliders, and H-Mirror and V-Flip toggles

Egy hőkamera-szkript vezérlői: két hőmérséklet-kiolvasás, kapcsolók a mérési módokhoz, és csúszkák a hőmérséklet-tartományhoz. Bármelyik módosítása elküldi az új értéket a szkriptnek.#

A nézet csatornánként van rendezve. Minden, a szkript által regisztrált csatorna egy szakasz lesz a csatorna nevével a címsorában, és a csatorna minden rekordja egy sor alatta, abban a sorrendben, ahogy a szkript hozzáadta őket. Amikor a szkript csatornát regisztrál vagy megváltoztatja egy csatorna alakját, a nézet újraépíti magát; amikor a szkript leáll, az utolsó értékek a képernyőn maradnak, letiltott vezérlőkkel, amíg a következő szkript el nem indul.

13.1.9.1. Widgetek#

A kiolvasások és vezérlők a kézenfekvő formákat öltik. A label egy csak olvasható érték a mértékegységével; a text rekord statikus formázott szövegblokk címsorokhoz és magyarázatokhoz. Az írható fajták a módosítás pillanatában visszaküldik az új értéküket a szkriptnek, ahol a szkript on_write visszahívása megkapja a rekord nevét és értékét: a toggle egy kapcsoló, a slider és a spinbox egy számot állít be a szkript tartományán és lépésközén belül (a léptetőmező a pontos bevitelhez), a radio gombok és a select a szkript opciói közül választanak egyet, a lineedit szabad szöveges mező, a pushbutton pedig pillanatnyi műveletet indít. A nézet a szerkesztésedet tartja a képernyőn, és nem ugrik vissza a kamera utoljára közzétett értékére, amíg az írás folyamatban van.

A szkript oldalán az egész készlet egy protocol.CBORChannel, widgetenként egy add hívással és egy visszahívással az írásokhoz:

import time
import protocol
from protocol import CBORChannel

def on_write(ch, name, value):
    print(name, "=", value)      # every change lands here

ch = CBORChannel(on_write=on_write)
ch.add("Status", type="label", value="starting")
ch.add("Enable", type="toggle", value=True)
ch.add("Threshold", type="slider", min=0, max=100,
       step=1, value=50, unit="%")
ch.add("Mode", type="select",
       options=["Idle", "Track", "Record"], value="Idle")
ch.add("Calibrate", type="pushbutton")
protocol.register(name="controls", backend=ch)

while True:
    if ch["Enable"]:                   # read a control back
        ch["Status"] = "threshold %d%%" % ch["Threshold"]
    time.sleep_ms(100)

Futtasd, és váltsd az ablaktáblát a Csatornák nézetre: megjelenik egy controls nevű szakasz az öt widgettel, és a csúszka mozgatása kiír a terminálba. A többi widgettípus – spinbox, radio, lineedit, text – egy-egy további add; a gazdagép-protokoll fejezet mindegyiket végigveszi.

13.1.9.2. Hullámformagrafikonok#

A hullámforma rekord egymásba fésült minták blokkja mintavételi sebességgel – hang, gyorsulásmérő-tengelyek, ADC-görbe –, és a nézet görgetődő grafikonként ábrázolja, tengelyenként egy, a szkript által elnevezett adatsorral. A grafikon vezérlői az eszköztárán és magán az ábrán vannak:

  • Húzással pásztázhatsz, görgetéssel nagyíthatsz; dupla kattintással visszatérsz az élő szél követéséhez. Az Előzmények beállítja, mennyi korábbi adat marad meg, hogy vissza tudj pásztázni benne.

  • Az Automatikus skála a függőleges tengelyt az adatokhoz igazítja; kikapcsolva a tengely a szkript által deklarált tartomány.

  • Kattints jobb gombbal az ábrára egy jelölő elhelyezéséhez, hogy leolvasd egy minta pontos idejét és értékét, vagy egy kioldási szint beállításához. Élesített Kioldó mellett a grafikon mozdulatlan marad, amíg a jel felfutó vagy lefutó élen át nem lépi a szintet – a tranziensek elkapásának oszcilloszkópos módja –, az Újraélesítés pedig a következőre vár.

  • A Spektrum a grafikont ugyanazon adatok frekvenciaábrájára váltja, választható ablakkal (Hann, Hamming, Blackman, négyszögletes), képkockákon átívelő Átlagolás és Csúcstartás lehetőséggel, valamint Log. frekvencia tengellyel. A grafikon alatti kiolvasás megnevezi a csúcsfrekvenciát és annak szintjét.

  • A Szünet lefagyasztja a grafikont anélkül, hogy a felvételt befolyásolná; a Stat. egy min / max / RMS sort ad hozzá; a jobb gombos menü pedig képként menti a grafikont.

The Channels view with two waveform records scrolling live: a 16 kHz microphone trace and a three-series accelerometer trace with its X, Y, and Z legend, each with its Record, Spectrum, Pause, and Stats buttons

Két élőben görgetődő hullámformarekord: egy mikrofongörbe és egy háromsoros IMU-görbe.#

A hullámformamező a mintavételi sebességet, és több jel egyszerre való küldéséhez az egymásba fésült series számát és neveit veszi át; minden frissítés egy, a mező typecode-jában lévő mintákból álló array nyers bájtjai:

import math
import time
import protocol
from array import array
from protocol import CBORChannel

RATE, CHUNK = 1000, 100            # 1 kHz, 100 ms per update

ch = CBORChannel()
ch.add("IMU", type="waveform", sample_rate=RATE, series=3,
       typecode="f", min=-2.0, max=2.0,
       options=["X", "Y", "Z"], unit="g")
protocol.register(name="signals", backend=ch)

t = 0
while True:
    block = array("f")
    for i in range(CHUNK):
        phase = 2 * math.pi * 2 * (t + i) / RATE
        block.extend((math.sin(phase), math.cos(phase), 1.0))
    ch["IMU"] = bytes(block)        # interleaved X, Y, Z
    t += CHUNK
    time.sleep_ms(100)

13.1.9.3. Mélységtérképek#

A mélység rekord távolságok rácsa – a képkockák, amelyeket egy repülésiidő-érzékelő (time-of-flight) előállít –, és a nézet hamisszínes térképként rajzolja ki, a grafikon magasságára felnagyítva. Az eszköztár választja ki a megjelenítést: a palettát (a kamera saját Depth, Rainbow és Ironbow palettái, plusz világos és sötét paletták az eseménykamerákhoz), a kis érzékelőrácsot felnagyító méretezési szűrőt (bikubikus a sima felülethez, bilineáris, vagy legközelebbi az érzékelőképpontonként egy blokkhoz), és a távolságot színné alakító tónusleképezést: a Szkript tartomány a szkript által deklarált tartományt használja, az Auto tartomány a színeket az egyes képkockákban ténylegesen jelen lévő távolságokra feszíti ki (a kiugró néhány százalékot figyelmen kívül hagyva), a Kiegyenlítés pedig a képkocka eloszlása szerint teríti szét őket, így egy lapos jelenet is mutatja a részleteit. A fejléc a térkép méretét, a deklarált tartományt, valamint a képkocka minimumát, maximumát és átlagát jelenti; az egérmutatót a térkép fölé víve a kurzor alatti távolság olvasható le, a Kép mentése pedig PNG-be írja a kirajzolt térképet.

The Channels view showing an 8 x 8 time-of-flight depth map scaled up smoothly with the Depth palette, the palette, scaling, and tone-mapping selectors in its toolbar, and the header reporting the size, declared range, and the frame's minimum, maximum, and mean

Egy repülésiidő-érzékelő mélységtérképe egy, az érzékelő előtt lévő kézről, az eszköztárban a paletta-, méretezés- és tónusleképezés-választókkal.#

A mélységmező deklarálja a rácsméretét és tartományát; minden frissítés maga a rács tömörített 32 bites lebegőpontos számokként, amit a tof modul olvasója állít elő:

import struct
import time
import tof
import protocol
from protocol import CBORChannel

tof.init()
ch = CBORChannel()
ch.add("depth", type="depth", width=tof.width(),
       height=tof.height(), min=0, max=1000)
protocol.register(name="ToF", backend=ch)

while True:
    try:
        d, dmin, dmax = tof.read_depth(vflip=True, hmirror=True)
    except RuntimeError:
        continue
    ch["depth"] = struct.pack("<%df" % len(d), *d)
    time.sleep_ms(50)

13.1.9.4. Felvétel#

Minden grafikonnak és térképnek van egy Record gombja, és az egynél többel rendelkező csatornának egy Record All sávja, amely együtt indítja őket. A felvétel az adatokat – nem a megjelenítést – érkezésükkor írja egy fájlba, amelynek formátuma a mentési párbeszédablakban választott kiterjesztést követi: CSV táblázatkezelőkhöz és ábrázoló eszközökhöz, WAV egycsatornás hang-hullámformákhoz, NumPy .npy tömbök Pythonhoz, és Edge Impulse JSON vagy CBOR, hogy közvetlenül egy Edge Impulse projektbe tölthesd fel tanítóadatként, opcionális címkével, amely elnevezi a fájlokat. Csak azok a formátumok kerülnek felkínálásra, amelyek képesek a rekord adatait tárolni; egy mélységtérkép például nem lehet WAV fájl. A hosszú felvétel sorszámozott részekre oszlik, hogy egyetlen fájl se nőjön kezelhetetlenre, és a felvétel túléli, ha a szkript újraregisztrálja a csatornáit. A gomb melletti kiolvasás követi, hány minta lett kiírva, és mekkora a fájl.

Az ablaktábla Channel Polling intervalluma, a beállítások protokoll szakaszában, azt szabályozza, milyen gyakran kéri az IDE a kamerától az új csatornaadatokat; az alapértelmezés a másodpercenként néhányszor közzétevő szkriptekhez megfelelő, egy hangot közvetítő szkriptnek pedig rövidebb intervallum válik hasznára.

Lásd még

protocol.CBORChannel a szkript oldalához – a rekordtípusok, az argumentumaik és az on_write visszahívás –, valamint a File → Examples alatti 12-Protocol példák működő szkriptekhez, amelyek kiolvasásokat, vezérlőket és egy mélységtérképet tesznek közzé.