platform-echo
ちょっと生気を取り戻しました。
2015年12月3日木曜日
更新無期限停止しますorz
コンテンツ公開の方針を考えていたのですが、なかなかネタも生産出来ておらず、全く更新がないまま無言で放置しておくのもアレかと思いまして、この度このようなことに相成りました。
2nd placeの方は、"2nd"という独立したサイトとして継続する予定です。何か公開できるものが出来上がったらそちらに流す方針で……。
2015年7月20日月曜日
PythonでGUIプログラミング (2)
はじめに
お約束の、「PythonでGUIプログラミング (1)」の続き。(1)ではPythonのTkinterを使ってGUIを実装したが、件の「動作が遅くなる」問題でイマイチ。そこで別のGUIライブラリをさがしてみたら、wxPythonなるライブラリが見つかり、それを使って実装しなおした。
wxPythonを使ったプログラムを書くに当たり参考になるチュートリアルはこちら。
これに倣ってコードを書けば、wxPythonの使い方がだいたいわかるはず。
なお、この記事ではwxPythonの詳しい使い方や仕様については記述しないので(あくまで本題はGUIプログラミングの基本について)、適宜ドキュメントを参照してほしい。
wxPythonを使ったプログラムの例
作りたいプログラムやGUIプログラミングに関する基本事項は「PythonでGUIプログラミング (1)」で語ってしまったので(こちらに目を通していない方は、ぜひ先にそちらを読んでいただきたい)、さっそくプログラムのサンプルを示したいと思う。
後々このプログラムをベースに機能を拡張したので、その布石となるいくつかの余計な機能も実装済みで少々長い。まぁ、参考になれば……。
プログラムの概要
14-16行目は、OscilloViewerクラスのapp_about()で使われるプログラムに関する情報を、変数に格納している部分である。特に重要性はない。
19-25行目は、後々色々な処理をタイマーを使って実装するので、タイマーにより実行する処理を判別するための準備の記述。詳しくはOscilloViewerクラスのOnTimer()の記述を参照されたし。
27行目からは、OscilloViewerクラスの宣言。主な処理に関わる比較的重要なメソッドの一覧と概要を表に示す。
__init__() | GUIウィンドウの初期化や波形データを保存しておくリストなどを用意する。 |
---|---|
init_GUI() | GUIのウィジェットの配置と、イベント処理の設定をまとめたメソッド。このメソッドは__init__()の中で呼ばれるので、__init__()にまとめてしまっても問題ない。このメソッドの内容を簡単に説明する。 [39行目] アプリケーションを開始。 |
start_window() | GUIを開始する。 |
OnTimer() | タイマーが回っている時に、タイマーにより起動される処理。self.timer_modeにセットされている値により処理を変えるようにしてある(実質的に1個しか機能が実装されていないが)。 |
start() | STARTボタンが押された時の処理。151行目から163行目までは、このプログラムではまず実行されないので気にしなくて良い。なお、この部分は私が意図したとおりには動作しないことが確認されている(←直せよ)。 大事なのは164行目以降で、self.timer_modeにTIMER_TESTRUNをセットし、タイマーを 50 ms 間隔にセットして開始する。以後、self.timer.Stop()が実行されるまでタイマーが回り続ける。 |
tf_start() | タイマーイベントにより実行されるOnTimer()メソッドで呼び出される処理本体。新しい波形の生成・セット・描画を1回だけ行う。 |
stop() | STOPボダンが押された時の処理。タイマーが動作中であれば停止させる。 |
おまけ的な機能を実装したメソッドについても簡単に説明する。
app_about() | 「メニューバー→ヘルプ→About」がクリックされた時の処理。ダイアログを表示する。 |
---|---|
app_exit() | 「メニューバー→ファイル→終了」がクリックされた時の処理。プログラムを終了する。 |
set_wave() | 波形データをインスタンス変数にセットする。 |
redraw() | インスタンス変数にセットされた波形データを、Panelに線を引いて描画する。 |
save_log() | 「メニューバー→ファイル→ログを保存」がクリックされた時の処理。TextControlに書かれたログをファイルに書き出す。 |
write_log() | TextControlにログを書く。 |
ボタンとイベント
「PythonでGUIプログラミング (1)」において、Tkで実装したものと実行される流れとしては同様なので詳しくは説明しない。
タイマーによる処理
STARTボタンが押されると、タイマーが回り始めるようになっている。タイマーによる処理の流れは次のようになる。
- イベント待ち状態
- タイマーイベントの発生
- OnTimer()が実行され、self.timer_funcにセットされている値により実行すべき処理を判別し、実行する (※単一機能であれば、この機能は必要ないが……。)
- 1に戻る
以上の処理により、「PythonでGUIプログラミング (1)」で実現したかった機能が実装できている。しかも、Tkのプログラムのように、タイマーによる処理がだんだんと遅くなっていくようなことはない(環境依存かもしれない。遅くなるようなことがあればお知らせいただきたい)。
タイマー使用時の注意
余談になるが、実行しないほうが良い、悪いプログラムの例を示す。要点のみ示すため、前に示したサンプルコードからは大幅に機能を削ってある。
やるなと書いたのに実行してしまったあなたは、「Yes」あるいは「はい」を連打していい塩梅に止めるか、タスクマネージャーなどで無理やりpythonのプロセスを終了させてあげてください。
このプログラムの意図としては、次のような処理を行おうとしたものである。
- Check valueボタンが押されたら、タイマーを開始する
- タイマー開始開始後
- イベント待ち
- タイマーイベントでOnTimer()が実行される。カウンタをインクリメントし、check_value()を呼ぶ。
- check_value()で、カウンタの値が10の倍数か否かを判定し、10の倍数ならダイアログを表示する。
- ダイアログで「Yes」あるいは「はい」が押されればタイマーを止め、「No」あるいは「いいえ」が押されれば継続する
- 1に戻る
しかしながら、このプログラムを不要に実行するとわかるとおり、割と困ったことが起きる。タイマー開始後、一定時間後にダイアログが表示されるが、ユーザがしばらく操作をせずに放っておくと、ユーザ操作の前に次のダイアログが表示されてしまう。
このことからわかるように、wxPythonにおけるタイマーは、ダイアログが表示されていようがいまいが、ユーザの操作があろうがなかろうが、何もしなければタイマーは回り続けるので、タイマーイベントがコンスタントに発生し、処理が実行され続ける。
この問題を解決したプログラムを次に示す。
bad_code.pyからの変更点は、37行目からのcheck_value()の中身である。まず、この関数が呼ばれ、if文の条件に適合したらタイマーを一度止める。その後にダイアログを表示し、ユーザが「No」あるいは「いいえ」を押した時だけタイマーを再開する。
考えてみれば至極当然のことだが、うっかりタイマーを止めるのを忘れないように注意されたい。
まとめ
「PythonでGUIプログラミング (1)」ではTkinterを使って実装したプログラムを、wxPythonを使って再度実装した。
2015年7月18日土曜日
PythonでGUIプログラミング (1)
はじめに(タイトルと無関係な雑談)
いやー、色々終わってようやく時間が出来ました(できてない)。「色々」の中でも一番大きいのは就活でして、なんとか無事に就職先も決まり、あとは卒業するために研究に専念するだけという状況です(だけ……?)。
他人はどうか知りませんが、私は多くのことを並列的にこなすのが苦手な人間なので(それではいけないとはわかっておりますが)、この半年間は色々な「通過儀礼」や「突発イベント」に振り回され、ゆっくり考える精神的余裕がなかったように思います。何かを「生産する」時間ができた今、この半年間、私は一体何をか成し遂げたであろうかと思い返すとうーん何もしてないな(しろめ)と死にたくなると同時に、「生産する」ことの楽しさをこれまで以上に感じられるようになり、最近は比較的心穏やかに過ごせています。
そんなわけで、ぼちぼちブログの更新もネタを見つけてはやっていこうという感じでおります。当り障りのないポエムばっかり書くと思いますが、どうぞよろしくお願いします。
はじめに(本題の雑談)
大事なことはちょっとしか語らないので、この節は読み飛ばしてもらって構わない。
なかなかにお堅い感じのタイトルではじめてしまったが、GUIプログラミングを最近する機会があって、軽度にハマったことがあったのでちょっと記事にしておこうと思い立った次第。
今回の記事では、言語はPython(2.x)を使用し、GUIを構成するためのライブラリとしてTkinterを使用する。Pythonを使用する理由は、単に私が使っている実験用プログラムがPythonで書かれているせいで必然的にPythonを使わざるを得ないため。けどまあ、書き慣れるとけっこう使いやすい言語だし、文法がわかりやすいので、プログラミング初習者にもいいと思う。ただし、この記事が「初習者向け」であることは保証しない。サンプルコードは載せるので、兎も角もプログラムを動かして遊んでみたいという人には良いかもしれない。
また、tkを使うことに限っては、言語が変わっても使い方や関数名などがほとんど同じだったりするので、Pythonでしか使えない話でも無いと思われる。他の言語でtkライブラリでハマっている人にも、参考になればと思う。
割とどうでもいい話だけど、以前の私は「Pythonはクソ、Ruby最高」の完全なるRubyistだったのだが、最近Pythonであーだこーだやっている間に慣れてきたので、そろそろPythonianを自称してもいいのではないかと思っている。
更にどうでもいいことだけど、タイトルに(1)が付いているのは、今後(2)を書く予定があるからだ。(2)では、TkinterではなくwxPythonというライブラリを使ってこの記事と全く同じことを目的としてGUIプログラミングをする。結論から言うと、成功談は(2)の方である。
目的
研究じゃない。難しい話はしないので気楽に読んでほしい。
今回つくろうとしているのは、オシロスコープからデータをパソコンに取り込んで、波形を表示しつつ、データをファイルに書きだすようなプログラム(見た目は fig.1 のような感じ)。もちろんオシロスコープの制御なんて話は多くの人にとってはどうでもいいことだと思うので、この記事で扱うのは何らかのデータがあって、それをちょこっと処理してグラフィカルに表示するプログラムという程度に思ってもらえば良い。この記事に載せるサンプルコードも、オシロスコープなどなくてもちゃんと動作する。
今回のプログラムを書くに当たり私がハマったのは、「描画」と「その他の処理」の並列実行はどうやるのかという問題。一見出来て当たり前のことだが、私のようにGUIプログラミングの経験が浅い人間はちょっとハマる。これも結論から言えば、「タイマー」という常套手段があって、これを導入すれば結構すんなり乗り越えられる(かも)。
知識を整理する意味も込めて、GUIプログラミングの基本事項から書いていこうと思う。
GUIプログラミングの基礎
GUIベースのプログラムを作成するには、大きく次の2つを実装することになる。
- UIのパーツ(≒ウィジェット、ボタンやテキストエリア、メニューバー等)の配置
- 発生するイベント(ボタンが押された、クリックされた、メニューから選択された、等)に応じた処理
1が見た目の構成、2が裏で実行される処理、という具合。
GUIベースのプログラムは、1で記述するパーツに対するユーザの操作、即ち「イベント」がトリガとなって、何らかの処理が実行される。イベントが発生するまでは、特にプログラムされていなければ基本的には何も行われない。GUIを使用しないプログラムと何が違うかといえば、1の表示に関わる部分があるかないかという程度で、2の「イベントに応じた処理」は基本的にはGUIを用いないプログラムと同様に書けば良い。
深入りはしないが、ここで出てきた「イベント」の概念が、GUIプログラミングを少々難しくする要素の一つだとも言える。GUIプログラムでは、通常、イベントと処理が交互に発生することになる(待ち→イベント→処理→待ち→イベント→処理→…)。このとき、処理の結果としてプログラムの表示が変わるようなプログラムを書こうとすると特に、GUIの表示と内部の変数などの「状態遷移」をよく把握しておかないと、意図しないUIの見た目になってしまったり、意図した処理と表示の対応がとれなくなるなど、割りと厄介なことになる。ただ、このコトに関しては今回は本筋ではないので深くは立ち入らない。
Tkinterを使ったプログラムの例
早速だが、今回私が最初に作成したGUIプログラム viewer.py を示す。
クラスとメソッドの概要
簡単にプログラムに含まれるクラスとそのメソッドについて説明する。
OscilloViewerクラス | データの描画や、GUIなど、見た目に関する処理をまとめたクラス。 |
---|
__init__() | GUIライブラリのTkの初期化や、描画する波形データを保存しておくリストなどを用意する。 |
---|---|
create_widgets() | 波形を描画するcanvas(図形などを自由に描画できるエリア)、START及びQuitのボタンなどを配置する。じつはこのメソッドは__init__()の中で呼ばれるので、__init__()にまとめてしまっても良かった。 |
start_window() | Tkのメインループを開始し、GUIを表示する。Tkのmainloop()が実行されると、制御がGUIに移り、イベントの発生待ち状態になる。 |
set_wave() | 引数waveは数値のリストで、波形データである。引数normの値で正規化してcanvasに描画できる状態にする。このメソッドでは描画までは行わない。 |
redraw() | set_wave()でインスタンス変数にセットした波形を描画する。ここでcanvasに線を引く等の処理を行う。 |
start() | start_windowと名前が似ているのであまり良い関数名の決め方ではないが……。GUI上のSTARTボタンが「押された」というイベントで呼び出されるメソッド。 |
処理の流れ
おおまかに、次のような流れでプログラムは実行される。
- モジュールがimportされる
- クラス宣言
- 101行目、OscilloViewerのオブジェクトが生成され、__init__()及びcreate_widgets()が実行される
- 102行目、start_window()が呼ばれて、GUIが起動する
- イベント待ち状態
このプログラムで発生し得るイベントは「STARTボタンが押される」か「Quitボタンが押される」の2つが主なもの(その他、ウィンドウの閉じるボタンが押される、等もあるが省略)である。
Quitボタンは、押されるとプログラムが終了するようになっている(40-42行目参照。commandで指定しているのが、ボタンが押された時に実行されるメソッド)。
STARTボタンが押されると、start()が呼び出される。
start()が意図したとおりに動かない
91-98行目のstart()をコーディングした意図としては次のとおりである。
- self.cycleを10から199まで変化させつつ、2以降を繰り返し実行
- [l.93-94] 角速度 (1/self.cycle)π の正弦波を生成する(描画するデータを生成する)
- [l.95] データを描画できるように事前処理を施す(描画するデータをセットする)
- [l.96] canvasに線を引き、描画する
- [l.97] ループ変数をインクリメント
つまり、正弦波の周期を変化させるごとに波形を再描画するようにしたい。しかし、プログラムを実行すると分かる通り、STARTを押した後、描画されるのはself.cycleが199のときの波形だけである。
データのセットと描画が交互に行われて欲しいのに、そのようには動作しない。このことから、イベント発生時に実行されるメソッドは、メソッド内に記述された処理が完全に終了するまで、GUIの描画に制御を戻さないことがわかる。
タイマーを使ったプログラミング
start()を意図したとおりに動かすために改良したプログラム viewer_rev.py を示す。
viewer.pyからの主な変更点
- 27行目 追加
- 39行目 STARTボタンが押された時の処理を変更
- 41-44行目 STOPボタンを追加
- 52-53行目 set_timer_func()を追加
- 103-113行目 start()、ループではなく1回のデータセット・描画のみを行うように変更
- 115-118行目 timer()を追加、self.timer_funcにセットされた手続きを呼び出し・実行した後、タイマーをセットする
- 123行目 timer()を呼び出し、タイマーを開始しておく
処理の流れ
おおまかに、次のような流れでプログラムは実行される。
- モジュールがimportされる
- クラス宣言
- 122行目、OscilloViewerのオブジェクトが生成され、__init__()及びcreate_widgets()が実行される
- 123行目、タイマーを回す(以降、プログラム全体が終了するまで回り続ける)
- 124行目、start_window()が呼ばれて、GUIが起動する
- イベント待ち状態
ここまでは、「タイマーの開始」が追加された以外は、大きな違いはない。
タイマーの概念
GUIプログラムにおいては、「イベント」が発生することで処理が開始すると前に書いた気がするが、要はこの「イベント」を「タイマー」によって定期的に、ユーザの操作によらず発生させるわけである。
まず、「タイマー」の機能は、115行目以降のtimer()に記述するとおり、Tkのafterメソッドにより繰り返し 50 ms 間隔でtimer()が呼び出されることで実現されていることに注意。timer()は、呼び出されるとself.timer_funcに手続きがセットされているか否かを調べ、セットされていればその手続を実行する。その後、afterメソッドにより 50 ms 後に再度timer()が呼び出されるようにセットして、“現在の”timer()は終了する。ここで、イベントによる処理が一旦終了することに viewer.py との差異がある。
タイマーによる意図した動作の実現
start_window()が呼ばれ、tkのメインループが開始された後、STARTボタンに関する処理は概して次のように動く。
- 処理待ち状態
- STARTボタンが押される
- 「ボタンが押された」というイベントにより、52-53行目のset_timer_func()が呼ばれ、self.timer_funcに“self.start()”という手続きがセットされる(39行目参照)
- 1に戻る
ここまでに、「データをセット」や「描画」などの手続きは含まれていない。あくまで「関数をセット」しただけである。「繰り返し波形を描画する」という手続きは、くどいようだがタイマーによって実現される。
- 処理待ち状態
- タイマーによる(50ms間隔で定期的な)イベント発生
- 「タイマー」というイベントにより、timer()が呼ばれ、self.timer_funcにセットされた手続き(=self.start())が呼び出される
- [l.104] self.cycleが200未満のとき105行目以降を実行、それ以外は112行目以降を実行(「それ以外」は説明省略)
- [l.105] 波形データの生成
- [l.107] データの事前処理
- [l.108] 波形の描画
- [l.109] ループ変数をインクリメント
- タイマーが再度セットされる
- 1に戻る
ポイントは、viewer.pyにおいて、「繰り返し描画」がwhileループにより実装され、その全てが一度の「ボタンが押された」というイベントで開始されていたところを、viewer_rev.pyでは「タイマー」によるイベントで「1回の描画」を繰り返し呼び出す点である。この変更によって、「1回の描画」が終わるたびに制御がGUIに戻り、周期が変化する過程の波形も1個1個表示することができる。
ついでだが、viewer_rev.pyで波形の繰り返し表示がうまくいったので、STOPボタンを実装した。STOPボタンをクリックすることで、波形の描画を途中で止めることもできる。
まとめ
というわけで、GUIプログラミングで意図した動作は実装できた。
しかし、このプログラム、実行してみればわかると思うが、波形の描画を繰り返すごとにだんだん動作が重くなっていく。このことについては私の中で解決できていない問題なので、どなたか詳しい方が教えていただけると有り難い。
なお、あとで書くつもりの「PythonでGUIプログラミング (2)」では、別のGUIライブラリである wxPython を使用し、遅くならないプログラムを書いたものを紹介する。個人的には、wxのほうがTkより洗練されている印象を持っている。内部でOSのAPIを直接呼び出しているためか、見た目もTkより綺麗なのが特に好印象。
気づいたらすごく真面目な調子の文章になってしまったので「だ・である調」やめようかしら('ω')
2015年1月12日月曜日
普段書かないC++でライブラリ使うのに苦労した話
新年のご挨拶
あけましておめでとうございます。
著者多忙により最近更新頻度が減っておりますが、一応生きてます。
今年もどうぞよろしくお願いします。
外部のライブラリ入れようとして苦労した
最近、昨年の夏ぐらいから温めていたアイディアを具現化すべく、C++でコードを書いています。
些末なことですが、C++を選んだ理由は、Windows環境でもLinux環境でもスタンドアロンで動く実行形式にコンパイルし易いことと、GUIアプリケーション制作のためのライブラリが充実していること、Visual Studio等の補助を受けやすいこと、Cと同じ文法で一応通用すること、などです。ちなみにLinux環境でも動かせるようにとのつもりで最初はC++にしたわけですが、実質Winodws向けのライブラリを多用しているので結局Windows向けアプリになりそう。まぁ僕はそれで困らないからそれでいい。
話が逸れました。
本題に戻りますが、今回、プログラムの中で離散フーリエ変換(DFT)を計算する必要がありました。DFTを計算するコードは自分で書いても良かったのですが、任意の長さのデータ列に対して適用する方法がなかなかわかりやすく説明されているサイトを見つけられず、また私の数学の知識では少々難しく(というより調べるのが面倒になった)、それに速度も出ないだろうということで既存のライブラリを探すことにしました。
そんなわけで、FFT(高速フーリエ変換)でググると真っ先に出てくるのがFFTWでした。とりあえず速いらしいので早速使うことに。
……どうやって使うんだろう。
はい、Rubyとかだったら、別ファイルに記述されているコードを読み込むには require "hogehoge" で終わったわけですけど。
単純に #include
そもそも、私はこれまで .dll とか .lib とかいうファイルの意味もよく分かってなかった雑魚なので、そういえば外部のファイルってどう使うんだろうとそこでハマってしまったわけです。雑魚なので。
そもそもプログラムをコンパイルするプロセスは
インタプリタ言語なら、(中間言語を介する場合もあるが)言語自体をそのまま解釈して実行するだけですが、CやC++のようなコンパイルして使う言語は、一旦プログラムを個別にオブジェクトファイル(≒実行ファイルの一部)に翻訳(コンパイル)した後、プログラムのなかで呼び出している外部のライブラリの機能を使用するため、「リンカ」によってそれらを結合させて初めて実行形式になります。
こういうストーリーの中で、 .dll とか .lib ってどういう立ち位置なんだろうか。
.dll って何なのか
Windowsのプログラムファイルの種類の一つで、様々なプログラムから利用される汎用性の高い機能を収録した、部品化されたプログラムのこと。
DLLファイルはそれ自体は単体で実行することはできず、実行可能ファイル(EXEファイルなど)が起動する際に自動的に連結されてメモリ上に展開される。多くのプログラムが共通して必要とする機能が収められており、様々なプログラムの一部として取り込まれて実行される。
DLL : IT用語辞典より引用
DLLファイルは、単独では実行できないオブジェクトファイルであり、他の実行可能なプログラムにリンクさせることで機能が使用できるライブラリなんですね。
.lib って何なのか
リンカー入力としての .lib ファイル を読んでみるも、イマイチよく分からない……。
要するに .lib ファイルというのは、プログラムのコンパイル時にリンカに対して「hoge.dllにはこういう関数や定数やクラスが記述してありますよ」ということを示すためのファイルのようです。
……あれ? .h ファイル(ヘッダファイル)も、関数のプロトタイプ宣言とか書いてあると似たような役割をしているような。
ヘッダファイルはその場で展開される
ヘッダファイルはあくまでソースコードであり、コンパイラが #include と記述されている位置で当該ファイルのコードを展開して解釈するようです。 .lib ファイルがリンカによって使用されるのとは性質が異なります。
で、FFTWを使ってみる
FFTW3のWindows用バイナリファイルをダウンロードしてzipを展開すると、各種ベンチマーク用ツールとかドキュメントとかと、.dll ファイル、.h ファイル、.def ファイルが入っていて、.lib ファイルが入っていません。どうやって使うんだろうと思って調べると、どうやら"LIB"と呼ばれるツールを使って、.def ファイルから .lib ファイルを生成できるらしい(fftw - HUROBINT)。
さて、.lib ファイルもできたのでいよいよ自前のプログラムに組み込んでみる。
結論として、プログラムに次の加筆をすることで .dll を呼び出して使えるようになるようです。
#include "fftw3.h"
#pragma comment(lib, "libfftw3-*.lib")
FFTWでは扱う浮動小数点データの精度で3種類くらい libfftw3-*.lib 及び libfftw3-*.dll の同種のファイルがありますが、僕は倍精度のを使うのでこのように記述しました。
fftw3.h 及び libfftw3-*.lib は、コンパイラが見つけられるところに置きます。僕はとりあえず他のソースコードと同じディレクトリに置いたら動きました(適当)。
上述のとおり、fftw3.h はライブラリに含まれる関数のプロトタイプ宣言のために必要で、libfftw3-*.lib は libfftw3-*.dll をリンクするために必要です。どちらが欠けても動きません。
また、libfftw3-*.dll はコンパイラが出力する実行ファイルと同じディレクトリに置いたら動きました。――本当に僕のコーディングのプロセスは適当だな(^ω^;)
まとめ
普段お手軽言語ばかり使っていると、なかなか一般的なアプリケーションがどのように動いているのか知る機会が無いのですが、今回はその一端を知ることができました。CとかC++って難しい。
でも、個人的には、C や C++ くらいがほどよい抽象度・機能性を持った言語なんではないかと。――いろんな方面からつつかれそうなことを書いてしまった。
……さて、そろそろ現実逃避やめて発表スライド作るか。
2014年10月6日月曜日
土浦の花火見てきた
なんか最近ひたすら花火を見に行ってる人のブログになりつつありますがそんなことはないと思います多分。
土浦花火は今年が初参加なので、今回は視察というつもりで見に行きました。もちろん花火はちゃんと楽しみましたが。
そんなわけで、色々と書きとめておきます。特に、『大曲の花火』のときとどう違ったか、など。
会場入りまで
10時半ころ仙台で買い出し、11時ころ仙台南インターより南下開始。東北道、磐越道、常磐道と経由して土浦北インターまで。途中、常磐道に入ってから中郷SAで昼食をとり、土浦に着いたのは15時頃だったと思います。
あ、お昼に食べた『あんこうから揚げ丼』おいしかったです。
インターを降りてからは、土浦市内で駐車場探しです。さすがにこの時間帯では、会場に近い、土浦駅西側の駐車場は大会用臨時も一般の有料駐車場もほとんど満車になっていました。
結局、打ち上げ場近くから徒歩40分程度の、霞ヶ浦近くの大会臨時駐車場に止めました。

