2023/8/9

add one rotation axis

mmwave 的 python tool 有 azimuth, elevation tilt,缺一個 (不知道名子)。
所以加上去。

code:
elevAziRotMatrix = np.matrix([  [  math.cos(aziTilt),  math.cos(elevTilt)*math.sin(aziTilt), math.sin(elevTilt)*math.sin(aziTilt)],
                                [ -math.sin(aziTilt),  math.cos(elevTilt)*math.cos(aziTilt), math.sin(elevTilt)*math.cos(aziTilt)],
                                [                  0,                   -math.sin(elevTilt),                   math.cos(elevTilt)],
                             ])
對照 [https://en.wikipedia.org/wiki/Rotation_matrix wiki]:


用 0 度來猜對應關係..
所以看起來缺的應該是 β

另外 eleTilt, aziTilt 的方向和座標定義方向相反 α β γ
  • β : rotation
  • α : elevation
  • γ : azimuth
所以code :
 cos(γ),  cos(α)sin(γ), sin(α)sin(γ)
 sin(γ),  cos(α)cos(γ), sin(α)cos(γ)
      0, -sin(α)      , cos(α)
和 公式比較, α γ 的角度方向大概是相反,所以 sin 都要 * -1。

加入 rotTilt : β

原來 sin(0) = 0 的部份,要加回去 sin(β),也就是 sin(rotTilt)

2023/8/7

筆記:3D people counting, point cloud detection algorithm

根據 [https://dev.ti.com/tirex/explore/node?a=1AslXXD__1.10.00.13&node=A__AIQPG9x7K34A8l4ZELgznA__radar_toolbox__1AslXXD__1.10.00.13&r=1AslXXD__1.20.00.11 3D people tracking detection layer tuning guide],
這個3D point cloud 的 processing 的順序是:
  • 每個chirp 都做 range FFT
  • 同一TX反射的,每個水平ANT 的 range FFT,做 capon beamformer,找出方位角
  • 這樣就類似 R-V map 一樣,變成2D 的 heat map 圖,不過現在是 Range-Azimuth map,因為原來的 doppler FFT 改成 capon beamformer
  • 在 2D heat map (R-A map) 上,用 2D CFar (2-pass CFar)找出 signal point (detection point)
  • 找出 detection point (2D heat map 的 bin),再用垂直向的 ANT 做 capon beamformer 找出垂直角(elevation)
  • 針對detection point,同一 ant,連續chirp 的 bin,做 doppler FFT,算出速度

範例有兩種 ANT 排列,一個是安裝在天花板,一個安裝在牆上。
天花板的ANT 排列,X-Z 向是對稱的。
牆壁的ANT排例,X向的天線數量比較多。

所以兩個的 processing algorithm 不一樣。

牆壁的ANT,X 向比較多,所以先做 azimuth capon beamformer,再把結果的 bin 做 elevation beam former,
天花板 X-Z 向一樣多,所以都做....

2023/8/4

go-lang small http file server with upload function

ChatGPT 寫的,還沒看能不能動...
package main

import (
	"html/template"
	"io"
	"net/http"
	"os"
	"path/filepath"
)

func main() {
	http.HandleFunc("/", handleFileServer)
	http.HandleFunc("/upload", handleUpload)

	// Start the server on port 8080
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		panic(err)
	}
}

func handleFileServer(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	dirPath := "." // Current directory
	filePath := filepath.Join(dirPath, r.URL.Path)
	file, err := os.Open(filePath)
	if err != nil {
		http.Error(w, "File not found", http.StatusNotFound)
		return
	}
	defer file.Close()

	// Check if the path is a directory
	fileInfo, err := file.Stat()
	if err != nil {
		http.Error(w, "Failed to get file info", http.StatusInternalServerError)
		return
	}
	if fileInfo.IsDir() {
		renderDirectory(w, filePath)
		return
	}

	// Serve the file if it's not a directory
	http.ServeFile(w, r, filePath)
}

func renderDirectory(w http.ResponseWriter, dirPath string) {
	tmpl, err := template.New("directory").Parse(directoryTemplate)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	// Read the directory content
	dir, err := os.ReadDir(dirPath)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		return
	}

	data := struct {
		DirectoryName string
		Files         []string
	}{
		DirectoryName: dirPath,
		Files:         make([]string, 0),
	}

	for _, entry := range dir {
		data.Files = append(data.Files, entry.Name())
	}

	// Render the template
	err = tmpl.Execute(w, data)
	if err != nil {
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
	}
}

func handleUpload(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// Limit the maximum file size to 10 MB
	r.ParseMultipartForm(10 << 20)

	// Get the uploaded file
	file, handler, err := r.FormFile("file")
	if err != nil {
		http.Error(w, "Failed to get file from request", http.StatusBadRequest)
		return
	}
	defer file.Close()

	// Create the file in the current directory
	f, err := os.Create(handler.Filename)
	if err != nil {
		http.Error(w, "Failed to create file on server", http.StatusInternalServerError)
		return
	}
	defer f.Close()

	// Copy the uploaded file to the server
	_, err = io.Copy(f, file)
	if err != nil {
		http.Error(w, "Failed to save file on server", http.StatusInternalServerError)
		return
	}

	// Redirect back to the directory listing
	http.Redirect(w, r, "/", http.StatusFound)
}

const directoryTemplate = `
<!DOCTYPE html>
<html>
<head>
	<title>Directory Listing: {{ .DirectoryName }}</title>
</head>
<body>
	<h1>Directory Listing: {{ .DirectoryName }}</h1>
	<ul>
		{{ range .Files }}
		<li><a href="{{ . }}">{{ . }}</a></li>
		{{ end }}
	</ul>
	<form action="/upload" method="post" enctype="multipart/form-data">
		<input type="file" name="file">
		<input type="submit" value="Upload">
	</form>
</body>
</html>
`