2023,江端さんの技術メモ

ラズパイ4 + USBカメラ Webカメラ C270n HD 720P で、SRTストリームに変換してライブ映像を転送する方法(色々やってきたんだけど、この組み合わせだけがスポッと抜けていて、探すのに苦労した)

送信側
cam@cam-desktop:~$ gst-launch-1.0 v4l2src ! video/x-raw,format=YUY2,width=640,height=480,framerate=30/1 ! videoconvert ! x264enc tune=zerolatency ! mpegtsmux ! srtserversink uri=srt://:8888

受信側
cam@cam-desktop:~$ ffplay -i srt://localhost:8888

2023,江端さんの技術メモ

f:/しゅらばしゅう/有吉先生データ/Moove/2023-07/fit_track3.go
BusRouteの点で繋がれた線とみなして、trackingDataの各点から、その線からの最短距離を算出するようなプログラムの改造をお願いできますか?
はい、バス路線の各点を線とみなして、トラッキングデータの各点からその線までの最短距離を計算するプログラムの改造を行います。planar.DistanceFrom 関数を使用して、各トラッキングポイントからバス路線を形成する線への最短距離を計算できます。

 

package main

import (
	"fmt"

	"github.com/paulmach/orb"
	"github.com/paulmach/orb/planar"
)

// Point はデータ番号と緯度、経度を保持する構造体です
type Point struct {
	Number   int
	Lat, Lon float64
}

// トラッキングデータとバス路線データの変換
func convertToOrbPoint(p Point) orb.Point {
	return orb.Point{p.Lon, p.Lat}
}

func main() {
	// トラッキングデータ
	trackingData := []Point{
		{1, 139.6268272, 35.3715607},
		{2, 139.627135, 35.3719136},
		{3, 139.6274291, 35.3721591},
		{11, 139.6276967, 35.3724112},
		{101, 139.6276253, 35.372575},
		{59, 139.6274377, 35.3727348},
		{7, 139.6272077, 35.3728485},
		{99, 139.6263279, 35.3728985},
		{111, 139.6262229, 35.3728182},
		{131, 139.6260982, 35.3726421},
		{200, 139.6260349, 35.3724965},
		{32, 139.6257477, 35.3720127},
		{42, 139.6254685, 35.3705626},
		{44, 139.6254273, 35.3703156},
		{46, 139.62361383758, 35.36644117332},
	}

	// バス路線データ
	busRoute := []Point{
		{0, 139.6272077, 35.3728485},
		{0, 139.6263279, 35.3728985},
		{0, 139.6262229, 35.3728182},
		{0, 139.6260982, 35.3726421},
		{0, 139.6260349, 35.3724965},
		{0, 139.6257477, 35.3720127},
		{0, 139.6254685, 35.3705626},
		{0, 139.6254273, 35.3703156},
		{0, 139.62361383758, 35.36644117332},
		{0, 139.62386146588, 35.3665604971},
		{0, 139.62412597981, 35.36668746811},
		{0, 139.6245189, 35.3668106},
		{0, 139.6250347, 35.367043},
		{0, 139.62548981146, 35.36726113676},
	}

	// orbライブラリを使用して、トラッキングデータとバス路線データをorb.Pointのスライスに変換
	var trackingPoints []orb.Point
	var busRoutePoints []orb.Point
	for _, p := range trackingData {
		trackingPoints = append(trackingPoints, convertToOrbPoint(p))
	}
	for _, p := range busRoute {
		busRoutePoints = append(busRoutePoints, convertToOrbPoint(p))
	}

	// トラッキングポイントからバス路線上の最も近い点までの距離を計算し、データ番号とともに出力
	for _, trackPoint := range trackingData {
		distance := planar.DistanceFrom(orb.LineString(busRoutePoints), convertToOrbPoint(trackPoint))
		fmt.Printf("Tracking Point %d: Lat: %v, Lng: %v, Distance: %v meters\n", trackPoint.Number, trackPoint.Lat, trackPoint.Lon, distance)
	}
}

出力結果

