OpticalFlow220424

ProcessingのOpticalFlowで人の行動を測定しようという企画。過去に何回か話題にあがっている。これとかこれとか、これも。すごい前から「使えそう」と言ってる割に、一回も使っていない。今回は大島さんとの共同研究で、実際に利用することになりそうだ。

 ProcessingのOpenCVライブラリには、OpticalFlow関連のサンプルプログラムがある。基本的にOpticalFlowを視覚化するプログラムなのだが、こちらのサイトから、640×480の各点のデータを取得する方法を学び、右半分と左半分を別に平均し、グラフ化、さらにディスクに保存するプログラムを作成した。
 結果はまぁまぁ予想どおり。各点の移動方向はVectorで取得できる。さらにそれをmag()関数で大きさを求め、指定範囲の平均を求めている。ProcessingのPVectorの説明はここにある。測定範囲を視覚化し、さらにある程度GUIで指定できるようになると、実用性が増すようにも思えるが、現場の状況を見ないとなんとも言えないので、次のMTGで話あいましょう。

import gab.opencv.*;
import processing.video.*;

Capture video; // ライブカメラ
OpenCV opencv; // OpenCV

String savefile = "data/movement.csv";
PrintWriter output;

void setup() {

  size(640, 480); //画面サイズ
  video = new Capture(this, 640, 480);  //キャプチャーするカメラのサイズ
  opencv = new OpenCV(this, 640, 480);  //OpenCVの画面サイズ
  video.start();  //キャプチャー開始
  
  output = createWriter(savefile);  //出力用ファイル
}

/////////////////////////////////
void draw() {
  
  scale(1.0);  //描画スケール設定
  
  opencv.loadImage(video);  //カメラの画像をOpenCVに読み込み
  image(video, 0, 0 );      //カメラ画像を表示
  opencv.calculateOpticalFlow();  //OpticalFlowを計算
  stroke(255,0,0);            //描画設定
  opencv.drawOpticalFlow();    //OpticalFlowを描画


  float LFlow = averagedFlow(0,0,320,480).mag();
  float RFlow = averagedFlow(320,0,320,480).mag();
  print(abs(LFlow)+"/"+abs(RFlow)+"\n");
  output.println(abs(LFlow)+","+abs(RFlow));
  
  
  stroke(0,0,255);  
  rect(0,480-LFlow*100,10,480);
  rect(630,480-RFlow*100,640,480);
  
  //PVector aveFlow = opencv.getAverageFlow();
  //print(aveFlow.x+"/"+aveFlow.y+"\n");
}

//キャプチャーイベント
void captureEvent(Capture c) {
  c.read();
}


/////平均化されたFlowを取得
PVector averagedFlow(int x,int y,int w, int h){

  float xsum=0,ysum=0,xavg=0, yavg=0;
  float c=0;
  for(int i=x;i<x+w;i++){  
    for(int j=y;j<y+h;j++){
      PVector vec = opencv.getFlowAt(i,j);
      xsum+=(float)vec.x;
      ysum+=(float)vec.y;
      c=c+1;
    }
  }
  xavg=xsum/c;
  yavg=ysum/c;
  
  PVector rv=new PVector(0,0);
  rv.x=xavg;
  rv.y=yavg;
  
  return(rv);  //ベクトルで返す
}

//終了時処理
void dispose(){
  output.close();
  println( "dispose start");
}

void keyPressed() {
  if (key == TAB) {          // Tabキーに反応
    output.close();
    exit();
  }
}

ArduinoでESP32

https://dl.espressif.com/dl/package_esp32_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json

TTGOでBME280を動かすには、下記のプログラムを使う。TTGOとBME280の接続は以下の通り。

(BME280)SCK-(TTGO)27
(BME280)SDO-(TTGO)G
(BME280)SDI-(TTGO)26
(BME280)GND-(TTGO)G
(BME280)VDD-(TTGO)3V

//BME280_ESP32
#include &lt;Wire.h>
#include &lt;SPI.h>
#include &lt;Adafruit_Sensor.h>
#include &lt;Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
unsigned long delayTime;

void setup() {
    Serial.begin(115200);

    Wire.begin(26,27);
    bool status;
    // default settings
    status = bme.begin(0x76); //read I2C address 0x76
    if (!status) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
    }
    delayTime = 1000;
    Serial.println();
}

void loop() {
    printValues();
    delay(delayTime);
}

void printValues() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");
    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
}

基礎実験課題220103

