家裡還是要有linux才行...
所以買了adata sc860 usb3.2 ssd 來裝。
pchome 特價 240G, 999
安裝 OK,但是很奇怪,SSD 端是 type C 頭,另一端雖然有 Type A 跟 Type C 頭。但是只有 type C 頭偵測得到開機碟。
-- 是因為當初安裝就是用 type C 頭?
速度果很快,比USB 3.1, 3.5" 外接硬碟還快。
安裝 ubuntu 18.03, Mate, cuda10.1 + pytorch 共用掉 20G。
原來還發生Power Off 卡住的狀況,後來沒有發生了。
實際的 Read/Write 速度沒有測,在另一個 blog,有用 windows 10 測過,Write speed 約 110MB/s
在這裡,用 ubuntu,, 開機是很快沒錯。
2020/6/29
2020/6/24
conf , in linux kernel source
make menuconfig, qconfig, xconfig .. etc 都是 call scripts/kconfig 下的 tool
scripts/kconfig 是一個獨立的tools, 包含一堆 conf.
Makefile 有說明裡面的執行檔 (不是 target..)
linux 的 kconfig 比較大,buildroot 的 kconfig 比較小,可以從buildroot 的 kconfig 看起。
scripts/kconfig 是一個獨立的tools, 包含一堆 conf.
Makefile 有說明裡面的執行檔 (不是 target..)
# =========================================================================== # Shared Makefile for the various kconfig executables: # conf: Used for defconfig, oldconfig and related targets # nconf: Used for the nconfig target. # Utilizes ncurses # mconf: Used for the menuconfig target # Utilizes the lxdialog package # qconf: Used for the xconfig target # Based on Qt which needs to be installed to compile it # gconf: Used for the gconfig target # Based on GTK+ which needs to be installed to compile it這幾個 conf 有共用的部份。
- conf : 沒有 ui,就是單純run check .config
- mconf: 用lxdialog 這個 library 做出 ui 的 config
linux 的 kconfig 比較大,buildroot 的 kconfig 比較小,可以從buildroot 的 kconfig 看起。
Makefile : target with variable %
kernel 或是一堆使用 menuconfig 的 project 在 make 之前都要 make XXX_config 或是 make XXX_defconfig。
然後這個 XXX_config , XXX_defconfig 還很有趣的是某個 file 的 filename..
所以是怎麼動態知道 filename as target 的呢?
就是用 Makefile 的 萬用配對符號: %
然後這個 XXX_config , XXX_defconfig 還很有趣的是某個 file 的 filename..
所以是怎麼動態知道 filename as target 的呢?
就是用 Makefile 的 萬用配對符號: %
%_config: $(BOARD_DIR)/config/%_config @$(GEN_CONF) $(TOPDIR)/build/kconfig/conf --defconfig=$<當然也有先把conf 下所有的 _defconfig 找出來做成target 的方法..
Makefile and shell script : echo command out
有時候,希望 Makefile 和 shell script 把執行當時的 command 印出來,
這樣比較容易trace 變數
shell script 的話,參考 這一篇..
在 shell script 的開頭加上..
Makefile 的話,一般都會印出執行的 command,除非在 command rule 之前有加 '@' 符號。
所以記得,把 '@' 刪除。
另外,make 的 option '-s' 也是 silenct 的意思,ref: make options。
所以要記得把 -s 刪掉。
這樣比較容易trace 變數
shell script 的話,參考 這一篇..
在 shell script 的開頭加上..
set -x也可用
bash -x myscipt.sh也可以
Makefile 的話,一般都會印出執行的 command,除非在 command rule 之前有加 '@' 符號。
所以記得,把 '@' 刪除。
另外,make 的 option '-s' 也是 silenct 的意思,ref: make options。
所以要記得把 -s 刪掉。
Makefile : about folders.
Makefile 中檢查folder 在不在
這一個 是動作不多的時候,利用 "一行" 的特性..
另外這一篇 前同事的 blog,是一般的,用 wildcard檢查好 create...
還有一個,看起來好像比較笨..在Makefile 中 call shell command 來做...
這一個 是動作不多的時候,利用 "一行" 的特性..
foo.bak: foo.bar echo "foo" if [ -d "~/Dropbox" ]; then echo "Dir exists"; fi或
oo.bak: foo.bar echo "foo" if [ -d "~/Dropbox" ]; then \ echo "Dir exists"; \ fi
另外這一篇 前同事的 blog,是一般的,用 wildcard檢查好 create...
OUTPUT_PATH := test all: ifeq "$(wildcard $(OUTPUT_PATH))" "" mkdir $(OUTPUT_PATH) echo "directory not existed" else echo "directory existed" endif
還有一個,看起來好像比較笨..在Makefile 中 call shell command 來做...
ifeq ($(shell [ -d $(OUTPUT_PATH) ] && echo y), y) echo "directory existed" else echo "directory not existed" endif
2020/6/23
mkfs.cramfs in 18.04
if [ ${OS_VERS_MAJ} -lt 18 ]; then INSTALLPKGS+=(mtd-tools) INSTALLPKGS+=(cramfsprogs) else INSTALLPKGS+=(mtd-utils) INSTALLPKGS+=(util-linux) fi原來 mkfs.cramfs 在不同的 ubuntu 版本,在不同的 package 裡..
2020/6/15
OpenRadar ..使用說明..
OpenRadar 這個 python 專案,真的很佛心。
把TI 沒給的東西都寫出來了,還是用 python,不必用 matlab.
雖然只是基礎而已,已經很有幫助了。
這個 Project 是用 python 來分析 DCA1000EVM 送出的 LVDS (ADC Data),也是是 raw data
他包含了:
所以 AWR1642 的 command 要自己做..用 uart 連線,送 config command..
基本的處理是在 Presense Applied Radar/basic 目錄下的 jupyter file (*.ipyb)
可以看到每個 sample code,一開始都是用np.load('XXX') 讀取預存資料。
所以 log DCA1000EVM 的部份,要另外做。
可以參考 dataloader/adc.py 的註解:
但是其中沒說明 AWR1642 chirp config 的內容,要和 adc.py 的參數。還有 orgnize( ) 的參數一致。
這部份,就要看 adc.py 的 source code,和blog 前面幾篇的內容。
因為 adc.py 要靠這些參數決定一個 frame 是多少packet。
同時,oragnize( ) 也需要這些參數才知道怎嬷分割 資料..
另外,adc.py 中,對 DCA1000EVM 的命令,並不會啟動udp 資料。
所以要照 blog 的修改,加上start_record( ) command .
大概就是這樣 (為什麼不修好?)
最後,總結 OpenRadar 這格 project 的使用方法...
把TI 沒給的東西都寫出來了,還是用 python,不必用 matlab.
雖然只是基礎而已,已經很有幫助了。
這個 Project 是用 python 來分析 DCA1000EVM 送出的 LVDS (ADC Data),也是是 raw data
他包含了:
- 送 command 給 DCA1000EVM,開始/停止 loggin
- 讀取 UDP 封包,分析,組合成一個 frame data
- rage fft, doppler fft, angle of arrival function library
所以 AWR1642 的 command 要自己做..用 uart 連線,送 config command..
基本的處理是在 Presense Applied Radar/basic 目錄下的 jupyter file (*.ipyb)
- Range - COMPLETED.ipynb : 畫出一個 chirp recived data的 range fft
- Doppler - COMPLETED.ipynb : 畫出一個 frame 的 range-doppler diagram
- Angle of Arrival - COMPLETED.ipynb : 畫出一個 frame 的 object 的 angle of arrival diagram
可以看到每個 sample code,一開始都是用np.load('XXX') 讀取預存資料。
所以 log DCA1000EVM 的部份,要另外做。
可以參考 dataloader/adc.py 的註解:
General steps are as follows: 1. Power cycle DCA1000 and XWR1xxx sensor 2. Open mmWaveStudio and setup normally until tab SensorConfig or use lua script 3. Make sure to connect mmWaveStudio to the board via ethernet 4. Start streaming data 5. Read in frames using class Examples: dca = DCA1000() adc_data = dca.read(timeout=.1) frame = dca.organize(adc_data, 128, 4, 256)這樣就取得一個 frame 的資料。
但是其中沒說明 AWR1642 chirp config 的內容,要和 adc.py 的參數。還有 orgnize( ) 的參數一致。
這部份,就要看 adc.py 的 source code,和blog 前面幾篇的內容。
因為 adc.py 要靠這些參數決定一個 frame 是多少packet。
同時,oragnize( ) 也需要這些參數才知道怎嬷分割 資料..
另外,adc.py 中,對 DCA1000EVM 的命令,並不會啟動udp 資料。
所以要照 blog 的修改,加上start_record( ) command .
大概就是這樣 (為什麼不修好?)
最後,總結 OpenRadar 這格 project 的使用方法...
- checkout 出來 -- 因為依照說明,用 pip install default packcage 的話,adc.py 的 chirp 參數沒辦法修改
- 修改source 的 module loading path. 這樣才 import 得到正確的 source
- 依照AWR1642 的 chirp config,修改 adc.py 的chirp parameters
- 把 start, stop record command 加到 adc.py 中
- uart 連接 AWR1642, 送出config
- follow adc.py 的example,config. start_record, 讀取 frame,存檔
- 參考basic/*.ipynb, 讀取剛剛存檔的內容,做 range, doppler, aoa
2020/6/12
完整做一次... save frame, draw range FFT..
AWR1642BOOST config command:
然後再改成二維陣列,每個 chirp 一個element.
然後把一個rx 的 chirp 畫出來看...
這個樣子..感覺應該是 signed 才對 (值很靠近 0, 所以負值以unsigned 看來看0xFFxx 變得很大)
看 OpenRadar 的 basic/range.ipynb,其中有說明:
所以修改 adc.py,存的時候就用 int16,不用 uint16,這樣np.load 後,也會是 int16.
上面的 code ,不用修改,就變成:
看起來比剛剛正常。
進型 FFT 後...
sensorStop flushCfg dfeDataOutputMode 1 channelCfg 15 3 0 adcCfg 2 1 adcbufCfg -1 0 0 1 0 profileCfg 0 77 429 7 57.14 0 0 70 1 256 5209 0 0 30 chirpCfg 0 0 0 0 0 0 0 1 chirpCfg 1 1 0 0 0 0 0 2 frameCfg 0 1 16 0 100 1 0 lowPower 0 1 guiMonitor -1 1 1 0 0 0 1 cfarCfg -1 0 0 8 4 4 0 5120 cfarCfg -1 1 0 4 2 3 0 5120 peakGrouping -1 1 1 1 1 255 multiObjBeamForming -1 1 0.5 clutterRemoval -1 0 calibDcRangeSig -1 0 -5 8 256 extendedMaxVelocity -1 0 bpmCfg -1 0 0 1 lvdsStreamCfg -1 0 1 0 nearFieldCfg -1 0 0 0 compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 measureRangeBiasAndRxChanPhase 0 1.5 0.2 CQRxSatMonitor 0 3 5 123 0 CQSigImgMonitor 0 127 4 analogMonitor 1 1 sensorStart這樣,adc.py 的chirp/frame 參數是:
ADC_PARAMS = {'chirps': 16, 'rx': 4, 'tx': 2, 'samples': 256, 'IQ': 2, 'bytes': 2}用 dca1000test:tryadc 的 testadc.c...
from adc import DCA1000 import numpy as np dca = DCA1000() dca.send_start_command() adc_data = dca.read(timeout=.1) np.save('framedata',adc_data) dca.send_stop_command()save 一個 frame 的資料 framedata.npy。
import numpy as np import matplotlib.pyplot as plt rawdata = np.load('framedata.npy') rxdata = np.zeros(len(rawdata)//2, dtype=complex) rxdata[0::2] = rawdata[0::4] + 1j * rawdata[2::4] rxdata[1::2] = rawdata[1::4] + 1j * rawdata[3::4] rxchirp = rxdata.reshape((16*4*2,256))把 data 讀進來,依照 udp data format 的順序,和 chirp parameters, 轉成 complex,
然後再改成二維陣列,每個 chirp 一個element.
然後把一個rx 的 chirp 畫出來看...
plt.plot(np.abs(rxchirp[0])) plt.show()
這個樣子..感覺應該是 signed 才對 (值很靠近 0, 所以負值以unsigned 看來看0xFFxx 變得很大)
看 OpenRadar 的 basic/range.ipynb,其中有說明:
#Read in chirp data addc_samples = np.loadtxt('../assets/chirp.txt',dtype=np.complex) #Manually cast to signed ints adc_samples.real = adc_samples.real.astype(np.int16) adc_samples.imag = adc_samples.imag.astype(np.int16) #Take FFT across ADC samples range_bins = np.fft.fft(adc_samples) # Plot the magnititude of the range bins plt.plot(np.abs(range_bins)) plt.show()果然,讀近來之後,要 cast 成 int16
所以修改 adc.py,存的時候就用 int16,不用 uint16,這樣np.load 後,也會是 int16.
上面的 code ,不用修改,就變成:
看起來比剛剛正常。
進型 FFT 後...
plt.plot(np.abs(np.fft.fft(rxchirp[0]))) plt.show( )顯示正確的 range peak:
2020/6/11
send, receive file in python
多電腦操作很麻煩...A NB 取得資料,B 分析。C對照。
用網路芳鄰還要用 mouse 拖拉很麻煩。
所以練習一下python...
附帶,, 在 Windows 上就是麻煩,不能直接 run py, 還要寫一個 bat.
所以把他 build 成 exe.
要用 tool : pyinstaller
可以直接 run 了...
測試,exe copy 到其他機器上也可以正常執行,沒有環境問題。
用網路芳鄰還要用 mouse 拖拉很麻煩。
所以練習一下python...
ppscv localip 收檔,,不關掉的話會一直收... ppsend targetip filename 傳檔,一次只能傳一個.. 果然是很低級的....
附帶,, 在 Windows 上就是麻煩,不能直接 run py, 還要寫一個 bat.
所以把他 build 成 exe.
要用 tool : pyinstaller
conda install pyinstaller pyinstaller -F pprcv.py這樣就在 dist 下產生一個 pprcv.exe。
可以直接 run 了...
測試,exe copy 到其他機器上也可以正常執行,沒有環境問題。
Modify OpenRadar command code
從python code to command DCA1000EVM Start/Stop Record
把這個啟動命令寫到 adc.py:
adc.py 的 command 宣告:
send command 的 function 是
把這個啟動命令寫到 adc.py:
adc.py 的 command 宣告:
class CMD(Enum): RESET_FPGA_CMD_CODE = '0100' RESET_AR_DEV_CMD_CODE = '0200' CONFIG_FPGA_GEN_CMD_CODE = '0300' CONFIG_EEPROM_CMD_CODE = '0400' RECORD_START_CMD_CODE = '0500' RECORD_STOP_CMD_CODE = '0600' PLAYBACK_START_CMD_CODE = '0700' PLAYBACK_STOP_CMD_CODE = '0800' SYSTEM_CONNECT_CMD_CODE = '0900' SYSTEM_ERROR_CMD_CODE = '0a00' CONFIG_PACKET_DATA_CMD_CODE = '0b00' CONFIG_DATA_MODE_AR_DEV_CMD_CODE = '0c00' INIT_FPGA_PLAYBACK_CMD_CODE = '0d00' READ_FPGA_VERSION_CMD_CODE = '0e00'對應ref 的內容,依序是送...
- 5aa50300060001020102031eaaee : CONFIG_FPGA_GEN_CMD_CODE
- 5aa509000000aaee : SYSTEM_CONNECT_CMD_COD
- 5aa505000000aaee : RECORD_START_CMD_COD
- 5aa506000000aaee : RECORD_STOP_CMD_CODE
send command 的 function 是
def _send_command(self, cmd, length='0000', body='', timeout=1): """Helper function to send a single commmand to the FPGA Args: cmd (CMD): Command code to send to the FPGA length (str): Length of the body of the command (if any) body (str): Body information of the command timeout (int): Time in seconds to wait for socket data until timeout Returns: str: Response message """ # Create timeout exception self.config_socket.settimeout(timeout) # Create and send message resp = '' msg = codecs.decode(''.join((CONFIG_HEADER, str(cmd), length, body, CONFIG_FOOTER)), 'hex') try: self.config_socket.sendto(msg, self.cfg_dest) resp, addr = self.config_socket.recvfrom(MAX_PACKET_SIZE) except socket.timeout as e: print(e) return resp所以對應上面的命令應該是...
_send_command(CONFIG_FPGA_GEN_CMD_CODE,'0600','01020102031e') _send_command(SYSTEM_CONNECT_CMD_COD) _send_command(RECORD_START_CMD_COD)然後停止是
_send_command(RECORD_STOP_CMD_CODE)所以在 adc.py 中增加兩個 functions:
def send_start_command(self): print(self._send_command(CMD.CONFIG_FPGA_GEN_CMD_CODE,'0600','01020102031e')) print(self._send_command(CMD.SYSTEM_CONNECT_CMD_CODE)) print(self._send_command(CMD.RECORD_START_CMD_CODE)) def send_stop_command(self): print(self._send_command(CMD.RECORD_STOP_CMD_CODE))
2020/6/10
chirp config and adc.py parameters
再來一次。用 mmWave Demo Visualizer (2.1) 的 Best Range Resolution 的 command,並且改 lvdsStreamCfg 輸出..
sensorStop flushCfg dfeDataOutputMode 1 channelCfg 15 3 0 adcCfg 2 1 adcbufCfg -1 0 0 1 0 profileCfg 0 77 429 7 57.14 0 0 70 1 256 5209 0 0 30 chirpCfg 0 0 0 0 0 0 0 1 chirpCfg 1 1 0 0 0 0 0 2 frameCfg 0 1 16 0 100 1 0 lowPower 0 1 guiMonitor -1 1 1 0 0 0 1 cfarCfg -1 0 0 8 4 4 0 5120 cfarCfg -1 1 0 4 2 3 0 5120 peakGrouping -1 1 1 1 1 255 multiObjBeamForming -1 1 0.5 clutterRemoval -1 0 calibDcRangeSig -1 0 -5 8 256 extendedMaxVelocity -1 0 bpmCfg -1 0 0 1 lvdsStreamCfg -1 0 1 0 nearFieldCfg -1 0 0 0 compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 measureRangeBiasAndRxChanPhase 0 1.5 0.2 CQRxSatMonitor 0 3 5 123 0 CQSigImgMonitor 0 127 4 analogMonitor 1 1 sensorStart這個對應的參數:
- ADC Samples: 256
- Loop Per Frame : 16
- TX : 2
- RX : 4
numpy reshape
np.reshape( ) 是把 array 重新安排 (group) ,可以重新安排維度..
舉例,宣告出一個一維的 array..
其中,第一個維度..
三個維度的話...
先分成三個 group,每個 group 再分成兩個 group...
這樣每個最小 group 裡面有 4 個 item.
舉例,宣告出一個一維的 array..
import numpy as np A = np.array([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6])把他分成6個group,每個 group 有 4 個 item..
A.reshape((6,3)) array([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]])這樣就變成二維矩陣。
其中,第一個維度..
A.reshape((6,3))[0] array([1,1,1,1])
三個維度的話...
先分成三個 group,每個 group 再分成兩個 group...
這樣每個最小 group 裡面有 4 個 item.
A.reshape((3,2,4)) array([[[1, 1, 1, 1], [2, 2, 2, 2]], [[3, 3, 3, 3], [4, 4, 4, 4]], [[5, 5, 5, 5], [6, 6, 6, 6]]])每個維度的 index.. 和 item..
A.reshape((3,2,4))[1] array([[3, 3, 3, 3], [4, 4, 4, 4]]) A.reshape((3,2,4))[1][0] array([3, 3, 3, 3])
openradar , frame reshape and chirps. frame parameters
覺得有關 frame, chirps 的參數,在 realtime.py 和 adc.py 中不一致。
這個也和 AWR1642 config command 有關。
realtime.py 的參數:
跟 stanley 說明的一樣,一個 loop ,就是 一個 profile.
一個 frame 的定義就是 N 個 loop。
這個 numLoopsPerFrame 只有在 這裡有用到,其他 source code 的地方都沒有用。
adc.py 的參數:
但是 bytes_in_frame,刪掉 rx, samples. IO. bytes 後...
回到 realtime.py,讀完一個 frame 後..
說明,安排的方式...
所以...
回到 adc.py 跟 realtime.py:
參考 DCA1000EVM UDP RAW data format
raw data 是.. 每個chirp(不管是那一個 tx 送的),依照順序送 rx0,rx1,rx1,rx2 的 adc samples
所以 tx0, tx1 如果是依序送出的話, raw data 的資料也會依序是..
chirps 應該是 TX 發出的FMCW波。
每個 chirps 會有 N 個 rx 信號。
所以 chirps_number * rx_number = frame rx number
最後... adc.py 跟 realtime.py 要對的起來的地方...
adc.py 的 read( ) 一個 frame,要剛好跟 realtime.py 的 orgnize( ) 的一個 frame 的 size 一樣。
read( ) 一個 frame (扣除 IO 跟 bytes):
這個也和 AWR1642 config command 有關。
realtime.py 的參數:
numFrames = 300 numADCSamples = 128 numTxAntennas = 3 numRxAntennas = 4 numLoopsPerFrame = 128 numChirpsPerFrame = numTxAntennas * numLoopsPerFrame numRangeBins = numADCSamples numDopplerBins = numLoopsPerFrame numAngleBins = 64他有 numChirpsPFrame = numTxAntennas * numLoopsPerFrame
跟 stanley 說明的一樣,一個 loop ,就是 一個 profile.
一個 frame 的定義就是 N 個 loop。
這個 numLoopsPerFrame 只有在 這裡有用到,其他 source code 的地方都沒有用。
adc.py 的參數:
ADC_PARAMS = {'chirps': 128, 'rx': 4, 'tx': 3, 'samples': 128, 'IQ': 2, 'bytes': 2} BYTES_IN_FRAME = (ADC_PARAMS['chirps'] * ADC_PARAMS['rx'] * ADC_PARAMS['tx'] * ADC_PARAMS['IQ'] * ADC_PARAMS['samples'] * ADC_PARAMS['bytes'])直接用 chirps.
但是 bytes_in_frame,刪掉 rx, samples. IO. bytes 後...
chirps * tx這樣看起來 chirps 好像是 loops ?
回到 realtime.py,讀完一個 frame 後..
frame = dca.organize(adc_data, num_chirps=numChirpsPerFrame, num_rx=numRxAntennas, num_samples=numADCSamples)其中 organize() :
def organize(raw_frame, num_chirps, num_rx, num_samples): """Reorganizes raw ADC data into a full frame Args: raw_frame (ndarray): Data to format num_chirps : Number of chirps included in the frame num_rx : Number of receivers used in the frame num_samples : Number of ADC samples included in each chirp Returns: ndarray: Reformatted frame of raw data of shape (num_chirps, num_rx, num_samples) """ ret = np.zeros(len(raw_frame) // 2, dtype=complex) # Separate IQ data ret[0::2] = raw_frame[0::4] + 1j * raw_frame[2::4] ret[1::2] = raw_frame[1::4] + 1j * raw_frame[3::4] return ret.reshape((num_chirps, num_rx, num_samples))最後的 reshape(num_chirps, num_rx, num_samples)
說明,安排的方式...
([[S,......samples], <--rx0 第一個 chirp [S,......samples]], <--rx1 [[S,......samples], <--rx0 第二個 chirp [S,......samples]], <--rx1 ... .. [[S,......samples], 第 num_chirps-1 個chirp [S,......samples]])上面就是一個 frame.的所有 chirps.
所以...
framedata = data.organize(...) framedata[0] <-- 這是第一個 chirp 的 rx0,rx1 矩陣 framedata[0][1] <-- 這是第一個 chirp 的 rx1 array (所有 sample point)
回到 adc.py 跟 realtime.py:
參考 DCA1000EVM UDP RAW data format
raw data 是.. 每個chirp(不管是那一個 tx 送的),依照順序送 rx0,rx1,rx1,rx2 的 adc samples
所以 tx0, tx1 如果是依序送出的話, raw data 的資料也會依序是..
TX0 : rx0, rx1, rx2, rx3, TX1 : rx0, rx1, rx2, rx3所以orgnize( ) 是不用管TX0, TX1..他只需要知道一個 frame 到底有多少 chirp (TX0 + TX1)
chirps 應該是 TX 發出的FMCW波。
每個 chirps 會有 N 個 rx 信號。
所以 chirps_number * rx_number = frame rx number
最後... adc.py 跟 realtime.py 要對的起來的地方...
adc.py 的 read( ) 一個 frame,要剛好跟 realtime.py 的 orgnize( ) 的一個 frame 的 size 一樣。
read( ) 一個 frame (扣除 IO 跟 bytes):
chirps * tx * rx * samplesrealtime.py 的 orgnize:
numChirpsPerFrame(numLoopsPerFrame * numTxAntennas) * numRxAntennas * numADCSamples這樣看來...numLoopsPerFrame 好像就是 adc.y 的 ADC_PARAMS['chirps']
2020/6/9
openradar : show range and doppler
在 demo/visualizer/realtime.py 有 fft processing 的 code..
... # (1) Reading in adc data adc_data = dca.read() frame = dca.organize(adc_data, num_chirps=numChirpsPerFrame, num_rx=numRxAntennas, num_samples=numADCSamples) # (2) Range Processing from mmwave.dsp.utils import Window radar_cube = dsp.range_processing(frame, window_type_1d=Window.BLACKMAN) assert radar_cube.shape == ( numChirpsPerFrame, numRxAntennas, numADCSamples), "[ERROR] Radar cube is not the correct shape!" # (3) Doppler Processing det_matrix, aoa_input = dsp.doppler_processing(radar_cube, num_tx_antennas=3, clutter_removal_enabled=True) # --- Show output if plotRangeDopp: det_matrix_vis = np.fft.fftshift(det_matrix, axes=1) plt.imshow(det_matrix_vis / det_matrix_vis.max()) plt.pause(0.05) plt.clf() ...
2020/6/8
cv2.VideoCapture() in Windows
簡單的測試 code;
只是不知道那一個 index 是那一個 camera..
這樣的 code,在 run 完後會出現一個 Warning:
google 說,在VideoCapture 加上 option:
另外,在 windows 系統上,取得 VideoCapture 後,前幾個 read( ) 到的 frame 都是 黑或是灰(16) 的內容…
好像跟 camera 有關,使用nb 內建的 camera,比較不會出現這個問題。
使用外接的 usb camera,不同的camera,第一個影像出現的時間會不一樣。
跟 cpu 的速度也有關係。
* 2022/02/23 update
Linux 系統也一樣,其實是 camera (capture) 有關。
有些 hdmi usb capture 裝置,程式開啟裝置後,都要等 0.5 sec,有些不用。
所以 safe 的作法 (要take snapshot 的話)。 delay 1s:
import cv2 cap = cv2.VideoCapture(0) ret, frame = cap.read() print(ret) print(frame) cv2.release()其中 cv2.VideoCapture(0) 的 0, 就是機器上的 camera index,有幾個 camera,就用 0, 1, 2 來選。
只是不知道那一個 index 是那一個 camera..
這樣的 code,在 run 完後會出現一個 Warning:
[WARN:0] terminating async callback這個只有在 windows 上才會有。
google 說,在VideoCapture 加上 option:
cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)說明使用 directshow 裝置。舊可以消除。
另外,在 windows 系統上,取得 VideoCapture 後,前幾個 read( ) 到的 frame 都是 黑或是灰(16) 的內容…
好像跟 camera 有關,使用nb 內建的 camera,比較不會出現這個問題。
使用外接的 usb camera,不同的camera,第一個影像出現的時間會不一樣。
跟 cpu 的速度也有關係。
* 2022/02/23 update
Linux 系統也一樣,其實是 camera (capture) 有關。
有些 hdmi usb capture 裝置,程式開啟裝置後,都要等 0.5 sec,有些不用。
所以 safe 的作法 (要take snapshot 的話)。 delay 1s:
import cv2 import time cap = cv2.VideoCapture(2) time.sleep(1) ret, frame = cap.read() cv2.imshow('ff',frame) cv2.imsave("abc.jpg",frame) ...
cv2.imshow fail on ubuntu 18.04 anaconda
好麻煩呀,ubuntu18.04 conda python 3.8 的話,opencv 的 imshow 會 fail:
但是新的 mantainer 有做,所以換安裝新版 opencv 舊可以。
是社群貢獻的 conda package repo(?).
Traceback (most recent call last): File "testvideocap.py", line 5, in好像是conda repo 的這個(3.4.2) 沒有人 mantain 了。cv2.imshow('dd',frame) cv2.error: OpenCV(3.4.2) /tmp/build/80754af9/opencv-suite_1535558553474/work/modules/highgui/src/window.cpp:632: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage'
但是新的 mantainer 有做,所以換安裝新版 opencv 舊可以。
conda remove opencv conda install -c conda-forge opencv=4.1.0-c 是 channel 的意思,用 conda-forge 這個 channel 的 opencv4.1.0 package 來安裝。
是社群貢獻的 conda package repo(?).
2020/6/1
chirp config file and adc.py parameters . set I
sensorStop flushCfg dfeDataOutputMode 1 channelCfg 15 3 0 adcCfg 2 1 adcbufCfg -1 0 0 1 0 profileCfg 0 77 429 7 57.14 0 0 70 1 256 5209 0 0 30 chirpCfg 0 0 0 0 0 0 0 1 chirpCfg 1 1 0 0 0 0 0 2 frameCfg 0 0 16 0 100 1 0 lowPower 0 1 guiMonitor -1 1 1 0 0 0 1 cfarCfg -1 0 0 8 4 4 0 5120 cfarCfg -1 1 0 4 2 3 0 5120 peakGrouping -1 1 1 1 1 255 multiObjBeamForming -1 1 0.5 clutterRemoval -1 0 calibDcRangeSig -1 0 -5 8 256 extendedMaxVelocity -1 0 bpmCfg -1 0 0 1 lvdsStreamCfg -1 0 1 0 nearFieldCfg -1 0 0 0 compRangeBiasAndRxChanPhase 0.0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 measureRangeBiasAndRxChanPhase 0 1.5 0.2 CQRxSatMonitor 0 3 5 123 0 CQSigImgMonitor 0 127 4 analogMonitor 1 1 sensorStart
這樣對應的 ADC 參數是
ADC_PARAMS = {'chirps' : 16, 'rx' : 4, 'tx' : 1, 'samples': 256, 'IQ' : 2 'bytes' : 2}
訂閱:
文章 (Atom)