C++ ときどき ごはん、わりとてぃーぶれいく☆

Wonder Rabbit Projectのなかのひとのブログ。主にC++。

.net の System.Xml.Linq の XDocument/XElement で Element/Elements メソッドの挙動が意図せず null になったり空になったり、あるいはそもそも名前空間を与えたつもりの実装で例外が飛んだりした時に思い出すため、のメモ

<?xml version="1.0" encoding="utf-8"?>
<A
  xmlns:bbbbb="http://example.com/bbbbb"
  xmlns="http://example.com/aaaaa"
>
  <bbbbb:Z>z-value</bbbbb:Z>
  <B>b-value-0</B>
  <B>b-value-1</B>
  <B>b-value-2</B>
</A>

とかなんとか適当に XML があって、 System.Xml.Linq.XDocument / System.Xml.Linq.XElementElement / Elements を使おうとしたら…

1. bbbbb:ZElement しようとしたら System.Exception 例外が "The ':' character, hexadecimal value 0x3A, cannot be included in a name." とか Message に入って飛んだ場合

例外の Message に書いてあるままなんだけど、要素名 bbbbb:ZXElement へアクセスしようと以下のようなコードを書くと発生する:

void f( XDocument x )
{
  // 例外はいてしぬ
  var z = x.Element( "bbbbb:Z" );
}

名前空間を付けた要素名を与えたい場合は:

void f( XDocument x )
{
  // string => XNamespace は暗黙変換される
  XNamespace ns_bbbbb = "http://example.com/bbbbb";
  // ( XNamespace + string ) => XName は operator が定義されている
  XName name_bbbbb_z = ns_bbbbb + "Z";
  // Element の1引数版は XName を引数にしている(先の例では string => XName が暗黙変換されていた)
  var z = x.Element( name_bbbbb_z );
}

こうすると死なない。というか、こうしないとならない仕組み。実際問題でいうとめんどくさいけどまあそれはこの際オイトイテ💁

2. BElements しようとしたら1個も取れないし Element したら null だった場合

void f( XDocument x )
{
  // bs は要素が空の列挙になる
  var bs = x.Elements( "B" );
  // b0 は null になる
  var b0 = x.Element( "B" );
  // ところがこうして要素名を指定せずに列挙すると B も取り出せてしまう"怪奇現象"かのような事が起こる(実際は仕様であって怪奇現象ではない)
  foreach ( var e in x.Elements() )
    System.Console.Error.WriteLine( e.Value );
}

冒頭の今回扱っている例示の XML では xmlns によりデフォルトの名前空間"http://example.com/aaaaa" と定義している。これを System.Xml.Linq でも明示的に実装しないと↑のように空になったり null になったりする。

void f( XDocument x )
{
  // デフォルトの名前空間を明示的に与えるためのデフォルトなので見えない名前空間をきっちり定義してあげる
  XNamespace ns_default = "http://example.com/aaaaa";
  // 意図通り要素を今回の例なら3つ取れる
  var bs = x.Elements( ns_default + "B" );
  // 意図通り先頭の要素を取れる
  var b0 = x.Element( ns_default + "B" );
}

「デフォルトとは…」みたいなお気持ちになるけど System.Xml.Linq はそういう仕様なのでこれもめんどくさいけどわざわざ明示的にデフォルトの名前空間の要素名 ( XName ) を扱うよう実装を書いてあげないと期待動作しないのでした。

めんどくさいなぁ…と思いながら、また数カ月後とかに使う機会があったときに「なんでだっけ…🤔」とかなりそうな予感がしたのでメモ。

Reference

ProMicro が Unknown USB Device (Device Descriptor Request Failed) になってしまった!?と思ったけど問題はケーブルだった話

f:id:USAGI-WRP:20190308193802p:plain

ぎゃー💁

と、昨晩なったんだ。本当に手元の ProMicro が全滅していたらこれはしんどい。でもまあ、そんなわけないよねー😃

f:id:USAGI-WRP:20190308201351j:plain