ああ先延ばしにしていた基礎実験追加課題・・・やはりやらねばならぬのだろうか?あと9日後には実施だから、準備するなら最早今しかない。思いついた実験計画は下記の通り。

樹木(多い・少ない)×水場(あり・なし)の2要因参加者内計画
全員が、2×2の計4条件を実施し、短縮版一般感情尺度に回答する。条件の実施順序は学籍番号でカウンタバランスする。実施時間は質問紙回答も含めて15~20分くらいを想定。学生はこの計画で分析する。

音声(あり・なし)×魅力的な地形(あり・なし)の2要因参加者間計画
参加者約100名を学籍番号で2×2の4群に配置する。参加者内計画の裏で参加者間計画を実施。あわよくば環境心理学会で発表。

樹木は多いほうがリラックスする。水場はあるほうがリラックスする。これは先行研究通りで、結果は固いだろう。鳥の声や水の音といった音声刺激も、リラックスに大きく寄与するとの指摘がある。また、先の見えないようなトレイルのほうが、記憶に留まりやすいというという指摘もある。探索行動を刺激するような地形は、行動を促進するのではないだろうか?

—–

懸案事項と対策状態

・テレインの複製方法がわからない。→データを複製すればできるようだ。


・どの程度のGPU負荷にして良いかわからない。そんなに木を増やせるだろうか?
→とりあえず手持ちのノートPCで検証しながらやろうか。ライトマップでできるだけ軽くしよう。できればLuxWater使いたいが・・・

・質問紙をUnityWebGL上で測りたいが、開発が間に合うだろうか?
ああWebGLサポート入れてない・・・。自然景観用の巨大アセット、WebGL変換どんだけ時間かかるだろうか。あまり多くは望めないか・・・。速い!ストレージが速いとこんなに違うのか!!

・地形を塗り分けたりするのが面倒くさい件
→VSProを使って自動塗り分けでお茶を濁すのはどうだろうか?水面付近がどうも怪しいね・・・テクスチャ変えたほうが良いかもしれない。

・行動データをとりたいが間に合うだろうか?
→これ大変だぞ!?行動データまでは無理かなぁ


で完成したのがこちら(プロジェクトCP2)。樹木(あり・なし)×水場(あり・なし)の2要因参加者内計画で、従属変数は一般感情尺度です。http://kodamalab.sakura.ne.jp/WGL/CP2/(Google Chromeを使用してください。公園CG提示中はWASDキーとマウスで移動できます。)木も水場もないと、ただの空き地だね。ポイントとしては、あえて都市部の公園という設定にした事で面積を限定し、実験刺激を作成しやすくしたこと。その分、道路や市街などの情報を足さなければならなかったが、これはこれで有りなのではないかと。遊具を置いてみたり、公園研究の将来に夢が膨らむ。

長谷川式にインスパイアされて、僕も実験刺激内で一般感情尺度を測ることにしました。

が・・・これには大きな問題が。WebGLでビルとすると、UIで日本語が入力できないらしい。マジか。内省報告とか書いてもらおうと思ってたのに・・・。ほぼ完成してから「あれ?!」とか気がつく間抜けぶりで。。。とりあえず今年の運用は諦めお蔵入りさせます。

VRコンテンツ作成入門

Quest2でのVRコンテンツ作成に関する概略
この記事は、Unityで非VRのコンテンツをある程度作成できる程度のスキルを前提にしています。

Quest2を使ってVRコンテンツを動作させる方法は2つあります。1)PCとUSBケーブルで接続して、PCのGPUを使って映像を描画する方式と、2)Quest2本体でアンドロイドアプリとして実行する方法です。それぞれ長所と短所がありますが、まずは下の動画を視聴し、1)の方法から始めるのが一般的です。

PCを使ったVRコンテンツ作成
 OculusQuest2をPCと接続して、Unityを使った簡単なVRアプリケーションを作ってみましょう。下記の動画コンテンツは、Unity2021.1.15OculusIntegrationを使いますので、事前にインストールを済ませておくとよいでしょう。また、Quest2とPCを接続する(Oculus Link)ためにUSB3ケーブルが必要です。PCは、OculusLinkに対応したGPUを搭載している必要があります。

