「第28回シェル芸勉強会 大阪サテライト」の復習(手抜きモード)

イベント関連ページ

各会場の告知

レポート・まとめ

午前の部

講師

  • 前半: 今泉光之(@bsdhack)さん/USP友の会
  • 後半: 上田隆一(@ryuichiueda)さん/USP友の会

動画

資料

感想など

プロセス間通信の手段であるシグナルについて学びました。

シグナルを受信したときに、その種類に応じて処理を行うコマンドtrap、そしてプロセスにシグナルを送るコマンドkillについて説明を受けました。

シグナル関連のコマンドといえば普段kill -9くらいしか使っていなかったこともあって、この講義を受けるまでは忘れていたのですが、シェル芸人は必ず持っていると言われている(未確認)、後半部の講師である上田隆一さんの著書『シェルプログラミング実用テクニック』の「A.4.5 ハト語に変換する(シグナル処理)」がtrapの良い(?)使用例になっているのではないかと思います。

なお、シグナルの概要についてはman 7 signalで知ることができます。

また、最後にはこの勉強会の共催をされている日本UNIXユーザ会様から、会の紹介が行われました。

午後の部

動画

問題・模範解答

解答

A1.1: \begin{figure}\end{figure}で囲まれた部分を全て抽出

$ sed '/\\begin{figure}/,/\\end{figure}/!d' contents.tex
\begin{figure}[htbp]
        \begin{center}
                \includegraphics[width=0.5\linewidth]{./figs/coordinate.eps}
                \caption{世界座標系とロボットの姿勢}
                \label{fig:coordinate}
        \end{center}
\end{figure}
(...略...)
\begin{figure}[htbp]
        \begin{center}
                \includegraphics[width=0.8\linewidth]{./figs/observation_noise.eps}
                \caption{ランドマークの計測値の不確かさを表す共分散行列}
                \label{fig:observation_noise}
        \end{center}
\end{figure}

sedで、アドレス範囲の指定を正規表現で行い、指定した部分以外を削除します。

A1.2: キャプションとパス名のリストを作成

$ sed '/\.\/figs\//,+1!d' contents.tex | sed -z 's/[^{}]*{\([^}]*\)}[^{}]/\1\n/g' | sed -z 's/\([^\n]*\)\n\([^\n]*\)\n/\2 \1\n/g'
世界座標系とロボットの姿勢 ./figs/coordinate.eps
計測値 ./figs/observation.eps
ランドマークの計測値から2点の相対姿勢を求める ./figs/two_poses.eps
ランドマークの計測値の不確かさを表す共分散行列 ./figs/observation_noise.eps

./figs/」で始まるパス名が含まれた行と、その次の行を抽出し、出力フォーマットに合うように整形します。

A2: 第2章の第1文を抽出(コメントは無視)

$ perl -0777 -F'/\\section\{.+?\}\n/' -naE '$_=$F[2];s/%.*\n//;s/(.*?。).*/$1/s;say' contents.tex

平面上を移動し、向きを持ち、カメラでランドマーク観測ができるロボットで
graph-based SLAMを実行する方法を考える。

複雑な正規表現を書く必要がある場合、最小量指定子「?」をサポートしていないsedだと不便なため、perlで解いています。

contents.tex全体を一気に読み込ませるため、-0[文字コード(8進数)]オプションに架空の文字コード(777)を設定し、さらにAWKライクな処理を行うように-aオプションを付けた上で-F[区切り文字(列)のパターン]オプションを指定してperlを実行しています。

この問題では\section{…}を区切り文字列として設定しています。

A3: \footnote{…}の部分を全て抽出