霞ヶ浦 pic.twitter.com/AQNRn4f4vc
— NKK-RN (@echo_ymbk) 2014, 10月 4
霞ヶ浦をちょろっと見られるということで良いんじゃないですかね。ガラガラでしたし()。
どうもここの駐車場が完全に埋まることはついぞ無かったのではないかという気がしています。
私の見解としては、首都圏から鉄道でのアクセスが良いこともあり、あとは東北からの客がおそらく少なそうなこともあり、大曲に比べると自動車の総数は少ないように思います。
逆に鉄道を利用して花火を見に首都圏からやてくる客が多そうで、そっちは大変そうです。
さて、駐車場からは徒歩移動。途中、生協に立ち寄って飲み物やおやつを調達し、会場入りしました。
会場の様子

きてるなぁ pic.twitter.com/RC8J0Hr8jx
— NKK-RN (@echo_ymbk) 2014, 10月 4
「あ、浴衣の人いる……」「客に緊張感が無い……」
大曲の花火大会くらいしか行かないので花火大会の会場はいつも戦場だと思っていた節があるのですが(私←)、土浦の花火は大曲と比べるとだいぶゆるい雰囲気が漂っています。
さて、肝心の場所取りはといいますと、川から堤防までの平地がきわめて狭いため自由観覧席自体がそれほど広くないのと、会場入り時刻が遅かったということで、メインの自由観覧席は既にいっぱいでした。
このため、打ち上げ場から少し離れた川原に陣取るか、川の対岸の、打ち上げ場に近い土手(道路)に陣取るかということになりましたが、今回は打ち上げ場にごく近い場所で、周りのお客さんに少しスペースを譲っていただき、シートを広げることになりました。
この頃すでに時刻は17時近くでしたが、まだぎりぎり陣取るスペースは残されていたように思います。
もちろん、見やすそうな場所にはもうシートが広げられていましたが。
花火が始まる
始まる前ですが、なにやら花火の歴史とかそんなことについて色々説明があったような気がします。
私は先輩とマリオカートで対戦していたのでよく聞いていませんでしたが。