Quest2本体を使ったVRコンテンツ作成
 OculusQuest2本体でVRコンテンツを作成するためには、いろいろ難しい側面もありますが、PCレス、ケーブルレスでVRコンテンツを実行できるアドバンテージがあります。下記動画を見ながらコンテンツを作成する際、Android build supportの使用方法や、Quest2を開発者モードにする方法などを参照すると良いでしょう。Androidアプリの動作画面を他の人に見せるためには、OculusDevelopperHUBもインストールしておくとよいでしょう。

Quest2でVRホラーを作る
 下記動画では、簡単なホラーを作成してみます。ホラーにつきもののゾンビや、怖いBGMも追加してみます。背景は、Hospital Horror Packを使います。ゾンビとアニメーションはMixamoから入手します。背景音はフリー音声素材サイトなどから、好きなものをチョイスして追加してみてください。

ハンドルコントローラを使ったコンテンツを作成する
 Oculusuには大変良くできたハンドコントローラーであるOculusTouchがついています。つかむ/はなす、指差すなどの「手を用いた動作」が、他のゲーム機などと大きく異る部分です。下記動画では、Auto Hand – VR Physics InteractionJapanese Apartmentというアセットを用い、ハンドルコントローラを用いたコンテンツの作成方法を解説します。
 AutoHandアセット内の、OculusVRというパッケージをインポートしないと、Oculus用のデモシーンがインストールされないのでご注意ください。また、TPM Importerというダイアログが出たら、importボタンを押すようにしてください。これをインポートしないと、動作が不安定になるようです。

市民憩の森 散策レポート

”市民憩いの森”に行ってきました。

学校からゆっくり歩いて帰ってきて15分~20分くらい。
広さはあまりないですが,しっかりとした土の感触,高い木々。
森林散策としては,めちゃくちゃいいと思いました。

なんだか生物の鳴き声もして,ちょっとだけ興奮できる。これはいいねポイント

これは実験に使えるじゃん!と思ったのですが。。。。。。。。。。。。。。。。。
現在,枝の落下が多発しているため,今後通行エリアが限られてしまうそうです。
なんてこった,,,,今後の経過を見守るしかなさそうですね。

FitBitマニュアルVer211017

 配布した用紙に記載されているIDとパスワードで、PCからWebメールにアクセスします(スマートフォンからだと文字が小さすぎて見えないようです)。Fitbitアカウントを登録する際に、確認メールがこのメールアドレスに送られてくるので、読めるように準備をしてから次の作業を進めてください。

 次に、スマートフォンにFitbitアプリをインストールし起動します。「Fitbitに登録」を押して、Fitbitアカウントを作成します。登録の際、IDとパスワードは配布した用紙に記載されているものを用いてください(一番上のフルネームの部分は任意の名前でOK)。Fitbitアカウントを作成したら、機種を選びます。ここでは、Charge4を選択してください。

 次にFitbitCharge4とスマートフォンをペアリングします。事前に、FitbitCharge4を充電器で充電しておきましょう。BluetoothをONにして接続する際、Charge4に表示されているパスコードを入力します。ペアリングが完了したら、「今すぐアップデート」ボタンをおして、Charge4を更新します(10分ほどかかります)。

 最後に、先ほど登録したGoogleアカウントのメールアドレスにメールがくるので、確認しましょう。これでFitbitが使えるようになりました。

DavinciResolve入門

ここでは、動画編集ソフトであるDavinciResolveについて学びます。まずはインストールして簡単な動画を作ってみましょう。

下記は、DavinciResolveを用いてCM動画を作成する手順を解説しています。作成したCM動画は、心理学の実験用に用いる事を想定しています。

ここに登録されている動画(Youtubeアップロード前のもの)は、こちらのフォルダからアクセスすることができます。

210829WS

心と皮膚温
指先の温度がストレス負荷中にどのように変化するのかを学びます。詳しくは下記動画をご覧ください。

実験刺激として用いられた動画は下記のものです。

https://www.youtube.com/watch?v=W-lVgZ-gos8

データは下記のリンクからダウンロードしてお使いください。


心と心拍・発汗
発汗や心拍数が心の状態に応じてどのように変化するのかを学びます。

実験刺激として用いられた動画は下記のものです。

https://www.youtube.com/watch?v=EjTB9RDuGLA

データは下記のリンクからダウンロードしてお使いください。

お笑い視聴時の生体反応

ウェアラブルでWifi接続式の計測器(下記は皮膚コンダクタンスと心拍数が同時に測定できるタイプ)を最大50個ほど生産し、ゲームや映画、お笑いなどのコンテンツを、多人数同時測定する仕組みを構築しています。

