以下、上記記事のコピペ
GitHub 上でサクッと空のディレクトリを作成する方法
golangによるudpの送信"だけ"するプログラムと受信だけするプログラム
// udp_sendto.go
// go run udp_sendto.go
// golangによるudpの送信"だけ"するプログラム
package main
import (
"fmt"
"math/rand"
"net"
"time"
)
func random(min, max float64) float64 {
return rand.Float64()*(max-min) + min
}
type unmTbl struct {
uniNum int
objType string // "Bus" or "User"
simNum int
pmNum int
lon float64
lat float64
}
func main() {
conn, err := net.Dial("udp4", "localhost:12345")
if err != nil {
panic(err)
}
defer conn.Close()
// 初期化
var ut [5]unmTbl
for i, _ := range ut {
ut[i].objType = "User"
ut[i].uniNum = i
ut[i].lat = 35.653976
ut[i].lon = 139.796821
}
for {
fmt.Println("Sending to server")
for i, _ := range ut {
ut[i].lat += random(0.5, -0.5) * 0.00001 * 10 * 5
ut[i].lon += random(0.5, -0.5) * 0.00002 * 10 * 5
str := ut[i].objType + "," + fmt.Sprint(ut[i].uniNum) + "," + fmt.Sprint(ut[i].lon) + "," + fmt.Sprint(ut[i].lat) + ","
fmt.Println(str)
_, err = conn.Write([]byte(str))
if err != nil {
panic(err)
}
time.Sleep(3 * time.Second) // 1秒休む
}
}
}
// udp_recvfrom.go
// go run udp_recvfrom.go
// golangによるudpの受信"だけ"するプログラム
package main
import (
"fmt"
"net"
)
func main() {
addr, _ := net.ResolveUDPAddr("udp", ":12345")
sock, _ := net.ListenUDP("udp", addr)
i := 0
for {
i++
buf := make([]byte, 1024)
rlen, _, err := sock.ReadFromUDP(buf)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(buf[0:rlen]))
//fmt.Println(i)
//go handlePacket(buf, rlen)
}
}
Golangの構造体やら動的リストやら
package main
import (
"fmt"
)
// 構造体の作り方
type unm_tbl struct {
obj_type string // "Bus" or "User"
sim_num int
pm_num int
}
func main() {
list := make([]unm_tbl, 0) // 構造体の動的リスト宣言
ut := unm_tbl{} // 構造体変数の初期化
ut.obj_type = "User"
ut.sim_num = 1
ut.pm_num = 0
list = append(list, ut) // 構造体をリストに動的追加
ut = unm_tbl{} // 構造体変数の初期化
ut.obj_type = "Bus"
ut.sim_num = 2
ut.pm_num = 1
list = append(list, ut) // 構造体をリストに動的追加
ut = unm_tbl{} // 構造体変数の初期化
ut.obj_type = "Taxi"
ut.sim_num = 3
//ut.pm_num = 3
list = append(list, ut) // 構造体をリストに動的追加
for i, _ := range list { // リスト分、ループする
fmt.Println(list[i].obj_type)
fmt.Println(list[i].sim_num)
fmt.Println(list[i].pm_num)
}
fmt.Println(list)
}
新しい言語の勉強って、たいてい、文字列処理で挫折するよね。
"You requested too many nodes (limit is 50000). Either request a smaller area, or use planet.osm" と言われた時の対応
https://www.openstreetmap.org/export#map=13/35.6367/139.8312 から、"You requested too many nodes (limit is 50000). Either request a smaller area, or use planet.osm"(ノード数が多すぎます(制限は50000)。もっと小さい領域を要求するか、 planet.osm を使用してください。) と言われた時の対応方法は以下の通りです。
(Step.1) 「ドラッグして別の領域を選択」を選択

(Step.2) 領域をマウスで拡大・変形した後、「Overpass API」を選択

(Step.3) 名前を付けて保存で、適当なファイル名(例 toyosu.osm)でセーブする