たのしい pic.twitter.com/OQXnRdKBww
— NKK-RN (@echo_ymbk) 2014, 10月 4
花火大会のオープニングは、大曲と比べるとかなりあっさりとした印象でした。
競技大会のメインで打ちあがる花火は大曲と大体同じで「10号玉」「自由花火」「スターマイン」とあり、「スターマイン」とかいうプログラムが、音楽に合わせて花火を打ち上げるアレでした。
今回は『来年の大曲の練習』と称して三脚を持ち込み、写真をけっこう撮りましたので下のほうに貼っておきます。
全体的な感想としては、競技花火は大曲と遜色ない見ごたえでした。オープニング・大会提供・エンディングなどもそれなりに面白かったのですが、大曲に比べるとやや物足りない印象でした。別に土浦の花火をdisるつもりはないんですが。
それから、今回は陣取った場所が打ち上げ場に近かったため、花火は大きく見え、音が大きく聞こえたのは良かったと思います。
会場脱出
大曲なら、ここからが本当の戦いなわけですが、会場脱出にはまったく苦労しませんでした。道を歩く人も大曲と比べるとほとんど人がいないも同然で(誇張)、車の流れに関しては会場周辺が多少詰まっていたくらい。会場から少し離れれば車は普通に流れていました。大曲程度の混雑はなく、大会の最後まで花火を見てもすんなり土浦市を脱出できました。
ただし、土浦駅方面に向かう人の流れはどうだったかわかりません。帰りの車中で、土浦駅に結構な密度の人混みが確認できました。
高速に乗るまで
今回は、色々メンバーが悪乗りしたせいで全工程を下道で帰ることになりましたが、一応どんな様子だったかをちらっとまとめておきます。
北に向かう場合は、まず、国道6号線は混みます。予想としては『千代田石岡IC』あたりまで混んでいたのではないでしょうか。痺れを切らして並行する市道・県道に入ってみましたが、こちらは車の流れは実にスムーズでした。
また、石岡市に入ってからは6号線も流れていました。
大曲ほど殺気立って車を運転する必要は無さそうです。
その後
このあとは色々とあったわけですが面倒くさいので割愛します('ω')
まとめ
大曲ほど混みません。車勢大勝利です。
ただ、現地入りは早いほうが良いと思います。
あと、夜は「砂浜が見たい」とか言って下道で帰るようなことはしないほうが良いと思います。
それから、せっかくなのでデニーズで夕飯を食べましょう(?)。
以下、写真