下図は、お笑い動画(ミルクボーイの湿布クールポコ)を視聴した際の心拍数、皮膚コンダクタンス、主観感情(PA:ポジティブ感情、NA:ネガティブ感情、CA:リラックス感情)を19名同時測定したものです。動画視聴中は心拍数の低下、皮膚コンダクタンスの上昇が認められます。主観感情変化が大きいほど、生体情報の変化も大きい事がうかがえます。


映画と皮膚温変化(公開用)

授業内で、映画を見ている際の、指先の皮膚温度変化を、20人同時に測定した事例を紹介します。実験刺激は、ミッション・インポッシブル/ゴースト・プロトコルの1シーンを用いました。主人公イーサンが、超高層ビルを登ってサーバールームに潜入し、潜入後戻ってくるまでの10分間を視聴しました。その前後に安静期を設け、前半は川の映像、後半は海の映像を、それぞれ5分間見ました。

皮膚温は、安静状態と動画視聴時の初期において上昇し、課題映像が盛り上がり始めると下降し、課題映像が終わると少し間をおいて上昇しました。動画後半の皮膚温変化は、動画の内容を鋭敏に反映しているような内容となっていました。予想以上に動画内容が反映されている印象です。

一般感情尺度(アンケート調査)による主観感情の変化を下記にグラフ化しました。映像視聴中、ネガティブ感情は大きく上昇し、リラックス感情は大きく下降していることがわかりました。

M3動画マニュアル

M3(皮膚コンダクタンス+心拍数)計測器の使い方を説明いたします。


M3計測器は、起動時にUSBポートの左右のボタンを押すことで、モードを切り替えることができます。モードはボタンを押すたびに、wifi1→wifi2→nowifi→servrと変わっていきます。Wifiの設定を変更するためには、serverモードに切り替えてPCから接続し、計測器に設定を保存する必要があります。


下記の動画では、電極を装着し、皮膚コンダクタンスと心拍数を測定し、PC側から確認する方法を説明します。M3計測器は測定した値をWifi経由でサーバーに記録します。その値を確認するためには、こちらのアドレスを表示する必要があります。


電源の切り方、充電方法に関する補足動画です。計測器を装着したまま充電を行うと、感電の危険があるのでご注意ください。また、充電中は計測器の側から離れないようにしてください。

Unityと扇風機の連動

前からアイデアとしては存在していた、Unityと扇風機の連動をとうとう実現。自分の操作に対するフィードバックがマルチモーダルに返ってきたとき、われわれはそれを現実であると認識しやすい、という知見に基づき、触覚フィードバック(つまり風)の存在意義を再確認したわけである。

風量の信号は、
Unity→(http)→Webサーバー→(http)→M5StickC→(PWM)→扇風機
の順で送られる。なぜhttpなのか。俊敏な信号を送っても、どのみちプロペラが回転し始めるのには時間がかかるし、なんといっても一番簡単だからである。

using UnityEngine;
using System.Collections;
 using UnityEngine.Networking;

public class HTTP_GET : MonoBehaviour {

    int power = 20000;

	// Use this for initialization
	void Start () {
        //StartCoroutine(GetText());
    }
	
	// Update is called once per frame
	void Update () {
        if (Input.GetKeyDown(KeyCode.Alpha0))
        {
            power = 0; StartCoroutine(GetText());
        }
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            power = 10000; StartCoroutine(GetText());
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            power = 15000; StartCoroutine(GetText());
        }
        if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            power = 20000; StartCoroutine(GetText());
        }
        if (Input.GetKeyDown(KeyCode.Alpha4))
        {
            power = 25000; StartCoroutine(GetText());
        }
    }

    public void HTTPGET() {
        //GetText();
        
    }


    IEnumerator GetText()
    {
        string url = "";
        url = "http://kodamalab.sakura.ne.jp/FAN/control.php" + "?power="+power.ToString() ;
        Debug.Log("request:"+url);

        UnityWebRequest request = UnityWebRequest.Get(url);
        // 下記でも可
        // UnityWebRequest request = new UnityWebRequest("http://example.com");
        // methodプロパティにメソッドを渡すことで任意のメソッドを利用できるようになった
        // request.method = UnityWebRequest.kHttpVerbGET;

        // リクエスト送信
        yield return request.Send();

        // 通信エラーチェック
        if (request.isNetworkError)
        {
            Debug.Log(request.error);
        }
        else
        {
            if (request.responseCode == 200)
            {
                // UTF8文字列として取得する
                string text = request.downloadHandler.text;
                Debug.Log("payload:"+text);

                // バイナリデータとして取得する
                byte[] results = request.downloadHandler.data;
            }
        }
    }
}

