いっしきまさひこBLOG

AI・機械学習関連、Web制作関連、プログラミング関連、旅行記録などなど。一色政彦。

Azure Blob(Webホスティング用)→S3移行を自動化! Pythonスクリプトを公開中

2024年12月、「Azure CDN from Edgioが廃止される」という突然の通知に驚き、移行作業に追われた方も多いのではないでしょうか。私もその1人でした。Webスタティックホスティング用途で「Azure Blobストレージ+Azure CDN」を複数のサイトで利用していたため、急遽、別のCDNへの移行が必要になりました。

Azure Front Doorへの移行が推奨されていますが、私の用途ではオーバースペックでコストが見合わず※1、最終的にAmazon S3+CloudFrontへの移行を選びました。その過程で、Pythonスクリプトを用いて効率よく移行を行う方法を開発しました。

※1 Azure Front Doorは高機能で優れた選択肢ですが、基本料金が高額で、小規模なWebサイトでは費用対効果が低い場合があると思います。

課題と解決策

移行作業では、AWS DataSyncも試しましたが、自由度が低く、私の求める柔軟性を満たせませんでした。そのため、自作のPythonスクリプトを使い、以下の機能を実現しました。

  • Azure Blobストレージから(ローカル環境へ)のデータ取得
  • Amazon S3へのアップロード
  • 実行時のログやエラーを管理

このあと、CloudFrontでHTTPS対応のホスティングを設定する作業は説明資料に従って進めてください。

スクリプトは以下のGitHubリポジトリで公開しています。興味がある方はぜひご覧ください。

本スクリプトおよび資料は、現状のまま(AS IS)で提供されており、いかなる保証も行いません。本スクリプトの使用により発生したいかなる損害や問題についても、作成者は一切の責任を負いかねます。ご利用は自己責任でお願いいたします。

説明資料

詳細な手順はREADME.mdに記載しています。以下にもその内容を転載しておきます。

https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png

Azure Blob to S3 Migration

このプロジェクトは、Azure Blobストレージからファイルをダウンロードし、Amazon S3にアップロードするためのPythonスクリプトを提供します。

また、アップロードした後に、Amazon S3をスタティック(静的)なWebサイトホスティングサービスとして構成し、Amazon CloudFrontによりCDNで配信されるようにし、AWS Certificate Manager(ACM)により生成し自動更新されるHTTPS用のSSL証明書を設定するまでの作業手順も、このREADME.mdファイルに掲載しています。

ただし、スクリプトはWindows環境で実行しているため、それ以外の環境での動作は保証できません。細かい調整が必要な場合は、スクリプトを修正することで対応してください。

※本スクリプトの実行は自己責任で行ってください。いかなる責任も負いません。また、本スクリプトにPR(プルリクエスト)やIssue(問題報告)を送られても、一切対応しませんので、あしからずご了承ください。

構成

  • requirements.txt: 必要なPythonパッケージのリスト。
  • config.ini: 認証情報を含む設定ファイル。
  • AzureBlobDownload.py: Azure Blobストレージからファイルをダウンロードします。
  • AwsS3Upload.py: ダウンロードされたファイルをAmazon S3にアップロードします。
  • BlobS3Compare.py: 念のため、Azure BlobストレージとAmazon S3の内容を比較します。開発者が3サイトで実施して失敗はなかったため不要かもしれません。

ログファイル

  • <Blob名>_download_log.txt: Azure Blobストレージからのダウンロードに関するログ。
  • <S3名>_upload_log.txt: Amazon S3へのアップロードに関するログ。
  • <S3名>_compare_log.txt: Azure BlobストレージとAmazon S3の内容比較に関するログ。

リトライ機能

※本プロジェクト開発者が試した限りでは、失敗が発生したことがないため、リトライ機能は実装済みですが、正常に稼働するかは検証されていません。

  • ダウンロードやアップロードに失敗したファイルは、リトライ用のファイルに記録されます。
  • 次回実行時にリトライ用のファイルを読み込み、前回失敗した処理を再試行します。成功した処理は再試行しません。
  • 全てのファイルが成功した場合、リトライ用のファイルは削除されます。

前提条件

Azure BlobストレージをWebサーバとして活用してスタティックなWebページや画像を配信していることを前提としています。また、Azure CDNなどでCDNとSSLの自動更新を対応している場合もカバーしています。

既存のAzure Blobストレージが存在するあることを前提としています。また、同名のAmazon S3バケットを以下の手順で作成しておいてください。

S3バケットを作る手順

