【JavaScript】Google Maps JavaScript APIで面倒なマッピングを自動化してみた話

## 内容
![gps.gif](https://qiita-image-store.s3.amazonaws.com/0/377231/d3f81c97-13a0-f068-a1de-087eb382563c.gif)
・事前に現場にて測位計測しないと作成できない走行用**マップの作成を自動化**．

・**GPS**を使った**自律移動ロボット**や**ドローン**向けのマップとして色々応用できると思う．







## 制作物紹介
**YouTube↓**（音量注意）
<a href="https://youtu.be/TU-1X-gPXJg"><img width="935" alt="gps.png" src="https://qiita-image-store.s3.amazonaws.com/0/377231/ba5cd4c3-d9e7-07ef-3b42-f8c96c469c0f.png"></a>
とまあこんなかんじで

waypointプロットするだけであとは自動で**座標取得**

→**平面座標系**への変換

→スタート地点を中心に**オフセット処理**

→**マップ**を作成してくれます

## 環境
・JavaScript
・HTML
・CSS
・Python
・Google Maps JavaScript API
・ShellScript

## 使い方
以下GithubからダウンロードしてYouTubeの動画どおりに利用してください．
詳細，各プログラムの解説も[Github](https://github.com/shutokawabata0723/GPS_CHANNEL)で行っています．

## 今回のコアな部分
流れ
・３つの地点候補から１つを選択させる
・選択された地点に移動
・スタート地点からゴール地点までの間に，waypointを任意の感覚でプロット
・プロットされたwaypointの全位置座標（緯度，経度）をCSVファイルで保存
・ShellScriptで各Pythonプログラムを逐次実行，経緯度座標を直行平面座標へ変換，グラフとして描写
<img width="1142" alt="kosen2.png" src="https://qiita-image-store.s3.amazonaws.com/0/377231/7a57afa0-20e3-b7c1-d1a8-fb7c12123dab.png">
・緑の線は，高専ときのWGS84座標系に変換したバージョン（間違ってる）

今回のコアであるJS部分のメモ

```html:0_googleMap.html
<!--以下JavaScript-->
<script>
var array0 = [['marker','latitude','longitude']];
var table  = array0;

// 場所選択時における画面遷移
function move(st_lat,st_lng) {
  // マップの初期化
  var map = new google.maps.Map(document.getElementById('map'), {
  zoom: 19,
  center: {lat: st_lat, lng: st_lng},
  mapTypeId: google.maps.MapTypeId.SATELLITE ,
  });
  // クリックイベントを追加
  map.addListener('click', function(e) {
    getClickLatLng(e.latLng, map);
  });
}


function calcBmi(){
  var place = document.getElementById('place').value;
  // ここの座標かえるだけでいろいろ応用可能
  if(place == 'oyama'){
    move(36.318940,139.842150);// 小山高専
  }else if(place=='tsukuba'){
    move(36.080349,140.115203);// つくばチャレンジ会場
  }else if(place=='daigaku'){
    move(36.109101,140.103641); // 筑波大学キャンパス
  }
}


var click_count = 0;
function initMap() {
  // マップの初期化
  var map = new google.maps.Map(document.getElementById('map'), {
  zoom: 19,
  center: {lat:36.38992, lng: 139.06065},
  mapTypeId: google.maps.MapTypeId.SATELLITE ,
  });

  // クリックイベントを追加
  map.addListener('click', function(e) {
    getClickLatLng(e.latLng, map);
  });
}


function getClickLatLng(lat_lng, map) {
  click_count++;
  str_cnt = String(click_count);
  str_lat = String(lat_lng.lat());
  str_lng = String(lat_lng.lng());
  var array1 = [str_cnt, str_lat, str_lng];
  array0.push(array1);

  // 座標を表示
  document.getElementById('lat').textContent = lat_lng.lat();
  document.getElementById('lng').textContent = lat_lng.lng();
  document.getElementById('cnt').textContent = click_count;
  
  // マーカーを設置
  var marker = new google.maps.Marker({
    position: lat_lng,
    map: map,
    animation: google.maps.Animation.BOUNCE ,
    opacity: 0.7,
    label: {
      text:""+click_count,
      color: "white" ,
      fontSize: "20px" ,
    },
    icon: {
      url: "./fig/marker.png" ,
      scaledSize: new google.maps.Size(15,30) ,
    },
  });
  var size = new google.maps.Size( 200, 200 ) ;
  // 座標の中心をずらす
  map.panTo(lat_lng);
}

// CSVファイルに出力するための関数
var downloadCsv = (function() {
  var tableToCsvString = function(table) {
    var str = '\uFEFF';
      for (var i = 0, imax = table.length - 1; i <= imax; ++i) {
        var row = table[i];
        for (var j = 0, jmax = row.length - 1; j <= jmax; ++j) {
          str += '"' + row[j].replace('"', '""') + '"';
          if (j !== jmax) {
            str += ',';
          }
        }
        str += '\n';
      }
      return str;
    };
    var createDataUriFromString = function(str) {
      return 'data:text/csv,' + encodeURIComponent(str);
    }


  var downloadDataUri = function(uri, filename) {
    var link = document.createElement('a');
    link.download = filename;
    link.href = uri;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  return function(table, filename) {
    if (!filename) {
      filename = 'output.csv';
    }
    var uri = createDataUriFromString(tableToCsvString(table));
    downloadDataUri(uri, filename);
  };
})();

// CSVに出力
function save(){
  downloadCsv(table);
}
</script>

// Google Maps JavaScript API　（開発者向け）の呼び出し
<script src="https://maps.googleapis.com/maps/api/js?signed_in=true&callback=initMap" async defer></script>
```




## 制作背景
・高専ときの研究，「GPS用いた自律移動ロボット」に必要なマップ作成が地味で大変な作業だった．（冬とかめっちゃ寒かった）
・これ自動化できたら便利じゃね？👀ってなった．
・高専ときの先生にあげた
・喜んでた