Tracking Point 1: Lat: 139.6268272, Lng: 35.3715607, Distance: 0.001145488357906135 meters
Tracking Point 2: Lat: 139.627135, Lng: 35.3719136, Distance: 0.0009375188544507943 meters
Tracking Point 3: Lat: 139.6274291, Lng: 35.3721591, Distance: 0.0007240789459736531 meters
Tracking Point 11: Lat: 139.6276967, Lng: 35.3724112, Distance: 0.0006560124160327593 meters
Tracking Point 101: Lat: 139.6276253, Lng: 35.372575, Distance: 0.0004991913560911751 meters
Tracking Point 59: Lat: 139.6274377, Lng: 35.3727348, Distance: 0.000256569074508911 meters
Tracking Point 7: Lat: 139.6272077, Lng: 35.3728485, Distance: 0 meters
Tracking Point 99: Lat: 139.6263279, Lng: 35.3728985, Distance: 0 meters
Tracking Point 111: Lat: 139.6262229, Lng: 35.3728182, Distance: 0 meters
Tracking Point 131: Lat: 139.6260982, Lng: 35.3726421, Distance: 0 meters
Tracking Point 200: Lat: 139.6260349, Lng: 35.3724965, Distance: 0 meters
Tracking Point 32: Lat: 139.6257477, Lng: 35.3720127, Distance: 0 meters
Tracking Point 42: Lat: 139.6254685, Lng: 35.3705626, Distance: 0 meters
Tracking Point 44: Lat: 139.6254273, Lng: 35.3703156, Distance: 0 meters
Tracking Point 46: Lat: 139.62361383758, Lng: 35.36644117332, Distance: 0 meters

2023,江端さんの技術メモ

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; start_atの時間順に表示するSQLを教えて下さい。
SELECT * FROM records ORDER BY start_at ASC;

降順(新しいものから古いものへ)に並べ替えたい場合は、ASCDESC に変更します:
SELECT * FROM records ORDER BY start_at DESC;

select user_id, start_at, end_at from records order by start_at ASC where user_id = 7; のSQLは何が間違っていますか?
SELECT user_id, start_at, end_at FROM records WHERE user_id = 7 ORDER BY start_at ASC;

moove=# select place from records where id = 2; place ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [{"lat": 34.7325, "lng": 135.4986}, {"lat": 34.7326, "lng": 135.4989}, {"lat": 34.7326, "lng": 135.4989}, {"lat": 34.7327, "lng": 135.4995}, {"lat": 34.7327, "lng": 135.5}, {"lat": 34.7328, "lng": 135.5002}, {"lat": 34.733, "lng": 135.5006}, {"lat": 34.7331, "lng": 135.501}, {"lat": 34.7334, "lng": 135.5015}, {"lat": 34.7336, "lng": 135.5018}, {"lat": 34.7336, "lng": 135.5018}, {"lat": 34.7336, "lng": 135.5019}, {"lat": 34.7337, "lng": 135.5021}, {"lat": 34.734, "lng": 135.5024}, {"lat": 34.7343, "lng": 135.5026}, {"lat": 34.7346, "lng": 135.5024}, {"lat": 34.7347, "lng": 135.5024}, {"lat": 34.7346, "lng": 135.5024}, {"lat": 34.7345, "lng": 135.5025}, {"lat": 34.7343, "lng": 135.5027}, {"lat": 34.7343, "lng": 135.5029}, {"lat": 34.7342, "lng": 135.5031}, {"lat": 34.7344, "lng": 135.5035}, {"lat": 34.7344, "lng": 135.5035}, {"lat": 34.7344, "lng": 135.5035}] (1 row) で登場する、最初の{"lat": 34.7325, "lng": 135.4986}と、最後の {"lat": 34.7344, "lng": 135.5035}だけを取り出すSQL文を書いて下さい
WITH places AS (
SELECT jsonb_array_elements(place) AS place_elements
FROM records
WHERE id = 2
)
SELECT
(SELECT place_elements FROM places LIMIT 1) AS first_place,
(SELECT place_elements FROM places ORDER BY jsonb_array_length(place) DESC LIMIT 1) AS last_place
FROM records
WHERE id = 2;

select user_id from records; で出てくる異なるuser_id(整数)をピックアップするSQL文を教えて下さい
SELECT DISTINCT user_id FROM records;

ありがとうございます。では、これを降順に並べる方法も教えてください
SELECT DISTINCT user_id FROM records ORDER BY user_id DESC;
昇順ならどうなりますか
SELECT DISTINCT user_id FROM records ORDER BY user_id ASC;

 

2023,江端さんの技術メモ

指定された二つの位置情報間のデータを30秒ごとに補完するには、まず、始点と終点の位置情報と時刻を取得し、それらの間の差を求めます。次に、時間と位置の差を等間隔に分割して、各時点での位置を計算します。

以下のGoプログラムは、始点と終点の情報を基に30秒ごとの位置情報を補完する例です:

package main

import (
	"fmt"
	"time"
)

// Location は緯度と経度を保持する構造体です
type Location struct {
	Lat, Lng float64
}