作成時に以下の内容を指定することを前提とします。

  1. AWS リージョンは「アジアパシフィック (東京) ap-northeast-1」とします。
  2. AWSコンソールでS3の[汎用バケット]を開き、[バケットを作成]をクリックします。
  3. [バケットタイプ]は「汎用」を選択します。
  4. [バケット名]はAzure Blobストレージアカウントと同じ名前にします。例:remasahiko
  5. [ACL無効]を選択してください。
  6. [パブリックアクセスをすべてブロック]のチェックを外してください。
  7. [バケットのバージョニング]は「有効にする」にしてください。
  8. [タグ - オプション]でキーは「Name」、値は「<任意のプロジェクト名(例:masahiko.info)>」でタグを追加してください。
  9. 他はデフォルトのまま[バケットを作成]をクリックしてください。
  10. これでS3バケットの作成は完了です。

必要なPythonパッケージ

以下のコマンドを使用して、必要なパッケージをインストールしてください。

pip install -r requirements.txt

認証情報の設定

Azure Blobストレージアカウントの接続文字列の取得

  1. Azureで対象のストレージアカウントを開き、左のメニューから[セキュリティとネットワーク]-[アクセスキー]を選択します。
  2. [接続文字列]をコピーします。

AWSのアクセスキーの取得

AWSのアクセスキーはユーザーごとに取得します。セキュリティの問題もあるので、全ての作業が終わったら無効化もしくは削除するのがお勧めです。

  1. AWS Management Consoleにログインし、IAMサービスに移動します。
  2. 左側のメニューから[ユーザー]を選択します。
  3. 該当のユーザー名をクリックします。
  4. 上部の[セキュリティ認証情報]タブを開きます。
  5. [アクセスキーを作成]をクリックします。
  6. [ユースケース]は「ローカルコード」を選択します。
  7. [説明タグ値]は空のままで[アクセスキーを作成]をクリックします。
  8. これにより、アクセスキーIDとシークレットキーが発行されるので、確実にどこかに記述してください。

config.iniの編集

ご自身の環境に合わせて修正してください。

  • ConnectionString: Azure Blob Storageの接続文字列を設定します。
  • BlobStorageName: Blobストレージ名を指定します。
  • S3BucketName: 比較対象のS3バケット名を設定します。
  • AccessKeyId: AWSアクセスキーIDを設定します。
  • SecretAccessKey: AWSシークレットアクセスキーを設定します。
  • Region: AWSリージョンを設定します。

使用方法

AzureBlobDownload.pyの使用方法

(1) AzureBlobDownload.pyを実行して、Azure Blobストレージからファイルをダウンロードします。

python AzureBlobDownload.py

注意点として、パブリックアクセスが 'container' 以外のコンテナ(プライベートやBLOBなど)はスキップする仕様なので注意してください。必要があればプログラムを書き換えてください。

(2) ダウンロードされたファイルは、指定されたローカルディレクトリに保存されます。

AwsS3Upload.pyの使用方法

(1) AwsS3Upload.pyを実行して、ダウンロードされたファイルをAmazon S3にアップロードします。

python AwsS3Upload.py

(2) アップロードの成功または失敗はログファイルに記録されます。

BlobS3Compare.pyの使用方法

(1) BlobS3Compare.pyを実行して、Azure BlobストレージとAmazon S3の内容を比較します。

python BlobS3Compare.py

(2) 比較の結果はログファイルに記録されます。

全て成功すれば作業は完了です。

S3バケットをスタティックなWebサイトホスティングサービスにするまでの手順

注意事項

  • パブリックアクセスを有効化する際はセキュリティに注意してください。不要なデータが公開されないように。
  • 公開したくないファイルはそもそもアップロードしない方がよいでしょう。このスクリプトではもともとAzure Blobストレージでパブリックに公開されていたBlobのみを移行する仕様になっていますので、基本的には新たに不要なデータが公開されることはないはずです。

手順 1: 静的Webサイトホスティングを有効化

  1. AWSコンソールで対象のS3バケットを選択します。
  2. 上部メニューの[プロパティ]をクリックしてください。
  3. [静的Webサイトホスティング]セクションの[編集]をクリック。
  4. 「静的Webサイトホスティング」の「有効にする」を選択します。
  5. [ホスティングタイプ]jは、「静的ウェブサイトをホストする」を選択します。
  6. [インデックスドキュメント](例: index.htmldefault.html)を入力。
    • 必要なら[エラードキュメント](例: error.html)も入力。このファイルは基本的にバケットのルート(トップレベル)に配置してください。
  7. [変更の保存]をクリックします。

サンプルのerror.htmlファイルをこのプロジェクトに含めていますので、これをS3バケットのトップレベルにアップロードしてみてください。

手順 2: ブロックパブリックアクセスをオフにする

この作業は、作成時にオフにしていれば不要です。

  1. 上部メニューの[アクセス許可]をクリック。
  2. [ブロックパブリックアクセス (バケット設定)]セクションの[編集]をクリック。
  3. すべてのチェックボックスをオフにします。
  4. 保存します。
  5. 注意: この設定変更により、バケットがパブリックにアクセス可能になるリスクがあります。次のポリシー設定を適切に行いましょう。