$ perl -0777 -nlE 's/(\\psi_){(.*?)}/$1{$2}/g;@m=/(\\footnote\{.*?\})/gs;map {s/{/{/g;s/}/}/g;tr/\n//d;say} @m' contents.tex
\footnote{この仮定は実用上強すぎるが、実際には、後の計算式から分かるように、2つの姿勢間での値$\psi_{c,t}, \psi_{c,t'}$の差だけが分かれば良い。例えば、2点間で得られた画像の向きを画像処理から割り出すなどの処理で、この差は得られる。}
\footnote{$「10$[\%]」は変数にすべきだが、記号が増えて理解の妨げになるので固定値として説明する。}
\footnote{おそらく$\psi$は$\theta$で置き換えられるので$\psi$を使わない実装もできるが、まだ自分自身では検証していない。}
\footnote{小さい角度なので、$\sin(3\pi/180)$は$3\pi/180$に近似しても良い。}
\footnote{固定しないと世界座標系が決まらない。}

A2と同じくperlを使って解いています。\footnote{…}の「」の部分にある「{」と「}」は処理の都合上、いったん全角に置換してから出力する直前に半角に戻しています。

A4: 各章を、タイトルをファイル名にした個別のファイルに分割

$ awk '{if(/\\section/){T=$0;sub("\\\\section{","",T);sub("}","",T);sub(" ","_",T);print $0 > T}else{print > T}}' contents.tex
$ ls $(awk '/\\section/' contents.tex | sed 's/.*{//;s/}//;s/ /_/g') | xargs head -n5
==> graph-based_SLAMの実装例 <==
\section{graph-based SLAMの実装例}

実装の一例を示す。

\subsection{グラフのエッジを作る}

==> はじめに <==
\section{はじめに}

この文章は、\cite{grisetti2010}などのチュートリアルを見ても数式の細かいところが分からない
graph-based SLAMについて、
実際の計算方法を細かく解説するためのものである。

==> 問題 <==
\section{問題}

%対向二輪型(その場で回転できるロボット)で、
平面上を移動し、向きを持ち、カメラでランドマーク観測ができるロボットで
graph-based SLAMを実行する方法を考える。ランドマークは環境にいくつか存在し、

行に\section{…}が含まれている場合に、「」の部分からファイル名を生成しています。

A5: 「○○座標系」を全通り抽出(○○はカタカナか漢字の単語)

$ grep -Po '[\p{Katakana}\p{Han}]+座標系' contents.tex | awk '!l[$0]++'
世界座標系
ロボット座標系
計測座標系

grepの正規表現で、「\p{…}」(否定の場合は「\P{…}」)といった、Unicodeのスクリプト(書記系)の名前による検索を利用しています。

ちなみに、ユニコードコンソーシアムの「Supported Scripts」によると、日本語で使われているスクリプトの名前は、ひらがな(Hiragana)、カタカナ(katakana)、漢字(Han)、ローマ字(Latin)となっているようです。

A6: 各段落の頭に全角スペースを挿入

$ perl -0777 -nlE 's/(\n{2,}(?!\\|%))/$1 /gs;s/(\n%.*?\n)/$1 /gs;s/\n %/\n%/gs;s/(\n{2,})(\\ref)/$1 $2/gs;s/\n (\n|\z)/\n$1/gs;say' contents.tex
\section{はじめに}

 この文章は、\cite{grisetti2010}などのチュートリアルを見ても数式の細かいところが分からない
graph-based SLAMについて、
実際の計算方法を細かく解説するためのものである。
(...略...)
すると、初期値に使ったデッドレコニングの値$\hat{\V{x}}_{0:T}$
がそれなりに良ければ、ランドマークの計測値を全体的にバランスよく説明できる
姿勢に$\V{x}_{0:T}$を$\Delta\V{x}$が収束する。

次のA7も含め、数式やコメントの部分は可能な限り原型を保つことを意識し、perlを使って解答しています。

複数の正規表現を使い、望む出力が得られるまで少しずつ形を整えていきます。

A7: 段落内の余計な改行を削除

$ perl -0777 -nlE 's/\n/\0/gs;s/\0\0/\n\n/gs;s/\0(\t+)/\n$1/gs;s/\0\\(begin|end)/\n\\$1/gs;s/(\\end\{.*?\})\0/$1\n/gs;s/\n\0/\n\n/gs;s/(%[^\n\0]*)\0/$1\n/gs;s/\0%/\n%/gs;s/\0//gs;say' contents.tex
\section{はじめに}

この文章は、\cite{grisetti2010}などのチュートリアルを見ても数式の細かいところが分からないgraph-based SLAMについて、実際の計算方法を細かく解説するためのものである。実装例はGitHubの\texttt{ryuichiueda/probrobo\_practice}の\texttt{./graph-based\_SLAM/graph-based\_slam.ipynb}にあり、この文章はこの実装の数学的な解説となる。ただし、コードで使った記号と本文章の記号は一部異なる。

\section{問題}
(...略...)
が成り立つ(説明は後で)。

以上の計算を、$\V{x}_{0:T}$を$\Delta\V{x}$だけ動かし、再度$H, \V{b}$を計算して$\Delta{x}$を求め、と繰り返す。すると、初期値に使ったデッドレコニングの値$\hat{\V{x}}_{0:T}$がそれなりに良ければ、ランドマークの計測値を全体的にバランスよく説明できる姿勢に$\V{x}_{0:T}$を$\Delta\V{x}$が収束する。

A6にもあてはまる話ですが、出力結果について、出題者が想定している正解の範囲からは外れているかもしれません。

今回はいつにもまして難問続きでしたが、その中でもQ6、そしてこのQ7が最高に難しい問題でした。

A8: 章節項のリストを作成

$ sed -r '/^\\(sub){,2}section\{/!d' contents.tex | sed -r 's/\\label\{.*//;s/\}$//;s/section\{/ /' | awk '$1=="\\"{A++;B=C=0;$1=A;print}$1=="\\sub"{B++;C=0;$1=A"."B;print}$1=="\\subsub"{C++;$1=A"."B"."C;print}'
1 はじめに
2 問題
2.1 ロボットの姿勢と座標系
2.2 観測
2.2.1 ランドマークの識別
2.2.2 ランドマークの姿勢計測
2.2.3 計測値の記録
2.2.4 計測値の誤差
2.3 完全SLAM問題
3 graph-based SLAMの実装例
3.1 グラフのエッジを作る
3.1.1 $\V{\mu}_{c,t,t'}, \V{e}_{c,t,t'}$の計算
3.1.2 $\Sigma_{c,t,t'}, \Omega_{c,t,t'}$の計算
3.2 最適化問題を作る
3.2.1 マハラノビス距離
3.2.2 最適化する式
3.3 $\V{e}_{c,t,t'}$の勾配を求める
3.4 問題を解く

1つめのsedで章節項を抽出し、2つめのsedで不要な文字の削除および次のawkで第1フィールドになるフラグ用の文字列を生成します。その後awkで第1フィールドの値に応じて章節項の数値を割り出してタイトルと共に出力します。

LT大会

急用のため残念ながらLT大会に参加することができませんでしたが、どうやらフォーク爆弾(言わずと知れた「:(){ :|:& };:」)ネタで盛り上がっていたようです。

感想など

今回の問題の難度は、「普通のsed」と予告されていたにもかかわらず、「sed地獄」と銘打たれていた前回よりも高く感じられ、当日解答できたのは

  • Q1.1
  • Q1.2
  • Q4
  • Q5

の4問にとどまりました。このような結果を招いた原因はおそらく、

  1. そもそも頭の回転が遅く、解法を考えるスピードが遅い
  2. 最初に決めた手法に固執してしまう

という2点にあり、これらの弱点を克服すべく更なるsh行に打ち込まなければならないと思いを新たにしました。

「第28回基準値を超えるシェル芸勉強会」の「基準」とは、常人とシェル芸人とを判別するための基準だったのかもしれません。

最後に、

に改めてお礼を申し上げます。ありがとうございました。

Written on April 26, 2017