func main() {
	// 初期位置情報
	startLocation := Location{Lat: 34.665300, Lng: 135.224100}
	endLocation := Location{Lat: 34.664900, Lng: 135.223900}

	// 時刻の設定
	startTime, _ := time.Parse("2006-01-02 15:04:05", "2023-03-03 07:39:30")
	endTime, _ := time.Parse("2006-01-02 15:04:05", "2023-03-03 07:43:30")

	// 各差を計算
	duration := endTime.Sub(startTime)
	latDiff := endLocation.Lat - startLocation.Lat
	lngDiff := endLocation.Lng - startLocation.Lng

	// 30秒ごとのデータを生成
	interval := 30 * time.Second
	for t := startTime; t.Before(endTime); t = t.Add(interval) {
		fraction := t.Sub(startTime).Seconds() / duration.Seconds()
		lat := startLocation.Lat + fraction*latDiff
		lng := startLocation.Lng + fraction*lngDiff

		fmt.Printf("Lat: %f, Lng: %f %v\n", lat, lng, t.Format("2006-01-02 15:04:05"))
	}
}

このプログラムは、指定された時間間隔(この場合は30秒)で始点と終点の間の緯度と経度を計算し、その結果を出力します。始点と終点の間の時間差と距離差に基づき、等間隔に位置情報を補完しています。

2023,江端さんの技術メモ

Go言語で、指定された日時(文字列形式)に30秒ずつ加算して表示するプログラムを作成するには、まず日時を扱うための time パッケージを利用します。以下は、その要件を満たす簡単な例です。

package main

import (
    "fmt"
    "time"
)

func main() {
    // 初期の日時設定
    startAt := "2023-03-01 03:38:00"
    layout := "2006-01-02 15:04:05" // Goの時間フォーマット

    // 文字列を time.Time 型に変換
    t, err := time.Parse(layout, startAt)
    if err != nil {
        panic(err)
    }

    // 30秒ずつ加算して表示
    for i := 0; i < 10; i++ { // 例として10回繰り返す
        t = t.Add(30 * time.Second)
        fmt.Println(t.Format(layout))
    }
}

このプログラムでは、time.Parse 関数を使用して日時の文字列を time.Time 型に変換し、その後 time.Add メソッドを使って30秒ずつ加算しています。最後に、time.Format メソッドを使用して日時を指定された形式で表示しています。ここでは10回の繰り返しを行っていますが、必要に応じて繰り返し回数を変更できます。

2023,江端さんの技術メモ

select place from records where id = 2 とした場合、最初の{"lat": 34.7325, "lng": 135.4986}と、最後の {"lat": 34.7344, "lng": 135.5035}だけを取り出すSQL文を書いて下さい。ただしplaceはjsonb形式です。

これを、

User
You
SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type FROM records WHERE user_id = 43 ORDER BY start_at ASC; で選ばれた上記のSQLを、first_place, last_placeとして追記できるようにするには、どのように記述すれば良いですか

とお願いしたのですが、上手く動かないようなので、Go言語で書いて貰いました。

/*

f:/しゅらばしゅう/有吉先生データ/Moove/2023-07/test1124.go

SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type FROM records WHERE user_id = 43 ORDER BY start_at ASC; で選ばれた上記のSQLを、first_place, last_placeとして追記できるようにするには、どのように記述すれば良いですか。

で、作ってもらったプログラム


*/

package main

import (
    "database/sql"
    "encoding/json"
    "fmt"
    "log"

    _ "github.com/lib/pq"
)

type Record struct {
    ID             int
    UserID         int
    StartAt        string
    EndAt          string
    Duration       string
    Distance       float64
    PredictionType int
    FirstPlace     Location
    LastPlace      Location
}

type Location struct {
    Lat float64 `json:"lat"`
    Lng float64 `json:"lng"`
}

func main() {
	// PostgreSQL データベースへの接続情報
	const (
		host     = "192.168.0.23"
		port     = 15432
		user     = "postgres"
		password = "password"
		dbname   = "moove"
	)

	// PostgreSQL データベースへの接続
	connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
	db, err := sql.Open("postgres", connStr)
	if err != nil {
		panic(err)
	}
	defer db.Close()


    rows, err := db.Query("SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type, place FROM records WHERE user_id = 43 ORDER BY start_at ASC")
    if err != nil {
        log.Fatal(err)
    }
    defer rows.Close()

    for rows.Next() {
        var r Record
        var placeJSON string

        err := rows.Scan(&r.ID, &r.UserID, &r.StartAt, &r.EndAt, &r.Duration, &r.Distance, &r.PredictionType, &placeJSON)
        if err != nil {
            log.Fatal(err)
        }

        var places []Location
        err = json.Unmarshal([]byte(placeJSON), &places)
        if err != nil {
            log.Fatal(err)
        }

        if len(places) > 0 {
            r.FirstPlace = places[0]
            r.LastPlace = places[len(places)-1]
        }

        fmt.Printf("%+v\n", r)
    }
}