手順 3: バケットポリシーを設定

S3バケットをパブリックにアクセス可能にするため、バケットポリシーを記載します。

以下は、特定のS3バケット(例: example-bucket)内のすべてのオブジェクトをパブリックにするポリシーです。arn:aws:s3:::example-bucketの部分は「バケット ARN」と呼ばれますが、編集画面上でコピーできます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
  1. 引き続き[アクセス許可]にある[バケットポリシー]セクションの[編集]をクリック。
  2. 上記のJSONコードを貼り付けます(example-bucketを実際のバケット名に変更)。
  3. 保存します。

手順 4: オブジェクト所有者を確認

S3バケットの[アクセス許可]で[オブジェクト所有者]が「バケット所有者の強制」となっている場合、ACL(アクセスコントロールリスト)は無効になっています。つまり、このバケット内のすべてのオブジェクトは、このアカウントによって所有されます。このバケットとそのオブジェクトへのアクセスは、ポリシーのみを使用して指定されます。

このプロジェクトでは、ACLが無効であることを前提としています。ACLが有効な場合、バケットポリシーを設定しても、オブジェクト(ファイル)がパブリックでない場合があります。

手順 5: WebサイトのURLにアクセス

スタティックWebサイトのURLは、以下の形式になります。

http://{バケット名}.s3-website-{リージョン}.amazonaws.com
http://remasahiko.s3-website-ap-northeast-1.amazonaws.com
  1. 対象のS3バケットの上部メニューの[プロパティ]をクリックしてください。
  2. 一番下の[静的ウェブサイトホスティング]にある「バケットウェブサイトエンドポイント」のURLを開いてみてください。個別のオブジェクトにアクセスできるかは後で確認します。
  3. 上部メニューの[オブジェクト]から任意のオブジェクトを開いてください。
  4. 上部メニューの[プロパティ]を開き、[オブジェクトの概要]の[オブジェクト URL]を開いて、実際にWebアクセスできるかを確認してください。
  5. これによりHTMLページや画像などが正常に表示されれば、S3のスタティックなWebサイトの公開は完了です。

S3バケットのサイトがCDN(カスタムドメインSSL証明書あり)で配信されるまでの手順

Amazon CloudFrontの手順の中で、AWS Certificate Manager(ACM)を使ってカスタムドメイン用のSSL証明書を取得するようになっています。証明書の発行時にDNS検証を選択することによって、期限切れの60日前に自動更新されます。

Amazon CloudFrontの設定手順

  1. CloudFrontディストリビューションの作成

    1. AWS Management Consoleにログインし、CloudFrontサービスに移動します。
    2. [CloudFront ディストリビューションを作成]をクリックします。
    3. [Origin domain]で、S3バケットのエンドポイントを選択し、それにより表示される[Web サイトのエンドポイントを使用]をクリックします。
      • 例: - <バケット名>.s3-website-<リージョン>.amazonaws.com
    4. [名前]は自動的に入力されます。
    5. [デフォルトのキャッシュビヘイビア]セクションで[ビューワープロトコルポリシー]を「Redirect HTTP to HTTPS」に設定します。
    6. [ウェブアプリケーションファイアウォール (WAF) ]セクションで「セキュリティ保護を有効にしないでください」を選択します。追加費用を発生させないためです。必要になったらONにすればよいと思います。
    7. [設定]セクションの[料金クラス]で、日本メインなら「北米、欧州、アジア、中東、アフリカを使用」を選択します。性能と価格のバランスがよいためです。世界中からアクセスされるなら「すべてのエッジロケーションを使用する (最高のパフォーマンス)」がよいでしょう。
    8. その下の[代替ドメイン名 (CNAME) - オプション]で、[項目を追加]をクリックして、カスタムドメイン名(例:re.masahiko.info)を入力します。
    9. その下の[Custom SSL certificate - optional]で、[証明書をリクエスト]リンクをクリックします。
      • [パブリック証明書をリクエスト]を選択して[次へ]をクリックします。
      • [完全修飾ドメイン名]にカスタムドメイン名(例:re.masahiko.info)を入力します。
      • [検証方法]は「DNS 検証 - 推奨」に必ずしてください。
      • 他はデフォルトの推奨設定のままにします。
      • リソースグループで管理しやすいように[タグ]も付けるのがお勧めです。キーは「Name」として、値は「masahiko.info」など独自のグループ名を指定します。
      • [リクエスト]をクリックします。
      • [ステータス]が「保留中の検証」となるので、検証用にDNSのCNAMEの追加が必要です。お使いのDNSの設定箇所で、[ドメイン]内の表で取得できる「CNAME名」からサブドメインまでの部分(例:_abcdef123456gh7i8j9klm01n2opq345.<subdomain>)を名前として、「CNAME値」(ドメイン名で場合によっては最後の.を除いて内容、例:_a0123bcdefghigklmnopqrst45fvwxyz.zfyfvmchrl.acm-validations.aws.)を値(正規名)として指定してください。
      • 30分もしないうちに発行済みになります。[ステータス]に「発行済み」と表示されるまで待ちます。ブラウザーでリロードすると表示が変わる場合があります。
    10. CloudFrontのディストリビューション作成画面に戻ります。
    11. [Custom SSL certificate - optional]の右端の更新ボタンをクリックした後で、先ほど作成したSSLを[Custom SSL certificate - optional]で選択します。
    12. [Default root object - optional]にルート(/)でアクセスされたときに自動表示するファイル名(例: index.htmldefault.html)を入力。
    13. [ログ配信]は必要があればオンにしてください。ただし追加費用がかかるため、私の場合はオフにしています。
    14. [ディストリビューションを作成]をクリックします。
  2. CloudFrontディストリビューションのデプロイ

    • ディストリビューションのステータスが「有効」になるまで待ちます。わたしの場合はすぐでしたが、数分かかることがあるようです。
    • ディストリビューションのステータスは、CloudFrontのトップページでも確認できます。
  3. CloudFrontディストリビューションの確認

    • CloudFrontディストリビューションの[ディストリビューションドメイン名]を使用して、S3に配置したオブジェクトのパスのWebページや画像にアクセスして、無事に表示されるのを確認します(表示されるようになるまでに数分かかります)。例: d123456abcdef8.cloudfront.net
    • [ディストリビューションドメイン名]はCDN設定で使うので、保存しておいてください。