#include <M5StickC.h>  // ----A
#define SERIAL_BAUDRATE     115200

#define LEDC_CHANNEL_0 0 //channel max 15
#define LEDC_TIMER_BIT 16 //max 16bit
//16bitの場合、最大周波数1220Hz
#define LEDC_BASE_FREQ 1220.0 //double 1220.0Hz以下
#define GPIO_PIN 26 //GPIO #36~#39 は設定不可

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>

#define USE_SERIAL Serial

WiFiMulti wifiMulti;
int cnt=0;
String payload;

void setup() {

    USE_SERIAL.begin(115200);

    USE_SERIAL.println();
    USE_SERIAL.println();
    USE_SERIAL.println();

    for(uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(1000);
    }

    wifiMulti.addAP("HELL", "kodamamasahisa");

  //////////////
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_BIT);
  ledcAttachPin(GPIO_PIN, LEDC_CHANNEL_0);
  //16bit の場合 duty 0x0000~0xFFFF (max:65535)
  //duty 50%: 0x8000 (=32768)
  ledcWrite(LEDC_CHANNEL_0, 0x8000);

}

void loop() {
    // wait for WiFi connection
    if((wifiMulti.run() == WL_CONNECTED)) {

        HTTPClient http;

        USE_SERIAL.print("[HTTP] begin...\n");
        // configure traged server and url
        //http.begin("https://www.howsmyssl.com/a/check", ca); //HTTPS
        http.begin("http://kodamalab.sakura.ne.jp/FAN/control.php"); //HTTP

        USE_SERIAL.print("[HTTP] GET...\n");
        // start connection and send HTTP header
        int httpCode = http.GET();

        // httpCode will be negative on error
        if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                payload = http.getString();
                USE_SERIAL.println(payload);
            }
        } else {
            USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }

        http.end();
    }

    //delay(5000);

    int power;
    power=payload.toInt();
    ledcWrite(LEDC_CHANNEL_0, power);
    Serial.printf("PWM:%d \n", power);
    delay(2000);      

    cnt++;
}

液晶画面に風速を表示

VR教室体験動画

研究にご協力ください。お願いします!

 

動画1.アトリウム

アトリウム360度動画をみる

アトリウムの動画の印象を回答する

動画2.教室

教室の360度動画をみる

教室の動画の印象を回答する

動画3.食堂

食堂の360度動画をみる

食堂の動画の印象を回答する

動画4.オフィス

オフィスの360度動画をみる

オフィスの動画の印象を回答する

動画5.教室2

教室2の動画の印象をみる

教室2の動画の印象を回答する

必要事項

こちらに入力してください

FitBitマニュアル

 配布した用紙に記載されているIDとパスワードで、スマートフォンに新しいgメールアカウントを登録します。このメールアカウントは、FitBitアプリの最終確認に必要になります。iPhoneの場合、「設定」の「メール」からアカウントの作成ができます。

 次に、Fitbitアプリをインストールし起動します。「Fitbitに登録」を押して、Fitbitアカウントを作成します。登録の際、IDとパスワードは配布した用紙に記載されているものを用いてください(一番上のフルネームの部分は任意の名前でOK)。Fitbitアカウントを作成したら、機種を選びます。ここでは、Charge4を選択してください。

 次にFitbitCharge4とスマートフォンをペアリングします。事前に、FitbitCharge4を充電器で充電しておきましょう。BluetoothをONにして接続する際、Charge4に表示されているパスコードを入力します。ペアリングが完了したら、「今すぐアップデート」ボタンをおして、Charge4を更新します(10分ほどかかります)。

 最後に、先ほど登録したGoogleアカウントのメールアドレスにメールがくるので、確認しましょう。これでFitbitが使えるようになりました。

FitBit/Python210622

今日は、自分の心拍数25日分(5/28~6/21)で分析をしてみる。まずは、授業日と非授業日の比較から。

就寝中は案外差がないように見受けられる。活動時間帯は、やはり全般的に授業日が高いように見える。特に、9時付近、14~16時、19~21時あたりで授業日vs非授業日の差がついているように見える。14~16時は授業だろう。月曜日は専門演習、金曜日は生理心理学実験がある。9時付近は授業準備だろうか?間に合わなくて朝やることもある。19~21時はタイ料理のせいだろうか。とりあえず授業中頑張っている事がわかったので良かった。次は、土曜日,日曜日,全体平均の比較だ。