出力結果

f:\しゅらばしゅう\有吉先生データ\Moove\2023-07>go run test1124.go
go run test1124.go
{ID:20132 UserID:43 StartAt:2023-04-08T05:35:00Z EndAt:2023-04-08T06:20:00Z Duration:00:45:00 Distance:348821.9097841587 PredictionType:4 FirstPlace:{Lat:35.3714 Lng:139.6255} LastPlace:{Lat:35.4409 Lng:139.6591}}
{ID:20133 UserID:43 StartAt:2023-04-08T06:20:30Z EndAt:2023-04-08T06:30:00Z Duration:00:09:30 Distance:153.88780282790526 PredictionType:2 FirstPlace:{Lat:35.4408 Lng:139.659} LastPlace:{Lat:35.4402 Lng:139.6596}}
{ID:20134 UserID:43 StartAt:2023-04-08T06:30:30Z EndAt:2023-04-08T06:49:30Z Duration:00:19:00 Distance:180.2412488153271 PredictionType:1 FirstPlace:{Lat:35.4402 Lng:139.6596} LastPlace:{Lat:35.4401 Lng:139.6599}}
{ID:20135 UserID:43 StartAt:2023-04-08T06:50:00Z EndAt:2023-04-08T06:53:30Z Duration:00:03:30 Distance:65.08472909159703 PredictionType:2 FirstPlace:{Lat:35.4401 Lng:139.6598} LastPlace:{Lat:35.44 Lng:139.6599}}
(以下省略)

 

2023,江端さんの技術メモ

moove=# select place from records where id = 2; place ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [{"lat": 34.7325, "lng": 135.4986}, {"lat": 34.7326, "lng": 135.4989}, {"lat": 34.7326, "lng": 135.4989}, {"lat": 34.7327, "lng": 135.4995}, {"lat": 34.7327, "lng": 135.5}, {"lat": 34.7328, "lng": 135.5002}, {"lat": 34.733, "lng": 135.5006}, {"lat": 34.7331, "lng": 135.501}, {"lat": 34.7334, "lng": 135.5015}, {"lat": 34.7336, "lng": 135.5018}, {"lat": 34.7336, "lng": 135.5018}, {"lat": 34.7336, "lng": 135.5019}, {"lat": 34.7337, "lng": 135.5021}, {"lat": 34.734, "lng": 135.5024}, {"lat": 34.7343, "lng": 135.5026}, {"lat": 34.7346, "lng": 135.5024}, {"lat": 34.7347, "lng": 135.5024}, {"lat": 34.7346, "lng": 135.5024}, {"lat": 34.7345, "lng": 135.5025}, {"lat": 34.7343, "lng": 135.5027}, {"lat": 34.7343, "lng": 135.5029}, {"lat": 34.7342, "lng": 135.5031}, {"lat": 34.7344, "lng": 135.5035}, {"lat": 34.7344, "lng": 135.5035}, {"lat": 34.7344, "lng": 135.5035}] (1 row) で登場する、最初の{"lat": 34.7325, "lng": 135.4986}と、最後の {"lat": 34.7344, "lng": 135.5035}だけを取り出すSQL文を書いて下さい

ただし、placeは、以下の通り、jsonb形式です。

moove=# \d records;
Table "public.records"
Column | Type | Collation | Nullable | Default
-----------------+-----------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('records_id_seq'::regclass)
user_id | integer | | |
distance | double precision | | |
place | jsonb | | |
speed | jsonb | | |
prediction_type | integer | | |
start_at | timestamp without time zone | | |
end_at | timestamp without time zone | | |
Indexes:
"records_pkey" PRIMARY KEY, btree (id)
moove=# \d records;
Table "public.records"
Column | Type | Collation | Nullable | Default
-----------------+-----------------------------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('records_id_seq'::regclass)
user_id | integer | | |
distance | double precision | | |
place | jsonb | | |
speed | jsonb | | |
prediction_type | integer | | |
start_at | timestamp without time zone | | |
end_at | timestamp without time zone | | |
Indexes:
"records_pkey" PRIMARY KEY, btree (id)


WITH places AS (
SELECT jsonb_array_elements(place) AS place_elements
FROM records
WHERE id = 2
)
SELECT
(SELECT place_elements FROM places LIMIT 1) AS first_place,
(SELECT place_elements FROM places ORDER BY jsonb_array_length(place) DESC LIMIT 1) AS last_place
FROM records
WHERE id = 2;