カスタムドメインのDNS設定と確認

最後にカスタムドメインでアクセスされるように設定すれば完了です。

カスタムドメインのCNAMEの内容(ドメイン名)に[ディストリビューションドメイン名]を指定してください。[ディストリビューションドメイン名]はCloudFrontで確認できます。

念のため、依然のCNAME内容は一時的に何かに書き写してバックアップしておきましょう。

反映まで1時間ほどかかります。長い場合は72時間程度も時間がかかることがあります。反映されたかはSSL証明書をブラウザから確認すればよいでしょう。もしくは以下のコマンドで確認できます。

nslookup <カスタムドメイン名>

ここまで出来たらAzure BlobストレージとAzure CDNの役目も終了なので、削除しても構いません。が、トラブル回避のため、72時間ほど様子を見てからの方がよいかもしれません。

全ての作業が終わったら、AWSのアクセスキーは無効化するか、削除しておきましょう。

ライセンス

このプロジェクトはApache License 2.0の下で公開されています。詳しくはLICENSEファイルをご確認ください。

AI/機械学習/データサイエンス関連の検定・資格の取得履歴

合格証明証を表示する場所もないので、このエントリに貼り付けていくことにしました。

ちなみに「gacco(統計学/サイエンス/AI・機械学習)の修了証」というページもあります。

Google データアナリティクス プロフェッショナル認定証

Google データアナリティクス プロフェッショナル認定証

マナビDX Quest:2022年度 第1ターム ケーススタディ教育プログラムGold修了証 (データ駆動型の変革推進の疑似体験)

マナビDX Quest:2022年度 第1ターム ケーススタディ教育プログラムGold修了証 (データ駆動型の変革推進の疑似体験)

データサイエンティスト検定 リテラシーレベル 2022

データサイエンティスト検定 リテラシーレベル 2022

JDLA Deep Learning for GENERAL 2017

JDLA Deep Learning for GENERAL 2017

統計検定2級

統計検定2級

オープンバッジ形式の合格証明書

ミニぷぱ(Mini Pupper)の日本向け販売サイトとROSを学ぶお勧め教材

ミニぷぱの日本向け公式販売サイトがオープンしたようです。

MangDang JP Shop

こちらの公式ツイートによると、2022年6月1日~15日で特別キャンペーンをやっているようです。30%オフとお安く入手できるチャンスです。初日(2022年6月1日?)のみのプレゼントもあるようです。

自分は入手済みなのでもう購入しないですが...。

Mini Pupper V2情報

上記はミニぷぱ「V1」の販売情報ですが、この記事を書いた本日、「V2」の情報が出てきています。詳しくは下記のツイートを参照してください。

「Fly in the sky?」とドローン的に飛べるようになるような感じで書かれていますね。AI機能も強化されそうです。以下にV1とV2の比較表を引用しておきます。

Mini Pupper V1とV2の比較表(@LeggedRobotのツイートから引用)

