jj1gujのブログ

アイコン画像は音速の奇行子 様よりいただきました

ABC150参加

ABC150に参加しました.
unratedになってしまいましたね.
コンテスト成績はこちら
今回はPythonで3完でした.

A問題

 500K \geq Xかどうか判定して終わりですね. はい.

B問題

文字列中に"ABC"がいくつあるか数えて終わりでした.

C問題

制約から全列挙で行けることがわかったためPythonのitertoolsを使ってとりあえず全ての順列を列挙しました.
その後、線形探索で与えられた数列がどこにあるか探し、その差の絶対値を取って終わりでした.

D問題

問題文から式変形をし、 X=\frac{a _ {k}}{2} (2p+1)となればいいことが分かり、そこからどうするか考えてたところでunratedが発表されたため、考えるのをやめました. はい()


今回久しぶりに全てPythonでのACでした.
できればどこかでFortranを使えばよかったかもしれません.
なんだかんだ17分で3完できたためratedだったら700超えてたかもですね…
とりあえず今年はレート1000超え目指してがんばります.

アマチュア無線について思うこと

あけましておめでとうございます.
すっかり寝正月ですね*1.
今年もよろしくお願いします.
さて、今日はアマチュア無線関連でTLが少しざわついたのでそのことについてつらつら書いていこうかと思います.

目次

わたしはだれ?

  ぼくはアマチュア無線とプログラミングが好きな大学生です.
最近は卒研配属関連で鬱になってるよ.
アマチュア無線は大学に入ってから始めました.
もともと高校生の時にBCL*2をやってて、そこからアマチュア無線の存在を知りました.
現在は個人局(JJ1GUJ)や社団局(JR1ZTT)コールサインで通常交信からコンテストまで幅広く出ています.
好きな周波数帯は遠くの局と通信できるHF帯で、好きなモードはCW*3です.
詳細はこちらを見てください.

jj1guj.github.io

元ネタというか事の発端と言うか…

  元ネタはここら辺ですかね.

まぁ今回はここら辺を受けて自分自身がアマチュア無線のことをどう思っているかつらつら書いていこうと思います.

アマチュア無線の利点

  アマチュア無線をやる上での利点とするとここら辺があげられるかと思います.
・kHz帯からGHz帯まで幅広い周波数帯で免許を下ろし、運用することができる
・FT8やCWをはじめとするデジタルモードや電話など様々な変調方式で電波を出し通信を行うことができる
  個人的にはAMラジオで使われている周波数帯からスマホで使われている周波数帯まで幅広く使えるのは素晴らしいことだと思っています.

アマチュア無線の欠点

  欠点としてはここら辺が挙げられると思います.
・初期コストが高い
・(いろいろな意味で)ビギナーに優しくない
・やりたいことがあっても情報が見つからない
  やはり初期コストの高さは学生ハムの参入を妨げている大きな要因かと思われます.
多くのビギナーがまず受けるであろう第3級アマチュア無線技士の試験手数料と免許申請料だけで7,000円近くになってしまいます.
そこからさらに開局しようとなると少なくともさらに2万円かかります.
よっぽどやる気がない限りなかなかやる気になれませんね.
一応弊社団では合格した場合や開局する場合には試験手数料や開局申請手数料をはじめとする各手数料は全て部費から支払ってくれる制度があります.
おそらく他社団でもこのような制度があるかと思われます*4.
  (いろいろな意味で)ビギナーに優しくないというのは実際に自身で免許を取得し、交信するようになった時に最も実感したことです.
「この周波数帯はラグチュー*5するための周波数帯だからラグチューする気ないなら電波出すな(意訳)」と言われておじいちゃんのつまらない話に付き合わされたり「30年前のQSLカード*6が来てない、はよ送れ*7」と言われたりして正直やる気無くしました*8.
このような経験を回避するためにはCW等のデジタルモードに逃げるのが手っ取り早いのですが、別途申請が必要だったり訓練をしなくてはならなかったりとなかなか辛いものがあります.
  最後にやりたいことがあっても情報が見つからないというのはぼく自身のサーチ能力がアレというのもあるかと思われます.
ただ仮に情報が見つかったとしても情報量がほぼゼロだったり内輪ネタが多かったり文体が読みづらかったり*9してとりあえずMPが削られます.