↑最小構成のデモ用にちょっと持ち出せて、でも、あくまでも仮組み、はんだレス。そんな感じで小型ブレッドボードに組んでみているところ。(ふだんはこの作業マットの上ではだかのProMicroにスルーホールテストワイヤーを直接ぐさぐさしてます😇)OLEDを付けると、スイッチは4つアシだと1つしかこのサイズのブレッドボードにはさせないけれど、2つアシなら2キーさせるかも。DIPなら4キーさせるけど…。

なんてことを遊んでいたところ、オシゴトで一端外していたものを翌日つけたら Unknown USB Device (Device Descriptor Request Failed) ですよ!😂

「壊しちゃった?でもなんで??」

と、思いつつ、予備(というか積みキ用に用意してある)の3つも試してみたら全部同じ状況発生でダメ!しょんぼりしたよ。

f:id:USAGI-WRP:20190308202239j:plain

↑で、こっちが問題が解決した状態の絵。何が違うか気づいて貰えるだろうか…。少なくとも夜な夜なオネムの私の脳はこの間違い探しには気づけなかった😂

こたえ:繋いでるケーブルが180°回っている。

ProMicro は USB Micro B なのでコネクターにケーブルが回転するなんて事はふつーは起こらないのですが、私が使っているこのケーブルは自キ界隈では広く恐れられている「もげマイクロ」現象への対策として マグネット式のアダプターを追加するタイプのケーブル を使っていたのです。

で、このマグネット式のケーブル、USB の最小限の4ピンはきちんと持っているのですが、180°回した状態でも接続できるのです。できる…いや、できないのですが、できるのです。機械的には。

ところが、誤った回転で接続すると、 ProMicro は Unknown USB Device (Device Descriptor Request Failed) となり COM ポートも見えません。壊れないだけいいけど…、いやはや、なんてこったいでした😅

"見せ電子部品"とか"輝き"が好きなので実験のほか、わたし設計の自キでは ProMicro も"見せ"る向きになる予定でした。このケーブルも接続状態に応じて緑や青に輝くところが密かなお気に入りポイントだったのですが…そこは背面にしないとならない事に気づいてしまいました。悲しい😂

…光るケーブル作ればいいって、思ったでしょ…。

ちょっと、考えてる。

Lian Li のこういうの とか😇

Metasequoia と RenderMan とカラープロファイル。 It で暗く出力されちゃって途方に暮れないための手順メモ

Metasequoia + RenderMan の連携機能で遊んだら出力画像が暗くなってしまって「なんでーー😂」ってなった。そうならない方法がわかったのでメモ。

問題の現象

f:id:USAGI-WRP:20190304215513p:plain

悲しい😥

何が起きているのか?

MetasequoiaRenderMan 連携機能でデフォルトになっている出力方式の Itレンダリングし、 It で出力結果画像を Export File すると PNG でも JPEG でも TIFF でも色味が暗くなってしまう。

原因はカラープロファイルで、 It ではデフォルト状態でレンダリング結果の LinearsRGB へ変換して表示してくれている。これは It のメニューの View から設定を変更できるので、切り替えて表示を確認してみると Export File で発生した暗くなる問題の原因がこの問題に起因するものという事はわかる。

わかるのだけど、どうやら It では PNG, JPEG, TIFF での出力にカラープロファイルを埋め込んでくれたり、 sRGB へ変換した上で保存してくれたりする機能はなさそう😥

EXR ( OpenEXR )形式で Export File すれば Linear の全域をそのまま出力できるので、 Krita などで開いて PNG など最終的な出力を得れば…と、思ったのだけど、

f:id:USAGI-WRP:20190304221003p:plain

とりあえず開いてみたら真っ白でしょんぼり。レイヤーを見ると "a" の名称で真っ白なレイヤーがあり、その下に "Ci" の名称で階層化された "000", "001", "002" の3つのレイヤーがあった。

f:id:USAGI-WRP:20190304221134p:plain