これは欲しい。OSは最新のUbuntu 22.04 LTSになり、ミドルウェアのロボット用プラットフォームはROS 2になるようです。V2は年末までにローンチされて出荷開始される計画とのこと。楽しみですね。それまでの練習にV1を購入して、ROSを学んでおくのもよいと思います。ROS 1の知識はROS 2でもある程度有効なようなので。

お勧めのROS 1書籍

ミニぷぱV1では下記の2本の記事を執筆しました。これ以上は書く予定はなく、V2待ちです。

これを書くに当たってROSはミニぷぱの開発を試しながら理解していったのですが、下記の書籍『ROSではじめるロボットプログラミング[改訂版] (I/O BOOKS)』を参考にしました(※2021/10/26発売の「改訂版」であることに注意)。

あらためて今日、最初から最後まで読み通しましたが、開発しながらコードや公式ドキュメント、ネット情報から調べて分かったことが全てこの本に書いていました...。本屋さんでこの本を選んだので、これ以外のROS本は読んでいませんが、他の人のコメントを読んでもROS初心者向けの最初の1冊として他の書籍よりもよさそうです。ROS 1を学ぶ人にわたしもお勧めします。

また、上記の2本目の記事もコードコメントの形で重要な内容を含めているので、そちらを読むだけでもROSの理解は広がるかなと思います。

ミニぷぱ(Mini Pupper)のキャリブレーションの「こつ」

ミニぷぱ(Mini Pupper)のキャリブレーションは意外に失敗しやすいポイントです。ここで失敗するとうまく走行できなかったりこけやすかったりします。実際に私も最初はキャリブレーションに失敗してこけやすく仕上がってしまい、サポートに問い合わせました。

まず、キャリブレーションには、

  • 45°(新しいバージョン)
  • 90°(古いバージョン)

の2種類の角度があります。PS4版のキャリブレーション時に、公式マニュアル通りにやると45°のキャリブレーションをするようになっていますが、これが難しい。しかし慣れた今ではコツが分かるので紹介します。

あと、PS4版のマニュアル通りにやったつもりでしたが、なぜか90°でキャリブレーションしなければなかったです。これもキャリブレーションに失敗した理由なのですが。

最新のPS4版のソースコードでは45°になっています。個人的には90°がキャリブレーションしやすいと思いましたが、開発元のMangDang社によると「45°が分かりやすい」という意見が多数でこれに決定したとのことでした。

これもかなり慣れてから気付いたこですが、OSイメージをダウンロードできる場所が、

このように複数あります。新しいOSイメージをダウンロードするように気を付けましょう。

45°のキャリブレーションの「こつ」

具体的には下の図のようになります。図は公式マニュアル「ソフトウェア — Mini Pupper 1.0.0-alpha ドキュメント」から引用した画像を少し加工したものです。

45°のキャリブレーションのこつ(公式マニュアルから引用して加工)

特に重要なのが(1)です。各足の接地点がモーターの軸の完全に真下にすることでこけることがほぼ無くなりました。マニュアルでは45°が強調されていますが、わたしの感想ではこの点が重要で、あとは(2)の関節部分を90°にすればよいだけです。これだけです。45°の分度器は不要です。

90°のキャリブレーションの「こつ」

もう一方の90°の方は簡単です。具体的には下の図のようになります。図は公式マニュアル「SLAM・ナビゲーション — Mini Pupper 1.0.0-alpha ドキュメント」から引用した画像を少し加工したものです。

90°のキャリブレーションのこつ(公式マニュアルから引用して加工)

単純なキャリブレーションは90°の方が簡単だと思いますが、実際の走行バランスが正確に取れることを考えると、確かに45°でキャリブレーションするのが一番いいですね。

「ミニぷぱの走行バランスがおかしい」「ミニぷぱがこけやすい」という人は、ミニぷぱが静止して起立した状態で、上の45°の状態になっているかを確認してみるとよいと思います。

ミニぷぱ(Mini Pupper)のPS4版/ROS版のキャリブレーションデータ

ミニぷぱでキャリブレーションをしたとき、のPS4版/ROS版ではデータの保存先が異なります。

PS4版

/home/ubuntu/Robotics/QuadrupedRobot/StanfordQuadruped/calibrate_tool.pyファイルの内容を確認するのが一番良いです。

コードを読むと、Raspberry Pi 4 Model Bボード上のEEPROM(不揮発性メモリ)に格納されています。これにより、PS4版のOSのmicroSDカードを差し替えても、キャリブレーションデータが引き継がれます。

このデータをROS版でも読み取ってくれればよいのですが、ROS版はファイルで管理されているようです。

ROS版

こちらは/home/ubuntu/catkin_ws/src/minipupper_ros/servo_interface/scripts/calibrate.pyファイルの内容を確認してください。

