# history & comment CHANGELOG.md とほぼ同等の history ログ。 どちらかというと slack にあげた update log をここに書く。 手探りで開発しているために、特にロボットの仕様で普段使ってないものが、 実は重要だったケースなどがのちに見つかる(ただし、ほとんど実用上は影響がない場合がほとんど) など。割と苦闘の歴史が山積してます。 ## 2026.05.13 主要モジュールをアップデートしました。 一応テスト済みです。 ese774_frame-v0.4.20 https://github.com/ohara-lab-su/ese774_frame/archive/refs/tags/v0.4.20.zip cobotta2-v0.13.8 https://github.com/ohara-lab-su/cobotta2/archive/refs/tags/v0.13.8.zip aandd_reader-v0.2.11 https://github.com/ohara-lab-su/aandd_reader/archive/refs/tags/v0.2.11.zip --- [注意] ese774_frame を v0.4.20 以降にしてから、それぞれ導入してください。 --- [変わること] 前までと同じ使い方はそのままできます(後方互換) スサノオで使われるフレームは全て透過型です、それを明確に使えるように、DeviceProxy 形を導入しました。従来の専用クライアント型(中身は透過)でも使えます。 メリット それぞれのデバイスクラスを明示的に使えること Async と Async でごちゃごちゃとわかりにくくなるのを防ぐ 透過型の通信を行なっていることが明示的になるため、機器態(サーバ)と制御クライアントの区別が明確 割と世界標準的な書き方(デバイスクラスとデバイスプロキシという思想で整理する) Registry + Factory デザインパーンで整理(世界標準) 新書式 ```python config = Config("cobotta1_server1.yaml") client = DeviceProxy("CobottaCtrl", config=config, async_mode=True,,,,)デフォルトは async_mode=True です ``` 旧書式(async) ```python config = Config("cobotta1_server1.yaml") client = AsyncCobottaCtrl(config=config,,,,,) ``` 新書式(sync) ```python config = Config("cobotta1_server1.yaml") client = DeviceProxy("CobottaCtrl", config=config, async_mde=False,,,,) ``` そのほかのオプションは同じです。 DeviceProxy は たとえば、AanddReader デバイスクラスを透過的に使うときは、新書式ならば 新書式 ```python config_reader = Config("aandd1_server1.yaml") reader = DeviceProxy("AandReader", config=config_reader, async_mode=True,,,,) config_cobotta = Config("cobotta1_server1.yaml") cobotta = DeviceProxy("CobottaCtrl", config=config_reader, async_mode=True,,,,) ``` などと言う形で纏まります。 ## 2026.05.12 cobotta2-v0.13.7 リリースいたしました。 https://github.com/ohara-lab-su/cobotta2/archive/refs/tags/v0.13.7.zip https://ohara-lab-su.github.io/cobotta2/ ・各I/Fレイヤー間のアノテーション不一致などの調整 ・コードの中も互換性(bcap/orin2)調整 ・散らばっていた環境のまとめなおし。 ・bcap/orin2 モードの互換性向上 展開後の cobtta2/tests/fastapi/async にテストプログラムをまとめております 現時点では --- ほぼ再テスト終了したもの - angle - autucal - busy - drive - error_code - get_bstrOpt (未使用) - get_cobotta_file_name - get_cord_type - get_P - get_path_blaned - get_position - get_speed - hand - init_hand - is_empty_position - move_fig - move_J - offset - P - p2j - release_arm - reset - set_P - speed - status - stop - rotate - rotate_H 廃止 - pacscrpt の run (bcap-mode) - バグを修正 - save_load ---- orin2/bcap にて少し前のバージョン 0.13.3 あたりで、実用的に使っていたものですがテストプログラムとしては一抹の不安があるもの - camera ---- まだ最新版では未テストだが、原理的にあまり影響ないと思われるもの(使用頻度もほぼない) - log ---- 使用頻度がないせいでテストしにくくて棚上げ状態のもの 座標系を取り直すなどのワーク座標系関係。 まだ本格運用で使ってないのと、ダイレクトティーチングする場合は あまり使い所がないため。後回し。 - work ---- 項目が多くてテストが少し足りてない あまりにも多機能で作ったために、 バージョンアップ頻度が高いために、機能のテストが追いついていないもの。 - move (一部のオプション) ## 2026.04.28 cobotta2 v0.13.3 リリースしました。 https://github.com/ohara-lab-su/cobotta2/archive/refs/tags/v0.13.3.zip git(https://github.com/ohara-lab-su/cobotta2) 基本は、バグfixおよび、test コードの再整備 これまで、機能拡張を行ったり、 方針が変わったり、ロボットの数が変わったりしたことにって、 機能しなくなっていたテスト系コード。 そららを動くようにした再整備・再調整と元コード(bcap/orin2/RestAPI通信)での動作コードです。 cobotta を使うときには、これらのコード https://github.com/ohara-lab-su/cobotta2/tree/main/tests 以下にある fastapi local 以下を参照してください。 fastapi は SPring-8 互換の通信を用いた使い方とテスト用の最小セット構成を それぞれの機能ごとに用意してます。 local は通信を使わずに直接 cobotta を使うテストです。 コボッタ自身の制御プログラム(のバグやつ方間違いで)コボッタが動かない 通信が原因でコボッタが動かないか? これらの問題を切り分けるのに使います。 もしくはコボッタ自身の機能(普段自分たちが使ったことのない使い方・高度な機能) などのチュートリアルも兼ねてます。 ## 2026.04.28 ロボット衝突時の復旧に関して 軽微な衝突であれば、 現在のシステムにおいては、 stop() などの命令の後に、 take_arm() turn_on_motor() にて通常制御に戻れるようにしています しかし、復旧してもまたすぐにエラーが起ききることがあります。 この場合は、 ・motor を off にするか ・非常停止ボタンを押すか 後に、Free モードに移動して復旧しないと復旧できません。 軽微な衝突の時のようにソフトウエアだけで復旧しないのか? と思いデンソーウェーブに問い合わせました。 衝突量が大きく、衝突点でロボットに継続的な外力が加わっている場合には、 モータを投入すると直ちに衝突検知となるため、移動命令を実行できません。 この状態でモータ駆動による復旧を許可すると、 機構や周辺装置を損傷するおそれがあるため、ロボットは安全設計上、駆動を抑止します。 そのため、外力が残っている衝突状態では、 フリーモードで拘束を解除するなどの手作業が必要となります。 この手作業は制御上の制限ではなく、安全確保のために不可欠な仕様です。 恐れ入りますが、ソフトウェアのみで常に代替できるものではありません。 何卒ご理解賜りますようお願いいたします。 つまり復旧は現在我々が理解している方法以外存在しないようです。 たとえば、 バイヤル瓶にゴムのキャップをつける動作などで、 キャップの上面をロボットで叩くなどのモーションをすると、 ロボットからの異常を検知して止まってしまうことがあります。 この場合は全ての動作を一旦止めて、手動でロボットを復旧しないといけません。 今の所の study では、 目標ターゲットから 5mm くらいまでは力の異常が出ないので押せることは大体わかりました(ターゲットまでの距離とpath_blend値で速度が変わりますので力が変わるので一概に言えませんが。数ミリは大丈夫でした。 ## 2026.04.21 ご存知の通り、ロボットの座標指定には以下の2種類があります。 P座標系 (x, y, z, rx, ry, rz) J座標系 (J1, J2, …, J6) 1つの P 座標に対して、それを実現する J 座標の取り方は複数存在します。 この「ロボットの形態(関節構成)」を指定する追加情報が多くのロボットに用意されていますが、 その表現方法はメーカごとに異なります。 P 座標が同一であっても、この形態情報によりロボットの取り得る姿勢が変化するため、 同じ座標でも移動できる場合とできない場合が生じます。 デンソーウェーブの場合、 位置姿勢の6要素に加え、 ロボット姿勢を識別する情報として動作形態 (Fig) が定義されています。 P座標系では Fig を7軸目として扱います。 これまで、スサノオを用いたロボットのデバイスサーバーでは、P座標系を [x, y, z, rx, ry, rz, option] という6軸+1軸の形式で扱っています。 get_current_position() や get_P(xx) の戻り値も7軸で返しており、現状はロボットネイティブ仕様を優先しています(将来的に他社ロボットが増えた場合は変更の可能性があります)。 紛らわしい点として、J座標系ではコボッタは J1–J6 を使用しますが、デンソーのソフトウェア上は J7, J8 が定義されており未使用となっています。一方、P座標系の7軸目は未使用軸ではなく Fig という姿勢識別情報です。 一方、現在のプログラムでは move() や set_P() に座標を与えた場合、6軸を超える入力があっても最後の1軸 (Fig) を -1 に固定、もしくは無視して6軸化していました。 そのため現状では A) 内部P座標が Fig 情報を含めて移動する場合 B) 座標指定移動が Fig 情報を使用せず (-1固定) に移動する場合 の2パターンが存在します。 その結果、 A) P指定移動では移動できない(ロボットが保持している Fig を使用) B) 座標指定移動では移動できる(Fig を使用しない) という挙動が発生します。 [17:18]他社で Fig に相当する概念としては デンソー: Fig (動作形態番号) テックマン: Pose / Config UR: qNear などの複数解選択パラメータ(どの関節解に近いか) FANUC: config YASKAWA: 形態 (form) などがあります。 move 実行時にはこれらの姿勢情報を指定できる必要があると考えています。 config という名称は意味範囲が広く衝突しやすいため、 ik_config なども検討しています。 ik は Inverse Kinematics(逆運動学)の略で、 fk (forward kinematics) と対になる一般的な用語です。 一方でテックマンの pose という用語も簡潔で分かりやすく、 デンソーの fig より直感的に感じます。 ただしP座標系を扱う以上、pose を返すこと自体は自然であり、 6軸+pose の7軸形式とするデンソー方式も一定の合理性があります。 現在の仕様方針は以下です。 7軸で入力した場合は7軸目を pose (fig) として扱う オプション指定がある場合はオプションを優先する move([6軸], pose=xxx) (新オプション) move([7軸list or 6軸list]) (従来拡張仕様) move(P10) (内部 Fig 情報を使用、現在のオプション) 現時点では pose はデンソーの Fig に対応する int 値を使用します。 6軸で入力した場合はfigは-1とします(現在) 当面は move 系APIのみ対応します。 最終的な仕様は他社実装を確認した上で再整備予定ですが、 おそらく pose 専用クラスを用意して対応する形になります。 以上の方針で現在プログラムを改修中です。 しばらく安定フェーズからは外れると思いますが。 0.12.x 系を現在のバージョンブランチとしてそのままにして、 0.13.xx からは上記シン仕様にする予定です。 ## 2026.04.21 cobotta2 v0.13.0 https://github.com/ohara-lab-su/cobotta2/archive/refs/tags/v0.13.0.zip 暫定ですがリリースしました。かなり改変したのバグが残っている可能性はありますが、 最低限のテストはしてます。 主な改変内容は以下です。 基本的には前と同じで動作しますが、 今まで、座標指定P動作(6軸)のときに、 完全に捨てていたpose情報(1軸) の7軸目を直接取り扱うことができる様にしました。 6軸入力では今までと同じ7軸目を使わない動作。 get系の戻り値では今まで同じく7軸情報入手 6軸入力+ pose オプション 動作 予定としては次のバージョンでは、 pose オプションでの LEFT/FLIP などのロボット形態を指定しての、 move を可能にする様にします。 今は、デンソーが指定する番号を入れます。 https://www.fa-manuals.denso-wave.com/jp/CVRover202508/006995/ hand で speed オプションをなしで動かした時に、正しく動かない問題 - bcap における speed 系のset/getを修正(主に初期化に関して) - bcap における client 系の speed/jspeed/accel/decel のバグ修正 ## 2026.04.20 v0.13.0, nakada ### 改修目的 pose 系 I/F の追加と、P 座標 7要素目の扱い修正。 対象は move 系。 ### 上位 I/F - cobotta_ctrl.py の active な上位 I/F は move() と dev()。 - CobottaCtrl.move() は pose 系 I/F の対象なので pose を追加し、下位 move() に渡す。 - CobottaCtrl.dev() は 6軸 offset 演算なので pose を追加しない。 ### FastAPI - MoveRequest には pose を追加する。 - MoveXRequest は現行 spec に move_P/L/C/S が残っているので、 - モデル整合として pose を追加する。 - ただしこれは CobottaCtrl のコメントアウト済み wrapper を復活させる意味ではない。 - spec_ctrl.py の dev は現状 ApproachRequest になっていて明確に誤りなので DevRequest に直す。 ### target と pose - move([6軸]) は従来通り P 座標 6軸として扱う。 - move([6軸], pose=xxx) は 7要素目を xxx にした P 座標として扱う。 - move([7軸]) は 7要素目を pose/fig として扱う。 - move([7軸], pose=xxx) は 8要素に追加しない。7要素目を xxx に置換する。 - move("P10") は文字列指定なので pose 解釈を入れない。内部 P 番号の fig 情報を使う既存経路のまま。 - move("P10+(...)") も文字列構文なので pose 解釈を入れない。 ### offset - offset は P 座標 6軸の dev 演算。P番号指定でも有効。 - move("P10", offset=...) は dev("P10", offset) 経路。文字列 target に pose 解釈を入れない。 - move([6軸 or 7軸], offset=...) は dev に渡す基準座標は 6軸。offset は 7軸目を変更しない。dev 結果は P 座標として move target にするが、offset 自体に pose を混ぜない。 ### ORiN2 / b-CAP - ORiN2 と b-CAP の支援関数名を揃える。 - _make_vnt_pose() / _build_move_target() は分かりにくいので、 両方とも _make_move_target() に寄せる。 - _to_pose_string() は dev/offset 用の 6軸 P 文字列化。pose 用にしない。 - _make_offset_pose() は "P10+(...)" 文字列構文用。pose 解釈を入れない。 - raise TypeError は使わず、失敗は False を返す。呼び出し側も False を判定して伝播する。 ## 2026.04.17 study により、新たな知見が得られました。 例えば、ある内部座標 P10 が特異点近傍にある場合、 移動不可: ある原点 → move(P10) 移動可: pos = P10 の座標リスト ある原点 → move(pos) という現象が確認されました。 座標系を積極的に利用する画像認識処理において判明したものです。 本件についてはサーバー側プログラムのバグではないことを確認済みであり、 デンソーウェーブへの問い合わせを含めて調査しました。 その結果、ロボット座標系の指定には追加オプションが存在することが分かりました。 また、ユニバーサルロボットやテックマンロボットなど 他社ロボットにも同様の概念があることを確認しており、現在対応を進めています。 ## 2026.04.16 cobotta2-0.12.6 リリースしました。 内部座標が未使用かどうか確認するメソッドを追加しました is_empty_position(position)未使用ならば True を返します。 たとえば、以下のようなスクリプトで未使用の内部変数領域に今の位置をティーチングできます ```python START_ID = 100 END_ID = 200 for id_num in range(START_ID, END_ID + 1): if client.is_empty_position(id_num, coord_type="P"): pos = await client.get_current_position() await client.set_P(id_num, pos) logger.info(f"learned current position -> P{id_num}") logger.info(pos) breakZip ``` ## 2026.04.10 cobotta2 v0.12.4 リリースしました。 camera関係を試してもらっている都合、bcap に切り替えたことによる不都合の洗い出しができました。 そのための様々なアップデート対応です。 全ての制御サーバーを入れ替えてますので、frame側のupdateと合わせて修正してください。 bcap利用でのpacscript/camera 関係のmethodを利用できる様にした orin2利用でのtake_camera/take_script 関係の方針変更して安定化(毎回ハンドルのrelase/add) ctrl(I/F) / bcap(backend) / orin2(backend) の調整 package 中のsampleスクリプトの整理 ## 2026.04.08 cobotta-0.12.3 ese774_frame-0.4.19 をリリースしました。 秤量コードのレベルで、bcapバックエンドが動く様になりました。動作確認済み。 まだ一部機能が不完全ですが、秤量コードの範囲で互換性があるので、 問題なく使えると思います。 http側(ese774側のタイムアウトは) 先に導入した set_timeout() メソッドを使わなくても、 とりあえず 60sec まではデフォルトtimeoutを伸ばしました。 そこそこ安心して、blocking 処理ができると思います。 60sec を超えるときは set_timeout() をご利用ください。 なお bcapでのソケット通信側の timeout は 2000sec です。 おそらくそこまで長いblocking処理はしないと思いますが、 http側とロボット基本制御側(bcap側)のタイムアウトが起きるときはこの二つを疑ってください。 ## 2026.04.08 ティーティングにおいて、デンソーウェーブのアプリを使わずに、ティーチングもできる様にしてます。 現在の位置を P110 に保存する場合は ```python new_pos = await client.get_current_position() client.P110 = new_pos ``` もしくは ```python new_pos = await client.get_current_position() await client.set_P(110, new_pos)の方法があります。プログラム上使いやすい方で使ってください。110 などの番号自体を変数にしたい場合はプロパティで呼ぶよりは、メソッドで読んだ方が便利です。 ``` ティーチングにアームを動かす場合は、 ダイレクトモードにして手で動かす方法と、 ゲームのジョイパッドをつかって、アームを動かす方法があります。 パッドを使って動かせば、完全にデンソーのソフトを使わない運用も可能です。 なお、用意している全てのメソッドには、成功か失敗か?の戻り値を用意してます。 グロボの中やハッチの中での運用となると、 デンソーのソフトを使わない(ロボット上の物理ボタンを使わない)運用が大事になると思います ## 2026.04.08 cobottaのエラーについて cobotta で何か衝突した時に、エラーリセットしても コボッタが動き続けるためにエラーが解消できないことがよくあります。 これの根本的原因が一つ判明しました。 コボッタ制御プログラムの使い方の問題です。 ```python await client.move("P10") await client.move("P11") ``` などとしていると思います。 このとき、move("P10") が衝突のために、 正常終了してないのに move("P11")の命令が実行されてしまいます。 この移動命令などは、次々と実行されます。 これがトラブル時に問題になります。 このときは、いつもは省略していますが move() の戻り値の bool 値で判断してください。 github の cobotta_client にも書いておりますが sample においてあるスクリプトでは たとえば以下の様になっています ```python ret = await client.move("P10") if not ret: error_description = await client.error_description() print(error_description) exit() ret = await client.move("P11") ``` などとすると、P10が以上終了した時に、P11 の移動命令に行きません。 そして、なぜエラーで止まった?というエラー状況を説明してくれる画面を表示します。 エラーが起きた時のロボットのエラー表示を、python だけで行うことができます。 デンソー側のソフトを立ち上げる必要なくエラーを判別できます。 エラーリセットはよく使っていると思いますが、 await client.reset_error() にて行えます。 ## 2026.04.07 ese774_frame 0.4.18 cobotta 0.12.1 主にjopad機能(gRPC)/cobotta機能(FastAPI[bcap, ORiN])のシームレスな連携用の準備 長いロボット動作の時にサーバーがタイムアウトする問題 クライアント側でtimeout時間設定できる機能を追加 client.set_timeout(30) 30秒の間タイムアウトしない autocal機能の本格実装 これまで、cobotta 電源 off / on でしか、キャリブレーション呼び出しができなかったのをプログラム起動できる様にした。(グロボの中やハッチの中では必須の機能) frame 側と cobotta 側 および clinet 側のどちらのアップデートも必要です。 ## 2026.03.27 バックエンドが b-cap 版と ORiN2 を簡単に切り替えられる様に b-cap 版の機能をORiN2版の機能に合わせる形で拡張 しました。v0.11.1 take_arm/reset_error/get_error_count.....エラー関係/move/ など最低限の動作は確認 python 3.7 互換性向上 drive命令/rotate命令 が option拡張ともに使えなくなっていたのを発見・修正 ```python server = FastApiServer( device_cls=CobottaCtrl, # 制御クラス router_cls=CobottaRouterCtrl, # routerクラス config=Config, api_spec=cobotta_ctrl_api_spec, device_kwargs={ "cobotta_ip": Config.COBOTTA_IP, "backend": "bcap", # "backend": "orin2", }, # COBOTTA制御Classのコンストラクタ引数) logger=logger, logger_name=Config.SERVER_LOGGER_NAME, # LOGGER_NAME lifespan_msg_prefix="COBOTTA", ) server.run(host=Config.SERVER_IP, port=Config.SERVER_PORT)サーバー起動時に device_kwargs の backend キーで orin2 と bcap を切り変えます。 ``` bcap 版だと、制限があった autocal() 機能が、cobotta のモードに関係なく立ち上げられます。 つまり、cobotta の電源を落とさなくて autocal できる様になりました。Zip ## 2026.03.26 検出器対応ための、venv ではなくグローバルに python 3.7 対応化するために、修正 (以前は python 3.11以降対応が基本としていたが、今回は古いpython対応した) cobotta2 v0.10.9 ese774_frame v0.4.16(編集済み) ## 2026.03.26 v0.10.8, cobottaのデバイスサーバーの重要なバグを修正(ORiN2) 内容: ・offset が int 強制をfloat化に修正 ORiN2のdev の P変数仕様を [in] を int と勘違いしてしまっていた。 (私のデバイスサーバーではoffsetは内部でdevを使って座標計算する様にしているため)