むすび的な何か

い か が で し た か 笑 ?
正直なところを述べると先に述べた欠点のうち初期コストの高さは仕方ないにしても残りの2点においてはなんとかしたいよねって感じです(そんな権限はないですが)
特に情報量の少なさについてはいろいろアマチュア無線使って遊んで(そんな余裕あるのか?)その記事を書いていって微力ながら貢献しようと思っています.
まぁこんな感じにいいとこも悪いとこもあるよねって感じです()
(ToDo: 言葉がまとまったら整備する)

参考文献

第三級及び第四級アマチュア無線技士国家試験案内

各級アマチュア無線技士 免許申請のご案内

総務省|関東総合通信局|【申請手数料】申請手数料及び申請用紙の購入先について

*1:ぼくはお雑煮を食べた後爆睡したけど、君は?

*2:ラジオとかテレビの放送を受信して放送局に受信できたよ〜っていうお手紙を送ってベリカードといわれる絵はがきのようなものを集める趣味

*3:いわゆるモールス通信のこと

*4:意外とないっぽい??(よくわからん)

*5:長話のこと

*6:交信した時に交換するカードのこと

*7:そんな前のデータなんてないに決まってる、きっと

*8:まぁその点から見るとよしなにぶった切って電源オフにしてもいい気がする

*9:諸説あるが文末にhiとかつけられると読む気なくす

Github Pagesでテーブルを表示させる方法

Github PagesでMarkdown記法でテーブルを書くとうまく表示されないという問題があったため、これを解決する方法をメモっておきます.

あらまし

僕は自分のwebページをGithub Pagesを使って公開しています.
Github PagesとはGithubMarkdownで書いたファイルをあげるとwebページで公開してくれるなんか、そう、すごいやつです(詳細はググってください).
そこで、自分が出場したアマチュア無線のコンテスト成績を公開しているのですが、その際に以下のように表示されてしまう問題がありました.
f:id:jj1guj:20191220011358p:plain
ちなみにリポジトリ上で見ると下のようにうまく表示されていました.
f:id:jj1guj:20191220011420p:plain

解決方法

どうやら上の事象からMarkdown記法では効かないっぽいのでHTMLで書いたところ、うまく表示されるようになりました.(なんでかは知らん)
f:id:jj1guj:20191220011428p:plain HTMLでの表の書き方はこちらを参考にしてください.

HTMLのtableでテーブルを作る方法と応用テクニックを解説 | webliker

また、CSSで表のスタイルを指定することもできます.
MarkdownCSSを適用させる方法はこちらを参考にしてください.

qiita.com

なんか原因を知っている方がいましたら教えてくださいm(_ _)m

知的・機能工学システム応用実験軌道生成ツールの解説

弊学では秋学期(10月~2月)にという各テーマごとに10人ほどに分かれ、3ヶ月間同じテーマに取り組む知的・機能工学システム応用実験という授業があります。
テーマはFPGAを使って何か実装したり跳躍ロボットを作ったりとハードからソフトまでかなり幅広いです。
僕はその中でロボットシステムという2軸マニピュレータを設計し、実際に動かすというテーマに取り組んでいます。
実際に動かしている様子はこちら↓

このテーマでは実際に2軸マニピュレータを動作させる際に時間ごとの角度情報をプログラムする必要があります。
一応便利ツールとしてExcelファイルが配布されるのですが編集するのに時間がかかりかなり不便なため、これをC++で実装しました。
実装したものはこちらにあります↓

github.com

今回は実装したものの中身というか原理というかを解説しようと思います。

目次

課題の概要

  今回の実験では指定されたコース(直線コースの往復とクランクコースの片道)をなるべく短い時間で動くよう、2軸のマニピュレータのリンク長を設計し、そのリンク長で最も早く動くプログラムを作成することとなっています。
リンク長は可動範囲がA4コピー用紙内全ての場所であればどのような長さ、幅でも問題ありません。
今回の軌道生成ツールはSolidWorksでのモーション解析や実機での動作用に作成したものとなっています。

手先速度の設計

  まず、手先の並進速度をどのようにするかを決定します。
  最初に思い浮かぶのは動作開始から動作終了まで終始一定速度で移動させることだと思います。
