{}, object, Objectの違い@TypeScript

TypeScriptはその名の通り、基本的に型を厳密に定義しないといけませんが、タイトルの通り似たような三つのオブジェクト定義が存在します。その性質の違いを見るのが以下のコードです。

// object, Object and {}
let o1: {}
let o2: object
let o3: Object  // Object is an interface

o1 = {a: 2} // object
o1 = 123    // primitive

o2 = {a: 2}
//o2 = 123  // primitive is not usable

o3 = {a: 2}
o3 = 123

o1 = {toString() {return 1}}    // accept any type of object
//o3 = {toString() {return 1}}    // treat o3 as a string type which is a predefined type

・{}, Object : オブジェクトもプリミティブも代入可能

・object : オブジェクトのみ代入可能

実はObjectはインターフェースであると、またTypeScriptではプリミティブ以外は全てオブジェクトです。

オブジェクトの定義方法としては、

オブジェクトとプリミティブの分離のためと思いますが、

let o0: {a: 1}のようなオブジェクトそのものを定義、もしくはobjectを使うのが推奨されています。

 

admin

type unknown@TypeScript

TypeScript読み始めて、型にanyがあるのは例えばGolangの構造体にもanyがあるから、まあそうかなと思いますがunknownというのは目新しい。

以下、unknown type説明用のコードですが、unknownでも限定的な演算子はサポートしていて例えば’===’はサポートされていますが、’+’演算子に対してはまさしくunknown扱いでコンパイルエラー(VScodeなので赤アンダーライン)になります。

typeofで型を特定してやればこの例ではnumberとして扱うことができています。

以下の実行結果で違いがわかります。

// unknown type 
let aa: unknown = 10    // type safe 'any'
let cc = aa === 10      // === is usable
console.log(cc)

//let dd = aa + 20      // -> cause error
if (typeof aa === 'number'){
    let dd = aa + 20
    console.log(dd)
}


// any type
let aaa: any = 10    // type safe 'any'
let ccc = aa === 10
console.log(ccc)

let ddd = aaa + 20
ddd = aaa + 20
console.log(ddd)

<results>

% ts-node "./hello.ts"
true
30
true
30

anyは文字通りどのような型であっても設定できますが、unknownは型の特定(annotation)が必要にされる場合があるところがanyとの違いです。故にunknownはtypesafe anyと呼ばれるようです。

この辺りの仕様は最近の言語仕様だと感じるところです。

P.S. 2023/6/13 unknownの補足

unknownは型の特定が必要ということで、もしunknownの変数を扱う場合には、例えばtypeofで型の絞り込みを行えば、TypeScriptがその型を認識してくれて処理ができます。以下、unknown型をnumber型として絞り込んで処理しています。

// type of unknown
let hh: unknown = 10
if (typeof hh === "number"){
    let hh_m = hh * 3
    console.log(hh_m)
}

 

admin

TypeScriptの概要本

TypeScriptについて一通り知るべき内容が記載されている書籍だろうと思います。

発行が2020年なのでTypeScript 3.0準拠でしょうが、4.0では大きな変更はないとのことなので差分を意識すれば十分使えるでしょう。

 

admin

 

AppleScript

初めて知りましたが、MacでAppleのスクリプト言語(OSA : open scripting architecture対応)を使えばJavaScriptの実行も呼び出せるということ。

例えば、以下のようなhello.jsファイルを実行するには、

let helloWorld = "Hello World";

console.log(helloWorld);

----------------------------------
% osascript -l JavaScript hello.js
Hello World

のように呼び出せます。一番簡単に使えるJavaScriptの実行環境になるかと思います。もちろんDOMなどの呼び出しはできませんが。

osascriptのコマンド使用方法は、

https://support.moonpoint.com/os/os-x/man/man_osascript.html

node.jsがインストールされていれば、その環境で実行するのが一番確実ではありますが。

 

admin

micro:bitのカスタムブロックを作る

以下を参照に一番簡単に作れるであろう、出来合いの拡張ブロックを動かしてみた。

https://qiita.com/tkyko13/items/081b8759ed98f6ed577d

手順はリンクの通りですが、普通にGitHubに上げることもできるので共有(全体になるので、ブロックを部品としては扱えない)もできます。

内部的にはブロックはおそらくStatic TypeScriptに変換され、さらにJavaScript、そしてマシンコードに落とされてhexファイルが作成されて、それをmicro:bitに転送すれば実行されるという流れになります。

Type Script(Java Script)のコードは適当なドキュメントが存在しない(見つけられないだけ)ようなので、ブロックからJavaScriptのコードを拾い出して使うしかなさそう。

 

admin

 

 

 

micro:bitの拡張機のでライントレース時のログを取ってみた

pxt-microbitを調べている間に、すでに拡張機能でmicro:bit内蔵のFlashにログが取れる機能があることを知りました。で画像下の黒ラインをトレースさせた結果のログを取ってみると、

こんな感じで画像化できました。ログデータはmicro:bitディレクトリから見えるMY_DATA.HTMをダウンロードするとcsvファイルなのでnumbersで加工。ログをクリアする処理を処理の初期化で入れてしまうと、ログを取ろうとすると中身が消えてしまうので追記型にしています。