コードを読むと、/home/ubuntu/catkin_ws/src/minipupper_ros/servo_interface/config/calibration/calibration.yamlファイルとして保存されています。よって、ROS版のOSのmicroSDカードを差し替える場合は、このファイルをコピペすれば引き継げるのではないかと思います(やったことがないので不明)。

どちらかに統一してほしいけど、YAMLファイルの方が取り扱いはしやすいですね。

ROS版にはPS4版のようにGUIで作業できるキャリブレーションツールがありません。PS4版のキャリブレーションツールをROS版で使っても、EEPROMに保存されるだけなので意味がありません。キャリブレーションツールのコードは難しく無さそうなので、ROS版用に修正するということも不可能ではないのですが、そこまでするのは面倒なのですよね。

ミニぷぱ(Mini Pupper)ROS版のRaspberry Pi 4 Model BのGPIOピン

非常にニッチだと思いますが、ミニぷぱのROS版のGPIOピンの情報を共有します。

※書く必要もないと思いますが念のため。この記事の通りに実施して何か起きた場合の責任は筆者および本サイトは負いません。自己責任でお願いします。

GPIOピン

ミニぷぱのROS版でGPIOピンがどのように使われているかはコードを追いかけて調べるしかありません(たぶん、資料がなさそうです)。書き方が雑ですが、自分がコード上に書いたものをコピペしたためです。

自分がコードを調べてチェックした限りでは以下のように使われいるようでした。※勘違いや間違いがあるかもしれないので、あくまでヒントとして参照してください。

# - GPIO0 : ID_SD <Serial Data for HAT for EEPROM>
# - GPIO1 : ID_SC <Serial Clock for HAT for EEPROM>
# - GPIO2 : I2C SDA <Inter-Integrated Circuit> <Serial Data>
# - GPIO3 : I2C SCL <Serial Clock>
# - GPIO4 : "[Leg4]Left-Front-Calf" GPCLK0 <General Purpose Clock>
# - GPIO5 : "[Leg4]Left-Front-Thigh" GPCLK1
# - GPIO6 : "[Leg4]Left-Front-Hip" GPCLK2
# - GPIO7 : "[Leg3]Right-Back-Calf" SPI CE0 <Serial Peripheral Interface> <Chip Enable>
# - GPIO8 : "[Leg3]Right-Back-Thigh" SPI CE1
# - GPIO9 : "[Leg3]Right-Back-Hip" SPI MISO <Master In Slave Out>
# - GPIO10: "[Leg2]Left-Fore-Calf" SPI MOSI <Master Out Slave In>
# - GPIO11: "[Leg2]Left-Fore-Thigh" SPI SCLK <Serial Clock>
# - GPIO12: "[Leg2]Left-Fore-Hip" PWM0 <Pulse Width Modulation>
# - GPIO13: "[Leg1]Right-Fore-Calf" PWM1
# - GPIO14: "[Leg1]Right-Fore-Thigh "UART TXD <Universal Asynchronous Receiver Transmitter> <Transmit Data>
# - GPIO15: "[Leg1]Right-Fore-Hip" UART RXD <Receive Data>
# - GPIO16: "Battery Buzzer"
# - GPIO17: 
# - GPIO18: PCM_CLK <Pulse Code Modulation> <PCM Clock>
# - GPIO19: PCM_FS <PCM Frame Sync>
# - GPIO20: PCM_DIN <PCM Data In>
# - GPIO21: "Servo 2 control" PCM_DOUT <PCM Data Out>
# - GPIO22: 
# - GPIO23: 
# - GPIO24: "LCD RST <ReSeT control>"
# - GPIO25: "Servo 1 control"
# - GPIO26: "LCD LED <backlight LED control>" <for input>
# - GPIO27: "LCD DC <Data/Command (NOT MOSI!)>" <for output>

Raspberry Piの40ピン構成:

# 40-pins configuration of Raspberry Pi:
#    3V3  (1) (2)  5V
#  GPIO2  (3) (4)  5V
#  GPIO3  (5) (6)  GND
#  GPIO4  (7) (8)  GPIO14
#    GND  (9) (10) GPIO15
# GPIO17 (11) (12) GPIO18
# GPIO27 (13) (14) GND
# GPIO22 (15) (16) GPIO23
#    3V3 (17) (18) GPIO24
# GPIO10 (19) (20) GND
#  GPIO9 (21) (22) GPIO25
# GPIO11 (23) (24) GPIO8
#    GND (25) (26) GPIO7
#  GPIO0 (27) (28) GPIO1
#  GPIO5 (29) (30) GND
#  GPIO6 (31) (32) GPIO12
# GPIO13 (33) (34) GND
# GPIO19 (35) (36) GPIO16
# GPIO26 (37) (38) GPIO20
#    GND (39) (40) GPIO21

ミニぷぱ(Mini Pupper)のROS版で起動時に鳴かせて顔を表示させる方法