どうやら Alpha, Red, Green, Blue をレイヤーとして分離出力したファイル…として認識されたらしい。他の EXR 形式対応のアプリで開いても同様だったところで EXR 形式の仕様を思い出してみてなんとなく納得した。つまり、 EXR で出力して、それを既存の一般的なラスターイメージ向けのアプリで変換するというのはめんどくさい…。できない事は無いが…😥 もちろんプログラマーさん的には変換アプリを作る事は EXR のライブラリーを使えばそんなに難しくはない…が…「既にそこにあるはずの絵」のためになぜ…という思いが…。つまりめんどくさい😥

この時点で思い付いたもっとも簡単ななんちゃって解決方法としては、「 ItPNG 出力して、画像編集アプリのレベル補正、ガンマ補正的な機能でぐいっと適当に調整する」というのもあるけれど、どうも既にできている出力画像を変換作業を手でやるめんどくささ+せっかく大域照明レンダリングしておいて情報損失しちゃうの勿体無い…というお気持ちでもんにょり。

そもそもの解決方法

問題は「 It または It から先でどうするか」だとばかり思ってしばらく悲しんでいたのだけど、「 It より前」に解決方法があった😃

f:id:USAGI-WRP:20190304222019p:plain

  • MetasequoiaRenderMan 連携機能のツールウィンドウの出力を It ではなく ファイル にする。

それだけの事だった😂

そうするとレンダリング途中経過の画像表示は行われないし、保存可能なファイル形式も BMP, PNG, JPEG, TIFF に変わるのだけど、 LinearsRGBレンダリング段階で既に完了した状態での出力となるのでカラープロファイル問題が起こらなくなる。

f:id:USAGI-WRP:20190304222338p:plain

意図した色味できれいな PNG ファイルを直接出力できました😃

KiCad 向けオレオレ 3Dモデリング Pro Micro 編、後半。


昨晩の 「Pro Micro の KiCad 向け 3Dモデル を作ってみるはなし。 Metasequoia の画像計測を使ったり 3DCG 方面の人っぽいアプローチでやってみるよ💁」 の続きです😃

仕上げにソケット&ピンをはめた状態にする前に、 KiCad ではテクスチャーを扱えないらしいので穴くらいはきちんとあけておくかーって思ったんです。 Metasequoia にもブーリアンは搭載されているので、基板にシリンダーで差ブーリアンするだけのはずーって思ったんです。

f:id:USAGI-WRP:20190228221639p:plain

思ったんです。

f:id:USAGI-WRP:20190228221648p:plain

ぎゃー💁

試しに1つだけ穴を開けるようにオブジェクトを調整してみても同様でした。なんてこったい…😂

再現性を確認するため、

  1. MQO を1つ別ウィンドウで起動
  2. 失敗した Pro Micro を作っている MQO から板とシリンダーをそれぞれコピーして検証用の別ウィンドウの MQO へ貼り付け(これができるところも MQO のべんりポイント💁)
  3. ブーリアン!!…同様に失敗💀
  4. シリンダーを1つだけにしてブーリアン!!…失敗💀

🤔…

原因を特定するため、

  1. 検証用の方で新たに板を作ってコピペしてきたシリンダーでブーリアン … 失敗💀
  2. 検証用の方で新たにシリンダーを作ってブーリアン … 成功😅 … ナゼダ…

f:id:USAGI-WRP:20190301110507p:plain

まー、できたからいっかー💁 昨晩は Fusion 360 へ移行するしかないかなーって諦めつつオネンネしいていたのでちょっと嬉しい。(CAD系3Dアプリの操作感はあんまり慣れないので😅)

f:id:USAGI-WRP:20190301114110p:plain

KiCad では 3Dモデル へテクスチャーは読めないらしーのでこれじゃあちょっと寂しいかなー…。

ホールの pad 乗せてみようかなー💁

f:id:USAGI-WRP:20190301140640p:plain

テクスチャー付けなくてもけっこーそれっぽく見えるようになった気がする😃

… SMD の pad も乗せてみようかなー💁

f:id:USAGI-WRP:20190301142915p:plain

だいぶそれっぽい!😃

シルクスクリーンのガイドも乗せてみようかなー💁

f:id:USAGI-WRP:20190301163422p:plain

もう Pro Micro にしか見えなくなってきた😃

… シルクの文字も乗せちゃおうかなー💁

f:id:USAGI-WRP:20190301171649p:plain