一定速度で終始動かすと下のグラフのように、動作開始時と動作終了時に加速度がとても大きくなります。

f:id:jj1guj:20191218162100j:plain
動作速度が常に一定の時の並進速度と加速度
回転体の運動方程式から、モータにかかるトルクは加速度に比例します。
そのため、これだとモータに大きな負荷がかかってしまい、モータのパフォーマンスを十分に生かせなくなってしまいます。
  これを解決するために動作開始時の加速度を小さくすることを考えます。
下のグラフのように加速度を小さくすると今度は加速時間を長くしなくてはならないことが分かります。
f:id:jj1guj:20191218162155j:plain
加速時間を長くし、加速度を小さくした時の速度曲線と加速度
そして、このときの速度曲線は上のグラフのように台形となることが分かります。
このような速度曲線を台形速度曲線といい、今回の手先起動の制御ではこれを使用します。

各時間ごとでの手先位置の設計

  並進速度の速度曲線を決定したら、次は各時間ごとのマニピュレーターの手先座標を考えていきます。
今回は指定されたコースをなるべく短い時間で動かすという目的であったため、加速度を調整するパラメータにしてしまうと直感的にどのくらい早くなるか見積もれません。
そこで、加速終了時刻と減速開始時刻を調整するパラメータとすることで簡単に動作時間を見積もれるようにします。
もし加速時の加速度の絶対値と減速時の加速度の絶対値が同じであれば動作時間は加速終了時刻と減速開始時刻の和になるためです。   この時、加速度と定速時の速度はどのように表すことができるか考えていきましょう。
下のグラフのように加速終了時刻を t _ {1}、減速開始時刻を t _ {2}とします。

f:id:jj1guj:20191218162314j:plain
考える速度曲線
また、加速時の加速度を a、減速時の加速度を -a、定速時の速度を vとします。
  この時、マニピュレータが動く道のり Lは上の図の台形の面積に等しいので
$L= vt _ {2}$ 、  v=at _ {1}から
$$L=at _ {1}t _ {2}$$ $$a=\frac{L}{t _ {1}t _ {2}}$$ よって a=\frac{L}{t _ {1}t _ {2}} v=\frac{L}{t _ {2}}となることがわかります。
  次に、加速終了時刻と減速開始時刻はそのままとし、原点 oから点P (p _ {x},p _ {y})まで台形速度曲線に従い動かすことを考えます。この時、 x軸方向に進む道のりは p _ {x} y軸方向に進む道のりは p _ {y}であるため、 x軸方向の加速度は $$\frac{p _ {x}}{t _ {1}t _ {2}}$$  y軸方向の加速度は $$\frac{p _ {y}}{t _ {1}t _ {2}}$$ となります。
加速終了時のマニピュレータの手先位置を (p _ {xt1},p _ {yt1})、減速開始時のマニピュレータの手先位置を (p _ {xt2},p _ {yt2})とすると各時間ごとのマニピュレータの手先位置 (x _ {t},y _ {t})
$$ (x _ {t},y _ {t})= \begin{cases} (\frac{p _ {x}t^{2}}{2t _ {1}t _ {2}},\frac{p _ {y}t^{2}}{2t _ {1}t _ {2}}) & (0 \leqq t \leqq t _ {1}) \\ (p _ {xt1} + \frac{p _ {x}(t-t _ {1})}{t _ {2}},p _ {yt1} + \frac{p _ {y}(t-t _ {1})}{t _ {2}}) & (t _ {1} \leqq t \leqq t _ {2})\\ (p _ {xt2}+\frac{p _ {x}(t-t _ {2})}{t _ {2}}-\frac{p _ {x}(t-t _ {2})^{2}}{2t _ {1}t _ {2}},p _ {yt2}+\frac{p _ {y}(t-t _ {2})}{t _ {2}}-\frac{p _ {y}(t-t _ {2})^{2}}{2t _ {1}t _ {2}}) & (t _ {2} \leqq t \leqq t _ {1}+t _ {2}) \end{cases} $$ となります。

2軸マニピュレータの逆運動学を解く

  逆運動学を解くということは、簡単に言うと「与えられた座標から各モータのモータ角を求めること」です。