ミニぷぱのROS版を触っていて、少し知見がたまってきています。

非常にニッチだと思いますが、ミニぷぱのROS版をPS4版のように扱えないと感じる人も多いかと思うので、個人的に知っている内容を書いておきます。誰かに役立つといいけど。

※書く必要もないと思いますが念のため。この記事の通りに実施して何か起きた場合の責任は筆者および本サイトは負いません。自己責任でお願いします。

ROS版で起動時に鳴かせる方法

PS4版では起動時に鳴くので起動が分かりやすいです。なぜかROS版では実装してくれていません(もしかしたら最新版では対応済みかもしれません。確認していません)。

鳴き声の音声はこちらにあります: github.com

これを再生するだけです。再生コマンドはmpg123 /home/ubuntu/Music/power_on.mp3にようになります。このコマンド実行を、起動時のrc.localサービスで実行してもらいます: github.com

rc.localファイルは、

  • /home/ubuntu/minipupper_ros_bsp/mangdang/System/rc.local

にあります。私のrc.localファイルの中身は以下のようになっています。個人的にカスタマイズを試しまくっているので元と違うかもしれません。

#!/bin/bash
#
# 1.Initialize power switch and pwm units
# 2.start lcd
#
# Copyright (c) 2020, Mangdang Technology Co., Limited
#
#

#remove bluebooth cache
# sudo rm /var/lib/bluetooth/* -rf
# sleep 2

# get hardware version
# echo 27 > /sys/class/gpio/export
# echo in > /sys/class/gpio/gpio27/direction
# hw_version_io=`cat /sys/class/gpio/gpio27/value`
# echo 27 > /sys/class/gpio/unexport
# if [ "$hw_version_io" == "1" ]; then
#   sudo echo "P1" > /home/ubuntu/.hw_version
# else
#   sudo echo "MP" > /home/ubuntu/.hw_version
# fi

#export pwm channel
for i in $(seq 0 15)
do
    sudo echo $i > /sys/class/pwm/pwmchip0/export
    sudo echo  4000000 > /sys/class/pwm/pwmchip0/pwm$i/period
    sudo chmod  777  /sys/class/pwm/pwmchip0/pwm$i/duty_cycle
done

# init the Bluetooth
# sudo hciattach /dev/ttyAMA0 bcm43xx 115200 noflow -
# sleep 8
# sudo hciattach /dev/ttyAMA0 bcm43xx 115200 noflow -
# sleep 2

# init lcd
#python3 /home/ubuntu/minipupper_ros_bsp/mangdang/LCD/lcd_init.py

# set cpu performance
# Set the Frequency Governor to Performance (run CPU at maximum frequency) which determines the frequency policy. Default is On-Demand
# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# conservative ondemand userspace powersave performance schedutil が利用可能
echo performance > /sys/bus/cpu/devices/cpu0/cpufreq/scaling_governor

# show wake-up-face (& means background job)
su ubuntu -l -c "python3 /home/ubuntu/minipupper_ros_bsp/mangdang/LCD/wake-up-face.py" &

# play sound (& means background job)
su ubuntu -l -c "mpg123 /home/ubuntu/Music/power_on.mp3" &

exit 0

音声コマンドは最後に実行しているsu ubuntu -l -c "mpg123 /home/ubuntu/Music/power_on.mp3" &ですね。/home/ubuntu/Music/ディレクトリに音声ファイルを配置しました。

このrc.localサービスを有効にするには、以下のコマンドを実行してください。

# Install mangdang wake-up service
cd /home/ubuntu/minipupper_ros_bsp/mangdang/System
sudo bash install.sh
sudo reboot

ROS版で顔を表示させる方法

顔もアニメーションさせたりいろいろとできるのですが、PS4版で動くとアニメーションするようなコードになっていたと思います。それを実装するのは面倒なので、取りあえず起動時にlogo用の顔(黄色と黒色が反転した顔)を表示させるようにしてみましょう。手間を省くため、上記と同じrc.localサービスを利用しました。

上のコードにあるsu ubuntu -l -c "python3 /home/ubuntu/minipupper_ros_bsp/mangdang/LCD/wake-up-face.py" &がその部分です。Pythonスクリプトを呼び出しています。そのスクリプトコードは以下の通りです。

import os
import sys

from PIL import Image

sys.path.append('/home/ubuntu/minipupper_ros_bsp')
sys.path.extend([os.path.join(root, name) for root, dirs, _ in os.walk('/home/ubuntu/minipupper_ros_bsp') for name in dirs])
# sys.path.append('/home/ubuntu/minipupper_ros_bsp/mangdang')
# sys.path.extend([os.path.join(root, name) for root, dirs, _ in os.walk('/home/ubuntu/minipupper_ros_bsp/mangdang') for name in dirs])
# from LCD.ST7789 import ST7789
from mangdang.LCD.ST7789 import ST7789