ログの対象はモーター駆動パワーと、ラインセンサーのフォトトランジスタ電圧をAD変換したもの。駆動パワーが130を超えている部分はラインを逸脱しそうになって右回転あるいは左回転を実行している部分です。

グラフ化してみると概ねイメージと合っていますが、データをビジアル化してみるのは理解が早まると思います。

今現在のコードは、

https://github.com/chateight/trace_microbit

P.S. 2023/6/14

フラッシュメモリへのログは予想以上に時間がかかっていて、ループ時間のおよそ30msは大半がログのための時間のようです

 

admin

 

 

 

makecode for microbit

makecodeのうちでmicrobit用のバージョンがmake code for microbitになります。pxtという言葉も出てきますが、makecodeというのは目に見える画面エディタのことで、pxtはmakecodeを動かすためのGitHubのリソースのことだという記述があります。

https://github.com/microsoft/pxt-microbit

にmicrobit用のpxtリソースが存在しますが、このpxtリソースでできることは、

① makecode for microbitをローカルサーバーで動かす

② ローカルで開発環境を構築

の二つだと思います。

手順通り動かしてみると、ローカルでmakecode for microbitが立ち上がりました。

大半はTypeScriptで拡張機能が実現できそうですが、ハードウェアを扱うときにはC++も必要になるでしょう。

 

admin

Static TypeScriptはmakecode for microbitの拡張機能作成で使われる

makecodeはマイクロソフトが開発したオープンソースでユーザ側が自由に拡張できますが、その元になっている仕組みを調べ始め。ネット上には情報が少ないですが、

きっかけは、

https://interface.cqpub.co.jp/magazine/202202/

ですが、雑誌というのは決まった分量に収めないといけないので、行間が省略されているので、雑誌のテキストだけではよく理解できないので自分なりに理解のための整理。

makecodeで何ができるのか?

開発がマイクロソフトなので、① Arcade、② micro:bit、③ Minecraftができるということです。

makecodeの開発言語はStatic TypeScript、なぜStaticなのかというとメモリの少ないマイコンでJavaScriptの動作環境は用意できないからネーティブのコードに変換する、つまりJavaScriptが持つDynamicな機能は削除されたTypeScriptのサブセットなのでStaticという名前がつけられています。実はmakecodeの開発環境にはTypeScipt以外にBlocksとStatic Pythonも使われている(BlocksとStatic Pythonはコンパイル時にTypeScriptに変換される)ようです。Blockは” Blocks is implemented using Google Blockly.“だそうですが、ScratchもGoogle Blocklyを使っています。

<makecode用の言語についてのリンク>

https://makecode.com/language

一方pxtはStatic TypeScriptコンパイルの実行環境。

<pxtについてのリンク>

https://github.com/Microsoft/pxt

pxtの実行環境には三種類あるそうですが、

“PXT programs are executed in at least three different environments: microcontrollers, with native code compilation (ARM) browsers * server-side JavaScript engines (node.js, etc)”

実際的にはnode.jsを使うのが一番ポピュラーでしょう。

 

admin

 

Docker割り当てリソースの設定

VScode起動時にDockerも起動されるようになっているので、その都度8GBも消費するのは無駄だろうから割り当てを変えます。実メモリ16GBでDockerに8GB割り当ててしまうと、状況によってはメモリプレッシャがwarningレベルになります。4GBあれば当面十分だろうからDockerの設定画面で変更。

アクティビティモニターで見ると、

割り当てサイズが変更されました。

 

admin

 

倒立振子のループ時間が変わるとパラメータも修正必要

以下で作成した倒立振子、

https://isehara-3lv.sakura.ne.jp/blog/2022/12/30/倒立振子(pi制御でハンチングなくした)/

Wi-Fi環境無いところのために、Wi-Fi関連の処理(Pose情報をudpで送信)を削除すると、PIDパラメータの最適値が変わってきます。

モーターの駆動力を計算しているところをloop処理から切り出すと以下のような処理ですが、

  // calc motor power
  float Duty, P, D, now, dt, Time;
  now = TARGET - roll_data;    // calc delta
  if (-25 < now && now < 25) { if (abs(now) >= 0){
      Time = micros();
      dt = (Time - preTime)/1000000;
      preTime = Time;
      P = now/90; // (-90~90) → (-1.0~1.0)
      I += P*dt;
      D = (P - preP)/dt;
      preP = P;
      power = P_val * P + I_val * I + D_val * D;
      //Serial.println(power);
      if (power < -1) power = -1;    // limit the max value
      if (1 < power)  power = 1; 
      if (power < 0){
        dir = 1;
      }else{
        dir = -1;
        }               // set forward/reverse
    }

時間で正規化されてるわけでも無いから、powerの値そのものが変動してしまうからでしょう。

電池電圧変動でも同じpower指定しても実際のモーター駆動力は変化して、調整点がズレるのと似ていると言えば似ているかもしれません。

 

admin