出力結果
first_place | last_place
-----------------------------------+-----------------------------------
{"lat": 34.7325, "lng": 135.4986} | {"lat": 34.7325, "lng": 135.4986}
(1 row)

2023,江端さんの技術メモ

moove=# SELECT id, user_id, start_at, end_at, end_at - start_at, distance, prediction_type FROM records WHERE user_id = 7 ORDER BY start_at ASC;

id | user_id | start_at | end_at | ?column? | distance | prediction_type
-------+---------+---------------------+---------------------+----------+--------------------+-----------------
20132 | 43 | 2023-04-08 05:35:00 | 2023-04-08 06:20:00 | 00:45:00 | 348821.9097841587 | 4
20133 | 43 | 2023-04-08 06:20:30 | 2023-04-08 06:30:00 | 00:09:30 | 153.88780282790526 | 2
20134 | 43 | 2023-04-08 06:30:30 | 2023-04-08 06:49:30 | 00:19:00 | 180.2412488153271 | 1
20135 | 43 | 2023-04-08 06:50:00 | 2023-04-08 06:53:30 | 00:03:30 | 65.08472909159703 | 2
20136 | 43 | 2023-04-08 06:54:00 | 2023-04-08 08:06:00 | 01:12:00 | 522.2898726850697 | 1
20137 | 43 | 2023-04-08 08:06:30 | 2023-04-08 08:15:00 | 00:08:30 | 144.15400138235145 | 2
20138 | 43 | 2023-04-08 08:15:30 | 2023-04-08 08:23:00 | 00:07:30 | 359.73505399604153 | 1
20139 | 43 | 2023-04-08 08:23:30 | 2023-04-08 08:54:30 | 00:31:00 | 13516.406121323496 | 4
20140 | 43 | 2023-04-08 08:55:00 | 2023-04-08 09:00:30 | 00:05:30 | 30.045448973873317 | 1
20141 | 43 | 2023-04-08 09:01:00 | 2023-04-08 09:05:00 | 00:04:00 | 39.96401615517626 | 2

2023,江端さんの技術メモ

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にするには、どのようなSQL文になりますか

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にして、時間順に表示するSQLを教えて下さい。

moove=# SELECT user_id, start_at, end_at FROM records WHERE user_id = 7 ORDER BY start_at ASC;
user_id | start_at | end_at
---------+---------------------+---------------------
7 | 2023-03-01 03:38:00 | 2023-03-01 03:58:30
7 | 2023-03-01 03:59:00 | 2023-03-01 04:03:00
7 | 2023-03-01 04:03:30 | 2023-03-01 04:09:30
7 | 2023-03-01 04:10:00 | 2023-03-01 04:15:30
7 | 2023-03-01 04:16:00 | 2023-03-01 05:22:30

中略
7 | 2023-05-17 10:48:00 | 2023-05-17 10:54:30
7 | 2023-05-17 10:55:00 | 2023-05-17 11:09:00
7 | 2023-05-17 11:09:30 | 2023-05-17 11:38:30
7 | 2023-05-17 11:39:00 | 2023-05-17 11:53:00
7 | 2023-05-17 11:53:30 | 2023-05-17 11:54:30
7 | 2023-05-17 11:55:00 | 2023-05-17 12:04:00
7 | 2023-05-17 12:04:30 | 2023-05-17 12:30:00
(1514 rows)

2023,江端さんの技術メモ

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にするには、どのようなSQL文になりますか

SELECT * FROM records WHERE start_at = '2023-03-20 05:03:00'; を"2023-03-20"が含まれているものだけを条件にして、時間順に表示するSQLを教えて下さい。

moove=# SELECT user_id, start_at,end_at FROM records WHERE user_id = 7 and DATE(start_at) = '2023-03-21' order by start_at;
user_id | start_at | end_at
---------+---------------------+---------------------
7 | 2023-03-21 00:03:00 | 2023-03-21 00:07:30
7 | 2023-03-21 00:08:00 | 2023-03-21 00:11:00
7 | 2023-03-21 00:11:30 | 2023-03-21 00:18:00
7 | 2023-03-21 00:18:30 | 2023-03-21 00:27:30
(中略)
7 | 2023-03-21 23:22:00 | 2023-03-21 23:30:30
7 | 2023-03-21 23:31:00 | 2023-03-21 23:53:30
7 | 2023-03-21 23:54:00 | 2023-03-22 00:00:30
(35 rows)