cartoons_folder = '/home/ubuntu/Pictures/'
disp = ST7789()


def main():
    """ To show wake-up-face
    """

    # Firstly, show logo
    #init st7789 device
    global disp
    disp.begin()
    disp.clear()
    image=Image.open(cartoons_folder + 'logo.png')
    image.resize((320,240))
    disp.display(image)


main()

####
#### run this script
####
# python3 /home/ubuntu/minipupper_ros_bsp/mangdang/LCD/wake-up-face.py

顔画像はこちらにあります: github.com

これらの画像ファイルを/home/ubuntu/Pictures/ディレクトリに配置しました。

仕組みさえ分かってしまえば特に難しいとろころはないのではないかと思います。その仕組みを説明する資料がないんですよね...。こんな感じでプログラミング次第で何でもできます。

ヒントとして、ROS版のこういったプログラム関連とそのインストール用ファイルは、

  • /home/ubuntu/minipupper_ros_bsp/mangdang

にまとめられています。それに対応するGitHubリポジトリが以下だと思います。

  • https://github.com/mangdangroboticsclub/minipupper_ros_bsp

また、ROS用のコマンドなど(ワークスペース)は、

  • /home/ubuntu/catkin_ws

というディレクトに入っています。それに対応するGitHubリポジトリが以下だと思います。

  • https://github.com/mangdangroboticsclub/minipupper_ros

ROS版でバッテリー電池不足時に鳴かせる方法

ついでにバッテリー電池不足時に鳴かせる方法も紹介しておきます。起動時に鳴かせる方法と基本的な考え方は同じです。電池がなくなったらsu ubuntu -l -c "mpg123 /home/ubuntu/Music/low_power.mp3"を実行するだけです。

バッテリー電池は/home/ubuntu/minipupper_ros_bsp/mangdang/FuelGauge/battery_monitorサービスで対応できます。私のbattery_monitorファイルの中身は以下のようになっています。

#!/bin/bash

#
# Copyright (c) 2021, Mangdang Technology Co., Limited
#

# IO Mapping configuration
IO_MAP=(
25 1  # Servo 1 control for v2 board - on
21 1  # Servo 2 control for v2 board - on
#26 1  # LCD LED <backlight LED control> - on
#24 0  # LCD RST <ReSeT control> - off
#27 0  # LCD DC <Data/Command (NOT MOSI!)> - off
)

# Set the above Configuration
function io_init(){
    len=${#IO_MAP[@]}
    for((i=0;i<len;i+=2))
    do
        io=${IO_MAP[i]}
        val=${IO_MAP[i+1]}
        echo $io > /sys/class/gpio/export
        echo out > /sys/class/gpio/gpio$io/direction
        echo $val > /sys/class/gpio/gpio$io/value
    done
}

# init IO
io_init
sleep 1

chmod 777 /sys/class/gpio/gpio24/value
chmod 777 /sys/class/gpio/gpio27/value
chmod 777 /dev/spidev0.0


#Power monitor
while true
do
    current_voltage=`cat /sys/class/power_supply/max1720x_battery/voltage_now`
    if [ $current_voltage -le 6500 ]; then
        echo 0 > /sys/class/gpio/gpio25/value
        echo 0 > /sys/class/gpio/gpio21/value
        su ubuntu -l -c "mpg123 /home/ubuntu/Music/low_power.mp3"
    fi
    sleep 8
done

このコード内のcat /sys/class/power_supply/max1720x_battery/voltage_nowで電圧をチェックし、電圧が6500未満になると、su ubuntu -l -c "mpg123 /home/ubuntu/Music/low_power.mp3"で音声ファイルを鳴らし続けています。PS4版のコードそのもののコードになっています。仕組みは簡単です。

ちなみにROS版の元々のコードでは、バッテリー側のブザー音を鳴らす内容になっていたと思います。音声ファイルの鳴き声の方が気分が乗りますよね。

このbattery_monitorサービスを有効にするには、以下のコマンドを実行してください。

# Install mangdang power-on service
cd /home/ubuntu/minipupper_ros_bsp/mangdang/FuelGauge
sudo bash install.sh
sudo reboot

ミニぷぱに付属のバッテリーでは、このように電圧をチェックできますが、人が見る場合、「電池があと何%?」と見た方が分かりやすいですよね。これを調べるには、

cat /sys/class/power_supply/max1720x_battery/capacity

というコマンドを実行すればよいです。実開発作業ではGUIを見ずにSSHでVisual Studio Codeから触ることが多いのではないかと思いますが、このコマンドは便利ですよ。

(走り書きで見直してないです以上です。読む人も限られると思うので最小コストで。)