土曜日の就寝中心拍数が低い。一方で日曜日の深夜は全体平均より高い。日曜日に大学でまとめて仕事をするせいだろうか・・・。日曜部の8~10時が低いのは、自動車に乗っていないからだと思う(残りの日は全部車を運転している・・・)。土曜日は全体的に平均より低いように見えるが、なんとも言えない。

思えば自分は「土日しっかり休む」タイプの生活ではなく、休みが広く浅く分散しているような生活スタイルだ。平日と土日のコントラストがハッキリしているような生活の人だと、より明確に差が現れるのかもしれない。

import sys
import fitbit
import gather_keys_oauth2 as Oauth2
from datetime import datetime, date, timedelta
 
print('Hello FitbitAPP4') 
 
USER_ID     = ""
CLIENT_SECRET = ""
 
def requestFitbit(DATE):
    rval=""
    global auth2_client

    fitbit_stats = auth2_client.intraday_time_series('activities/heart', DATE, detail_level='1min')
    HRstats = fitbit_stats['activities-heart-intraday']['dataset']
   
    OUTPUT_FILE = "ALL.csv"
    csv_file = open(OUTPUT_FILE, 'a')
    csv_file.write(DATE+",")
    for var in range(0, len(HRstats)):
        csv_file.write(str(HRstats[var]['value']))
        csv_file.write(",")

    csv_file.write("\n")
    csv_file.close()

    return rval
##################################################

"""Get tokens"""
server = Oauth2.OAuth2Server(USER_ID, CLIENT_SECRET)
server.browser_authorize()
ACCESS_TOKEN = str(server.fitbit.client.session.token['access_token'])
REFRESH_TOKEN = str(server.fitbit.client.session.token['refresh_token'])
 
#print(ACCESS_TOKEN)  
#print(REFRESH_TOKEN)

"""Authorization"""
auth2_client = fitbit.Fitbit(USER_ID, CLIENT_SECRET, oauth2=True, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN)
 
"""request"""
#DATE = "2021-06-19"
#today = datetime.today()
#requestFitbit(datetime.strftime(today, '%Y-%m-%d'))
#requestFitbit("2021-06-19")

today = datetime.today()
for var in range(0, 26):
    #day=today + timedelta(days=1)
    #print(var+":" + datetime.strftime(yesterday, '%Y-%m-%d'))
    stamp=datetime.strftime(today - timedelta(days=var), '%Y-%m-%d')
    print("target: " + stamp)
    requestFitbit(stamp)

24*60=1440サンプルあるはずが、日によって少し足りなかったりする。サンプル出来ていない時間帯がツメられてしまっているものと思う。正しく計算するには、タイムスタンプも反映させながらワークシートを作成する必要がありそうだ・・・。
 自宅でFitbitAPIにアクセスしようとしてハマった。途中で心が折れそうになるが、どうにか原因を特定、プログラムの改造にこぎつけた。注意点は下記の3つ。

1.自宅および主要ノートPCはポート8080を何かで使っているらしい。Application登録時のRedirect URLを8088に変更したら動作するようになった。これどういう意味があるんだろう?

2.Tokenは発行されるのにHRなどの計測値が落ちてこない・・・これは、ApplicationのOAuth 2.0 Application Type をPersonalにし忘れていたことが原因。

3.途中で「fitbit.exceptions.HTTPTooManyRequests: Too Many Requests」なるエラーが出て、一切リクエストができなくなる。リクエスト回数に制限があるらしい。これはアプリケーションを新たに登録してIDとSECRETを取得することで回避できた。

美術館実験210620

栗山さんと大野田くんのために、美術館スタイルの実験刺激作成がスタートする。まずは栗山さんバージョンを意識し、作り込んで見る。

・ライトマップをベイクするのに手こずる。
・画像はすべてPrefabをUnwrapする。でないと一部だけグレーになる。
・壁のマテリアルの明るさを変える。
・Lightning設定からAmbientLightの設定を暗めにする。
・PointLight/SpotLightの明るさを変える。

などを繰り返し調整し、ベイクしまくった結果が以下のものである。今日はこのあたりで許してもらおう。どの刺激の側にいて、どこを見ていたのか、が記録できるようにしないといけないんだけど。。。

美術館形式実験210620