どうみても Pro Micro !!😃

…チップのレーザー刻印も付けちゃおうかなー…💁

f:id:USAGI-WRP:20190301201206p:plain

…裏面もちょっとだけシルク乗せちゃおー…💁

f:id:USAGI-WRP:20190301201328p:plain

できた、できた。もう誰がどうみてもパターンとはんだは無いけど ProMicro でしょー😃

いざ KiCad へ!

f:id:USAGI-WRP:20190301203938p:plain

…なんでやねーん😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂😂

期待動作していない点は、

  1. 基板の色が「赤」のはずが灰色
  2. 基板のポリゴンが壊れてる(↓図)
  3. 基板から R っぽいポリゴンがにょっきしてる(↓↓図)

f:id:USAGI-WRP:20190301205305p:plain

f:id:USAGI-WRP:20190301205634p:plain

先ず、色からなんとかする。

f:id:USAGI-WRP:20190301220612p:plain

MQO のレンダリングを基準に Material を作ったけれど、 KiCad で読むと shininess は金属部品を除きほぼ 0 にしないと diffuse が出ないみたい。 shininess1.0 くらいでもかなーり彩度が失われて灰色化してしまうと実験的にわかり、金属部品を除き基本的に shininess0 にしました😃

すると今度は LED が不透明な事に気付く。 KiCad 公式の LED の 3Dモデル は半透明になっていたはず…↓

f:id:USAGI-WRP:20190301221455p:plain