以上
Error response from daemon: open \\.\pipe\docker_engine_linux: The system cannot find the file specified. 等が出てきて、ドキっとする件
最近、PC起動時に、
C:\Users\ebata>docker ps
Error response from daemon: open \\.\pipe\docker_engine_linux: The system cannot find the file specified.
などが出てきて、ドキっとさせられる症状が頻発している。
基本的には、Dockerアイコンを使って再起動(Restart docker...)で、改善するんだけど、心臓に悪い。
近い内に、何か起こりそうな気がします。
(まとめ)地図DBの作り方
0. メモ
CREATE DATABASE ca_sim0; の逆で、DBの消去方法は DROP DATABASE ca_sim0;
- メイン
すでに地図DBは作ってきたが、今のうちに纏めておきます。ここでは東京の豊洲地区を例にして説明します。
なお、Dockerの利用を前提とし、それぞれの地区のDBはバラバラに管理するものとします。地区ごとに取り扱えるようにして、DBを切り替えて利用することを前提とする為です。
(Step1) (to-path)/toyosu というディレクトリを掘る
(Step2) そのディレクトリに、以下のdocker-compose.ymlを作ります。
version: '3.7'
services:
db:
image: postgis-pgrouting:latest
environment:
POSTGRES_HOST_AUTH_METHOD: 'trust'
POSTGRES_PASSWORD: 'postgres'
expose:
- 5432
ports:
- 15432:5432
volumes:
- db_data
- ./shared:/shared
db_data:
image: busybox
volumes:
- /data/db
これに対して、
docker-compose up -d
Creating network "toyosu_default" with the default driver
Pulling db (postgis-pgrouting:latest)...
ERROR: The image for the service you're trying to recreate has been removed. If you continue, volume data could be lost. Consider backing up your data before continuing.
Continue with the new image? [yN]y
Pulling db (postgis-pgrouting:latest)...
ERROR: pull access denied for postgis-pgrouting, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
ubuntu@ip-172-26-13-137:~/toyosu$
てなものが出てきた時は、
image: postgis-pgrouting:latest
の代わりに、
image: pgrouting/pgrouting:v3.0.0-dev-postgresql_12
にしたら動いた(理由は不明だが、まあいいか)
DB(PostgreSQL)のアクセス用のポート番号は、15432としています。ローカルにPostgresがある場合にバッティングを避ける為です。
(Step3) そのディレクトリの中で、"docker-compose up -d"を実行する。
(Step4)"$ docker start -a toyosu_db_1"としてコンテナを起動する
(Step5)(winpty) "docker container exec -it toyosu_db_1 bash" でシェルに入る
(Step6) "psql -U postgres" で、DBのコンソールに入る
(Step7)psqlでデータベースを新規作成する(以下、データベース名をca_simとする)。
postgres=#CREATE DATABASE ca_sim
(Step8)次のコマンドを実行する
postgres=# \c ca_sim
postgres=# create extension postgis;
postgres=# create extension pgrouting;
(Step9) ここで、もう一つ、コンソール(2)をたちあげて、(to-path)/toyosuに入っておく
(Step10) https://www.openstreetmap.org/ から、豊洲地区を選んで地図DBをエクスポートする

ファイル名を"toyosu.osm"として、(to-path)/toyosuに保存する。
↓私が使っている、"toyosu.osm"
(Step11) コンソール2で、"toyosu.osm"を、コンテナに放り込む
>docker cp toyosu.osm toyosu_db_1:/db_data
(Step12)コンソール2で、"apt-get update"、"apt-get update" を実施した後、"apt-get install osm2pgrouting"を実施
(Step13)コンソール2で、"osm2pgrouting -f /db_data/toyosu.osm -c /usr/share/osm2pgrouting/mapconfig_for_cars.xml -d ca_sim -U postgres" を実施
これで、地図DBはできているハズだが、多分、一発で成功することはないので、いろいろ試してみて下さい。
(Step14) psqlでログインしているコンロールから、以下の操作をして表示ができれば、成功
postgres=# \c ca_sim
You are now connected to database "ca_sim" as user "postgres".
ca_sim=# \dt
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | configuration | table | postgres
public | pointsofinterest | table | postgres
public | spatial_ref_sys | table | postgres
public | ways | table | postgres
public | ways_vertices_pgr | table | postgres
(5 rows)
ca_sim=# select * from ways;
で
以下のような表示がでてくれば、(多分)成功