今回は座標とそれぞれのモータ角を下の図のようにとります。

f:id:jj1guj:20191218162338j:plain
座標とモータ角の定義
この時、 \theta _ {1} \theta _ {2}はそれぞれ
$$ \begin{cases} \ \theta _ {1}=\pi - \tan ^{-1} \frac{y}{x}- \cos ^{-1} \frac{x^{2}+y^{2}+L _ {1} ^{2}-L _ {2} ^{2}}{2L _ {1} \sqrt{x^{2}+y^{2}}}\\ \ \theta _ {2}=\sin ^{-1} \frac{x^{2}+y^{2}-L _ {1} ^{2}-L _ {2} ^{2}}{2L _ {1}L _ {2}} \end{cases} $$ となります。
実際にSolidWorksや実機で動かす際にはラジアンから度に変換しなくてはならないので注意してください。

プログラムへの実装

  ここまできたらあとは実装するだけです!
基本的なアルゴリズムとしては時間ごとの座標を求め、それに対応するモータ角を算出するという方法で問題ありません。
CSVへのファイル出力は、

#include<fstream>
#include<iostream>
using namespace std;

int main(){
    ofstream output;
    output.open("hoge.csv",ios::out);
    output<<0<<","<<"Hello World!"<<endl;
    return 0;
}

とすれば出力できるはずです。 なお、コンマと改行をつけ忘れると実機やSolidWorksに読み込ませることができなくなってしまうのでお忘れなきよう….

今後の展望

とりあえず時代はGUIなのでQtのお勉強してGUI化しようと思います。
あとは作成したプログラムだとクランク起動では各コーナーでいちいち停止してしまってるのでこれを解消するようにしようと思います。

参考文献

回転運動の運動方程式

追記

  • 2021/12/16 そういえばこのときに作成したリポジトリが南極に埋められました(今更)f:id:jj1guj:20211216134234p:plain

archiveprogram.github.com

三井住友信託銀行プログラミングコンテスト2019 参加

三井住友コン参加しました.
問題はこちら
結果はこちら

いつもとかわらず3完でした(4完したかった…) 今回はFortran、Python3、C++と全て違う言語で出しました~

A問題

Fortranで提出しました.
入力された2つの月が異なるとき末日になるのでこれで実装し提出しました.

B問題

Python3で提出しました.
ごちゃごちゃ考えるのが面倒だったのでとりあえず1円から N 円までループを回して、税込価格が N円と等しくなる iが存在するときにはこれを出力し、ないときは':('と出力しました.

C問題

C++で提出しました.
入力された価格 Xを100で割った商が買える品物の個数だと考えました. そのため、あとは Xの下二桁を作るには少なくとも何種類の品物を買えばよいか考え( X \equiv 0\ mod 5なら Xを5で割った商、それ以外なら Xを5で割った商に1を加えたもの)、これが買える品物の個数を超えていたときには'0'、超えていないときには'1'を出力するようにしました.

D問題

ずっと考えていたのですが、時間切れで最後までわかりませんでした.
とりあえずコンビネーション計算を使えば良いと考えていて、あとは重複する組み合わせをどうやって排除するかでずっと悩んでいました(最終的にわからずに諦めてずっとついったやってた).

D問題、解説に書いてあった全探索の解法が頭良すぎてずっと泣いてました.
どうやったらあんな天才解法思いつくんだろう...
あとはF問題が解説読んでみた感じ割と簡単そうだったのでDを捨ててFでずっと考えてたほうが良かったかもですね...
とりあえず今回レートがちょっと回復したので学年変わるまでに緑色になれるよう頑張りたいと思います.

ラズパイ4を買った

レポートの現実逃避で書いてます…
11/25に発売されたラズパイ4、買いました!

あきばお〜で購入すると8 GB MicroSDもついてくるとのことだったので、ここで購入しました.
あとは千石でMicroHDMI-HDMIの変換ケーブル、ケース、USB TypeC-USB TypeAの変換ケーブル、ヒートシンクを購入しました.
お家に帰ったらとりあえずRaspbianをインストールすることに.
公式からダウンロードしてきたのですが、ありえんほど重い…
結局ダウンロードが完了するまでに4時間程かかりました.