この↑ kicad-footprints:LED_D3.0mm 用の 3Dモデル のソースを眺めてみる。 VRML はテキストフォーマットなので GitHub でそのまま読める💁

                        DEF o2 Group {
                          children 
                            Shape {
                              appearance 
                              Appearance {
                                material 
                                Material {
                                  diffuseColor 1 0 0
                                  ambientIntensity 0.086274512
                                  specularColor 1 1 1
                                  shininess 1
                                  transparency 0.5

                                }

ambientIntensity が怪しいような、あるいはそもそも VRML 2.0 形式じゃないと透過処理してくれない実装なのか…。 MQO では VRML 1.0 しか吐けないし、これはまたそのうちの対応としよう…💀

さて、続いて致命的なポリゴンが壊れる問題へ。この問題は四角ポリゴンが原因かもしれない。

f:id:USAGI-WRP:20190301205820p:plain

この手の3Dモデルデータのアプリ間交換ではよくあるぱたーんの1つ。MQO で全てのオブジェクトを選択して 面を三角形化 を行ってみる。

f:id:USAGI-WRP:20190301232358p:plain

うむ、良い感じ😃

とはいえ、 SMD 風に実装する事はまず無いので「下駄」とセットの絵にしないとちょっとうさんくさい。自キ界隈でよくつかわれているように見えるスプリングピンヘッダー、コンスルーと呼ばれる工夫されたピンヘッダーを作って穿かせる事にしました。

f:id:USAGI-WRP:20190302060850p:plain

ほいできたっと♥

これを…穿かせて…

f:id:USAGI-WRP:20190302061106p:plain

KiCad で読み込んで…

f:id:USAGI-WRP:20190302061234p:plain

f:id:USAGI-WRP:20190302061349p:plain

オモテ、ヨシ😃

f:id:USAGI-WRP:20190302061442p:plain

ウラもヨシ😃

KiCad ProMicro オレオレ 3Dモデル できました!

https://github.com/usagi/usagi.kicad も更新。

f:id:USAGI-WRP:20190302063847p:plain

高さ違いのバリエーションも用意してみました。游舎工房お取り扱いはH=2.5mm、スイッチサイエンスお取り扱いはH=2.mm 。他の H については マックエイトカタログページ の PDF リンクのデータシート部分を参照して作成しました。10mm も下駄を穿かせるなら中にリセットスイッチとか実装しちゃうと名刺サイズとか小さなプラットフォームでは役に立つこともある…かな💁

f:id:USAGI-WRP:20190302064549p:plain

ProMicro のフットプリントなんだけど3Dモデルはスプリングピンヘッダーだけ立てる版も用意してみました。スプリングピンヘッダーだと ProMicro は着脱可能だしね!

f:id:USAGI-WRP:20190302073520p:plain

それとスプリングピンヘッダー単体も。

この後は「下駄」のバリエーションとしてピンヘッダー&ピンソケットを増やしたら、 MX Switch のKiCad用オレオレ3Dモデルを作ろうかなーって思います💁

それではおやすみなさーい💤

Pro Micro の KiCad 向け 3Dモデル を作ってみるはなし。 Metasequoia の画像計測を使ったり 3DCG 方面の人っぽいアプローチでやってみるよ💁

自分で作ったものを自分で使いたいお気持ちのホビーとして作ってみました。

先ず、ノギスで主要な図りやすい部分の長さを測って記録して…、それから、今回は表面に箱をたくさん生やす必用がある上にノギスでは図りにくい極小部品もあるので画像計測することにしました。

写真をトリマス。

f:id:USAGI-WRP:20190228135011p:plain

撮影時にピチピチに水平や画角を調整しておく手もありますが、今回はてきとーに撮っててきとーに補正しててきとーに測るてきとー方式で💁

f:id:USAGI-WRP:20190228134550p:plain

InkScape にノギスで測った Pro Micro の基板本体部分の外形の枠をレイヤーで用意します。枠はストロークを基板と被らないキョーレツな色(今回は緑)、フィルを基板と枠と被らない適当な色を不透明度を落として(今回は青のα=32)で用意すると作業しやすいと思います。

f:id:USAGI-WRP:20190228135449p:plain

てきとーに撮影した画像を貼り付けて、おーよその大きさを併せます。

f:id:USAGI-WRP:20190228141245p:plain

画像を移動&変形して枠の四隅に基板の四隅を合わせます。基板で画像がちょうどぴったりきれているわけではないので、回転は使わずに移動と剪断変形でてきとーに調整すると楽かもしれません。

f:id:USAGI-WRP:20190228143227p:plain

基板ピッタリサイズにページ設定をして、枠のレイヤーを非表示にして Export すると、きれいな正射影もどきの"テクスチャー"のできあがり。

f:id:USAGI-WRP:20190228143314p:plain

さて、それで画像計測はどこでするの?というと Metasequoia でてきとーにしちゃう。てきとーてきとー💁

f:id:USAGI-WRP:20190228143539p:plain

マテリアルにテクスチャーをがーんと乗せたやつを作る。編集作業中に確実にくっきりはっきり見たい用途ではマテリアルのパラメーターを「自己照明」= 1.00 で拡散、反射、周囲光を 0.00 にしてしまうのは Metasequoia のちょっとしたコツかもしれない。

f:id:USAGI-WRP:20190228143654p:plain

基板の外形を立方体で作って、天板だけこのテクスチャーのマテリアルを設定するとこうなる。

画像計測はいつになったらするのかというと、

f:id:USAGI-WRP:20190228144427p:plain

はいこの通り💁 Metasequoia 4 Ex にはこういう使い方する人に便利な「計測」ツールが狭義の CAD アプリに比べればおまけ程度ではあるんだけどしっかりついてる。べんり。

f:id:USAGI-WRP:20190228162317p:plain

と、いうわけで、ノギスで測っておいた数値と画像計測からそれっぽい数値をとってマテリアルで適当に色付けした直方体を置いていきます。

今回は MEGA32U4 と足から。この部品は 45° 傾いていているのだけど、 Metasequoia には部品ごとローカル座標系で編集したりする機能はないので、思い切ってすべてのオブジェクトを選択して側面ビューから回転ハンドルで 45° 傾けた状態で作ってしまいます。作り終わったらまた全てのオブジェクトを 45° 回して戻す。回転を行う際は、3面図ビューなどで必ず真横や真上からハンドルを操作します。そうしないと気づいたらオブジェクトが妙な角度に捻れてしまい悲しみの CTRL Z 連打をする事になるので注意…していてもたまにやってしまう😂

f:id:USAGI-WRP:20190228211204p:plain

f:id:USAGI-WRP:20190228212128p:plain

Pro Micro の USB Micro B コネクター、保護してない在庫が無かったのでコネクター以外の外形はフィーリングで作ったらわりと違っていて修正に手間取った上にちょっと違う感じになってしまったのが悔やまれる。気が向いたらコネクターだけ作り直したいな。

ピンヘッダー&ピンソケット版、コンスルー版を用意して KiCad で実用時の見た目に近くなるようにしたら https://github.com/usagi/usagi.kicad に追加しようと思います。今日は疲れたのでここまで💁

はじめての KiCad の 3Dモデル 作成メモ

さいきんは Fusion 360 で作る話が一般的なようだけど、私は Metasequoia に慣れているので、 Fusion 360 で作るより速いかなーって思い Metasequoia で作ってみた。 MetasequoiaVRML-1.0 を吐けるのでモデリングから KiCad で必用なフォーマットでの出力まで、色付けまで含めて1つのアプリでできる。

はじめての KiCad の 3Dモデルとして作るのは「トグルスイッチ」の

さんです💁

f:id:USAGI-WRP:20190228023849p:plain

Metasequoia はいわゆる狭義の意味での CAD ではなく 3DCG モデラーなので、あんまりカチコチっとした数値と拘束によるデータ作成には向いてないし、頂点の移動で複数選択して移動する時に代表の座標をどこにするか選べず「選択中の最小値の頂点の座標成分値」での数値制御になるのでワールド座標で+側と-側で与える数値の絶対値が同じにできず脳内算数する必用がちらほらあったりで、最適とはいえない。

最適とは言えないのだけど、私は Metasequoia 慣れしているので、この程度のモデリングするならどっちでもいいかなーと😃

f:id:USAGI-WRP:20190228010425p:plain

フットプリントエディターでごにょごにょ…。

f:id:USAGI-WRP:20190228011826p:plain

フットプリントのプロパティーから作成した VRML 形式のファイルを読み込んだ…はず…なのだけど…。

f:id:USAGI-WRP:20190228015323p:plain

居た😂 ちっさい…。 MetasequoiaVRML 出力する際に 1/100 設定で出しちゃってた。

f:id:USAGI-WRP:20190228015350p:plain

と、いうわけで、 KiCad の方で 39.4 倍に倍率設定してきれいにぴったんこ。

f:id:USAGI-WRP:20190228015758p:plain

f:id:USAGI-WRP:20190228015823p:plain

と、いうわけで…

KiCad のライブラリーを公開しました💁

参考

C# こわい話: LINQ でパスのサニタイズしたくらいでテストが通らないなんてそんな事が

起きた😅

現象

f:id:USAGI-WRP:20190225125342p:plain

  public static class x
  {
    public static string f( string input )
    {
      var targets = Path.GetInvalidFileNameChars();
      var intermediate = 
        from c in input where !targets.Contains( c ) select c;
      var result = string.Concat( intermediate ); // <-- 予想外の結果が生じていた
      return result;
    }
  }

input"Death Sauce \n\r 02:00:00" を与えてテストしたら "Death Sauce 020000" が Expected 、と思ったんだけど、実際に出たのは "System.Linq.Enumerable+WhereEnumerableIterator1[System.Char]"` でした💀

対策

f:id:USAGI-WRP:20190225125313p:plain

      var result = new string( intermediate.ToArray() );

stringchar[] からのコンストラクターを持っているのでこれで Actual == Expected へ。

この問題に気づいて初め、ほぼワンライナー程度の実装なのでテスト側のコードにべたっと書いてデバッガー挿したら期待動作しちゃったんだよね。ぇー…って思って wandbox で最小コード切り出して叩いても期待動作して再現しないし。

ローカル環境では放り込むアセンブリーの単位を変えたら発症したので、そこらへんに理由があって、古い .NET Framework ターゲットでは string.Concatオーバーロード解決がナウい処理系とは異なるとかなのかな。もっと単純に何か私がミスしてるのかな🤔

回避方法は上記の通り簡単だし、この処理はボトルネックでもなんでもないのでさくっと回避して通り過ぎる事にしたけれど、お気持ちは少々もんにょりが残る。なんじゃろ。