QGIS3で接続すると、こんな感じのものが表示されるはず


以上
Dockerの中にある、postgreSQLのpostGISのDB情報を、sqlファイルに変換する件
この環境↓を前提として、
Dockerの環境にて、ca_sim2ののダンプによるsqlファイル(map5.sql)の作成に先程成功しました。
[江端メモ]
root@6432e639f678:/db_data#
>pg_dump -U postgres ca_sim2 > map5.sql
>mv map5.sql /db_data (これ、カレントディレクトリで作業しているなら不要です)
C:\Users\ebata\toyosu>docker cp toyosu_db_1:/db_data/map5.sql map5.sql
(まあ、私の環境でなければ、分からないとは思います)
QGIS3でosmファイルを地図表示する方法
QGIS3でosmファイルを地図表示する方法
いつも、osmファイルをドラッグする場所を忘れるので、メモ

すると、こうなる。

以上
「TILE38紹介」を紹介する
1.前書き
TILE38のクライアントプログラムのサンプルを見たくて、色々探していたら、「TILE38紹介」を紹介するという、非常に良いページを見つけました。
私がプログラムを良く忘れるので、このページのプログラムをそのままコピペさせて頂いて、私の備忘録とさせて頂きます(私の環境では、コメントアウト等がちょっと違ったようです)
2. 前提
Tile38のサーバを立ち上げておきます。Dockerを使って立ち上げておくと簡単です。dockerを使わない方法は、https://github.com/tidwall/tile38 に記載があります。
docker pull tile38/tile38
docker run -p 9851:9851 tile38/tile38
3. サンプルプログラム
(1つ目)
package main
import (
//"encoding/json"
"fmt"
"log"
//"reflect"
"github.com/garyburd/redigo/redis"
)
func main() {
// db connect
c, err := redis.Dial("tcp", ":9851")
if err != nil {
log.Fatalf("Could not connect: %v\n", err)
}
defer c.Close()
// SET location
ret, err := c.Do("SET", "location", "me", "POINT", 35.6581, 139.6975)
if err != nil {
log.Fatalf("Could not SET: %v\n", err)
}
fmt.Printf("SET ret:%s\n", ret)
// GET location
ret, err = c.Do("GET", "location", "me")
if err != nil {
log.Fatalf("Could not GET: %v\n", err)
}
fmt.Printf("GET ret:%s\n", ret)
}
(2つめ)
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/garyburd/redigo/redis"
)
type GeoJsonMember struct {
Type string `json:"type"`
CoordinatesRaw json.RawMessage `json:"coordinates,omitempty"`
CoordinatesObj interface{} `json:"-"`
}
type Point [2]float64
type LineString []Point
type Polygon []LineString
func (member *GeoJsonMember) String() string {
return fmt.Sprintf("%s %v", member.Type, member.CoordinatesObj)
}
func (member *GeoJsonMember) setCoordinates() error {
var coordinates interface{}
switch member.Type {
case "Point":
coordinates = new(Point)
case "LineString":
coordinates = new(LineString)
case "Polygon":
coordinates = new(Polygon)
default:
return fmt.Errorf("Unknown type: %v", member.Type)
}
err := json.Unmarshal(member.CoordinatesRaw, &coordinates)
if err != nil {
return fmt.Errorf("json.Unmarshal error: %v", err)
}
member.CoordinatesObj = coordinates
return nil
}
func unmarshalMultiResults(shapes []byte) ([]*GeoJsonMember, error) {
var members []*GeoJsonMember
err := json.Unmarshal(shapes, &members)
if err != nil {
return nil, fmt.Errorf("Unmarshal error: %v", err)
}
for i, member := range members {
err := member.setCoordinates()
if err != nil {
return nil, fmt.Errorf("member[%v]:type:%v coordinates:%v err:%v\n", i, member.Type, member.CoordinatesRaw, err)
}
}
return members, nil
}
func unmarshalSingleResult(shapes []byte) (*GeoJsonMember, error) {
var member GeoJsonMember
err := json.Unmarshal(shapes, &member)
if err != nil {
return nil, fmt.Errorf("Unmarshal error: %v", err)
}
err = member.setCoordinates()
if err != nil {
return nil, fmt.Errorf("type:%v coordinates:%v err:%v\n", member.Type, member.CoordinatesRaw, err)
}
return &member, nil
}
func main() {
// db connect
c, err := redis.Dial("tcp", ":9851")
if err != nil {
log.Fatalf("Could not connect: %v\n", err)
}
defer c.Close()
// SET fleet
for _, data := range [][]interface{}{
{"fleet", "id1", "FIELD", "start", "123456", "FIELD", "end", "789012", "POINT", 35.6581, 139.6975},
{"fleet", "id2", "OBJECT", `{"type":"Point","coordinates":[139.6975,35.6581]}`},
{"fleet", "id3", "OBJECT", `{"type":"LineString","coordinates":[[139.6975,35.6581],[1,1],[2,2]]}`},
{"fleet", "id4", "POINT", 35.6581, 139.6975},
} {
ret, err := c.Do("SET", data...)
if err != nil {
log.Fatalf("Could not SET: %v\n", err)
}
fmt.Printf("SET ret:%#s\n", ret)
}
// SCAN fleet
results, err := redis.Values(c.Do("SCAN", "fleet"))
if err != nil {
log.Fatalf("Could not SCAN: %v\n", err)
}
var cursor int
var members []interface{}
_, err = redis.Scan(results, &cursor, &members)
if err != nil {
fmt.Printf("scan result error: %v", err)
return
}
for len(members) > 0 {
// pick up one record from results as []interface{}
var object []interface{}
members, err = redis.Scan(members, &object)
if err != nil {
fmt.Printf("scan record error: %v", err)
return
}
// scan columns from one record -> [id,json],fields
var id []byte
var json []byte
others, err := redis.Scan(object, &id, &json)
if err != nil {
fmt.Printf("scan columns error: %v", err)
return
}
// unmarshal geojson string to struct
gjm, err := unmarshalSingleResult(json)
if err != nil {
fmt.Printf("unmarshal json error: %v", err)
return
}
fmt.Printf("id:%s json:%s others:%s\n", id, gjm, others)
}
}
4. PruneMobileと組み合わせてみる
ランダムウォークさせている歩行者が、一定のエリアに入った時に、メッセージを送付する。
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
cgoの使い方メモ(不定期に更新)
- 参考文献
https://r9y9.github.io/blog/2014/03/22/cgo-tips/
https://hawksnowlog.blogspot.com/2018/12/getting-started-with-cgo.html - 取り敢えず、Goのプログラムの中からCの関数を使う方法
// go run main.go package main /* #include <stdio.h> #include <stdlib.h> void myprint(char* s) { printf("%s\n", s); } */ import "C" import "unsafe" func main() { cs := C.CString("Hello from stdio\n") C.myprint(cs) C.free(unsafe.Pointer(cs)) } // output // Hello from stdioとか
package main /* #include <math.h> double MyPow(double x, double y) { double ret = pow(x, y); return ret; } */ import "C" import "fmt" func main() { ret := C.MyPow(10, 2) fmt.Println(ret) } - 結構面倒くさい決まりごと
(1)import "C" の前には空行を入れない// #include <stdio.h> // #include <errno.h> import "C"(2)C / C++ のコンパイラに渡すオプション(flag)を記述する
// #cgo CFLAGS: -I/usr/local/lib import C