みんな、ミラーからダウンロードしような.
まぁそんなこんなあったものの、無事起動できました~.
とりあえず今は普段遣い的な感じで使ってます(Mなのかな?)↓

使い心地としてはちょっと重いかな?ってくらいで全然問題なく使えますね.
ただいかんせんCPU温度が高い(アイドル状態で50℃超える)のでお金たまったら専用ファン買ってつけます.

ABC145参加

ABC145参加しました~
結果はこちら
2完しかできず詰みました…
コンテスト中はすべてFortranで出しました.

A問題

  円の面積は \pi r^{2}なので r^{2}を出力して終わりでした.

B問題

  Nが偶数かつ文字列の前半分と後ろ半分が同じときのみYesと出力するようにしました.

C問題

  とりあえず3と4のときの順列を列挙して手で数えてみたところ、特定の隣り合う2つの組み合わせが 2^{N-1}回出てくると勘違いして、各点間の距離の総和に 2^{N-1}/N!をかければよいという結論に至り、実装して試してみたらサンプルケースで見事にコケてしまいました(それはそう). そのため、全探索するかぁってモチベーションになったものの、やりかたがよくわからず、時間がかかりそうだったのでしばらく迷ってから諦めました.

D問題

  与えられた条件から、到達できる点は下の図のように格子状に存在することがわかりました.

f:id:jj1guj:20191117010137j:plain
図1  与えられた条件で到達できる点の分布
ここから、入力された点 (X,Y)が到達できるかどうか判定して、あとはで求めれば良いことがわかったので到達できる点かどうかの判定方法および n rの求め方を考えていくことにしました.
  まず、到達できる点かどうかの判定法です.
  図1から、
$$y= \frac{x}{2}+b \tag{1}$$ は必ず
$$(a, 2a) ただしa \in \boldsymbol{N} \tag{2}$$ を通ることがわかります. よって、ここから式(1)の bを求めると、 $$2a= \frac{a}{2}+b$$ $$b=\frac{3a}{2}$$ これと (X,Y)を式(1)に代入し、 aについて解くと、 $$Y= \frac{X+3a}{2}$$ $$a=\frac{2Y-X}{3} \tag{3}$$ よって、式(2)から 2Y-Xが3の倍数でないと到達できないことがわかります.
  次に、 n rを求めます. 図1において、目的地まで原点から上方向にいくつ進まなくてはならないかは、入力された点 (X,Y)を通り傾きが \frac{1}{2}である直線と y=2xの交点の x座標に等しいことがわかります. これは、式(3)と等しいので、これを使います. 横方向には、今度は点 (X,Y)を通り傾きが 2である直線と y=\frac{x}{2}の交点の y座標と等しいことがわかります. よって、これを求めていきます. 点 (X,Y)を通り傾きが 2である直線を $$y=2x+c \tag{4}$$ と置き、 (X,Y)を代入して cを求めると、 $$c=Y-2X$$ よって、式(4)と y=\frac{x}{2}の交点の座標 (l,m)は $$2l+Y-2X=\frac{m}{2}$$ $$l=\frac{2(Y-2X)}{3}$$ よって、 y座標は $$m=\frac{l}{2}=\frac{Y-2X}{3}\tag{5}$$ であることがわかります.
よって、式(3)および式(5)から、 $$n=a+m=\frac{X+Y}{3}$$ $$r=min(a,m)$$ であると求められました.
ここまできたら後は実装するだけだったのですが、効率のよいコンビネーションの求め方がわからず、ひたすらググっていました…
結局、こちらのサイトに載っていたコードを使用させていただきました.
【Python】組み合わせ(nCr) 計算の高速化 - Qiita
ただ、これで実装できたはいいものの、終わったのがコンテスト終了直後という悲しい結末… しかも、提出してみたら普通に通ってしまったという悲しさ…

終了20秒後に出したのが通るとかなんなん…
終わってからずっとほえてました…

反省とか

よかったところ: Fortranの実装速度が上がった
悪かったところ: B問題に見切りをつけるのがおそすぎた
結局レートはちょっと下がってしまいました...(100くらい下がるかと思ってたけどそうでもなかった)

とりあえず来週もABCあるのでレートを戻せるようにがんばります.
あと4~5回くらいで緑色になりたいなぁ…