1 準備
- GoogleColab.
にログインしておいてください。
- 「
PG1-第11回講義.ipynbという名前でノートブックを作成しておいてください。 - 今回はノートブックの提出はありません。
- 「
- 最後に 課題05 の予告があります。
2 課題04 (予告)
現在までのプログラミング学習の集大成として「7月30日 (火) 23:00」を期限とする 自由課題 に取り組んでもらいます。
- 参考 : 昨年度の作品
提出場所などの詳細については次回以降の授業で説明しますが、以下の要件で実施予定なので、取り組みをはじめてください。
- GoogleColab.上で実行可能なものとしてください。Colab.環境で
pipを使ってライブラリを追加することもOKです。 - 提出された課題は 本校の学生と教員に公開 します。公開可能な内容としてください。公序良俗や著作権などに反しなければ、テーマについて制限はありません。
- この課題には 最低でも10時間以上 を費やして取り組んでください (本科目は前期末試験がありません、試験勉強に相当する時間と熱量を投資してください)。
- テキストセルに プログラムの解説など を記述してもらいます。
- 現在までに、この授業で学習したことを最大限に取り込んだ内容を期待しています (この授業で習っていない技術やライブラリを組み込むことも歓迎・推奨です) 。
- ICT分野の インターンシップ (4年生) や
就職活動などでは、ポートフォリオ (作品集)
が必要になってきます。そのための準備という位置づけでも頑張って取り組んでください。
- 例: https://internship.team-lab.com/
- 例: https://www.jig.jp/news/topics/20240411_01
- 例: https://prtimes.jp/main/html/rd/p/000000385.000005362.html
- ウェブエントリの項目「現在までに自分で作成してきたアプリやウェブサービスなどの成果物について記述してください。公開しているURLあれば記載してください。」
- ポートフォリオとしての質を考えた場合、コメントの有無や内容、可読性、保守性、再利用性などもポイントとなります。
3 復習: 実行開発環境の構築
今後、授業のなかで練習時間は確保しませんが、必要に応じて以下の手順で Pythonの仮想環境の新規構築がスムーズにできる ようになっておいてください。指示があったときは、以下について (ライブラリのダウンロードとインストールの待ち時間を除いて) 5分以内 にできるようになっておいてください。
- プロジェクトフォルダの作成、VSCodeによるフォルダのオープン
- 仮想環境の作成
python -m venv .venv
- 仮想環境の有効化
.venv/Scripts/Activate.ps1
- pipのアップグレード
python -m pip install --upgrade pip
- 必要パッケージのインストール
pip install XXXXX
- 動作確認用のプログラムファイルの新規作成
- 通常プログラムなら
xxxx.py - ノートブックプログラム (=Jupyter環境を要インストール ) なら
xxxx.ipynb,
- 通常プログラムなら
- プログラムの実行と動作確認
慣れるまでは 週1で練習してください。
4 ファイルネームに関する注意
Jupyter環境 (GoogleColab.環境) 以外で、プログラムファイルを作成する際は、ファイル名に 日本語やスペース (半角も全角も) 、ハイフンなどを絶対に使用しないでください。
また、プログラムのなかでインポートしているライブラリ (モジュール) と 同じ名前のPythonファイル名をつけないでください。
例えば、プログラムのなかに import random
という文を含む場合、そのプログラムファイルに
random.py という名前を付けたり、同フォルダに
random.py というファイルが存在すると 実行時エラー が発生します。
初心者によくあるミスなので注意してください。
4.1 演習1 ( 目標時間: 10分)
ローカルに構築した仮想環境
(=新規作成は不要。前回講義で作成した PG1-10
をそのまま利用すればよい) で pip install numpy
を実行して、numpy をインストールしてください。
.venv/Scripts/Activate.ps1
pip install numpy
既に、仮想環境に numpy がインストール済みであれば
pip install numpy は省略可能です
(再度、実行しても問題はありません)。
仮想環境の明示的な有効化
VSCodeは起動時に、.venv
フォルダの存在を検知して、自動的に仮想環境を有効化
します。ただし、タイミングの問題などで、仮想環境が自動的に有効化されない場合もあります。その状態で、pip
を実行すると、ライブラリが (仮想環境ではなく)
グローバル環境 (共通環境)
にインストールされてしまいます。
グローバル環境にライブラリがインストールされると、ライブラリ同士の依存関係の問題で根深いバグや不具合を引き起こす可能性があります。特に複数のライブラリを組み合わせて大規模な開発をするときに起きます。
そのため、上記では .venv/Scripts/Activate.ps1
のコマンドで 明示的に仮想環境を有効化
しています。
なお、現在、有効になっているPython環境は、PowerShellで以下のコマンドを打って確認できます。表示されたパスに、VSCode内の
.venv
が含まれていれば仮想環境が有効化されています。
Get-Command python | Select-Object -ExpandProperty Definition
なお、そもそも「仮想環境とは何なのか?」が分からない人は、以下のプロンプトで生成AIに質問してください。
Pythonプログラム開発では、仮想環境を構築して、それを有効化して作業するように言われます。そもそも「仮想環境」とは何ですか。それを使うことによるメリットはなんですか。使わないと何が問題なのですか。プログラミング初学者の高校2年生が理解できるように分かりやすく説明してください。専門用語の使用はできるだけ避けて、分かりやすいたとえで説明してください。
次に np-01.py
という名前で「Pythonファイル」を新規作成してください。そして、以下のプログラムを貼り付けて「期待する結果」が得られるように
np.arange の第2引数を調整してください
(サンプルとして提示のプログラムでは 5.00
が表示さません)。
なお、np.arange については 前回講義
で既に解説済みです。
import numpy as np # numpy を np という省略名で使用
for t in np.arange(0.0, 5.0, 0.5):
print(f'{t:.2f}',end=' ')期待する結果
0.00 0.50 1.00 1.50 2.00 2.50 3.00 3.50 4.00 4.50 5.00
(ここからが本題です)
上記のファイル名を numpy.py
(プログラムのなかでインポートしているライブラリと同じ名前)
に変更して、その実行結果を確認してください。
また、ファイル名を np.py
に変更して、その実行結果を確認してください。
必要に応じて「なぜこのようなことが発生するのか」をウェブ検索あるいはChatGPTを使って解決してください。これは、適切な検索キーワードやプロンプトを構築する練習です。
ここから先は、GoogleColab または Jupyter を利用してください。
5 型 (Type)
ここまでは、あえて言及を避けてきましたが、Python においても、C/C++言語 (Arduino言語)、Java と同様に 型 (Type) が存在して機能しています。
ただし、Python
では、C/C++言語のようにプログラマによる明示的な型付けはせずに、Python実行環境が
動的に型付け をします。つまり a=10
という文を書けば a は自動的に 「整数型
(int)」となります。また、一方で
a='ABC' という文を書けば a は 自動的に「文字列型 (str)」
となります。
- 例:
a=10と書くと変数aは、整数 (int) 型として扱われる。 - 例:
a='10'あるいはa="10"と書くと変数aは、文字列 (str) 型として扱われる。 - 例:
a=10.0と書くと変数aは、浮動小数点数 (float) 型として扱われる。 - 例:
a=[10]と書くと変数aは、リスト (list) 型として扱われる。
型付けの種類
プログラミング言語の型システムには「静的型付け」「強い動的型付け」「弱い動的型付け」「型なし」などが存在します。それぞれ一長一短があります。興味のある学生は調べてみてください。なお、Pythonは 強い動的型付け言語 に属します。
5.1 どうやって型を確認するのか?
type()
という組み込み関数を使用してデータの「型」を確認できます。
具体的には、is 演算子と type()
の組み合わせで 変数が特定の型であるかどうか
を判定できます。ここでは print
関数と組み合わせていますが、実務的なプログラムでは、if文の「条件」としてよく使用されます。
例えば「変数 a が str型
であるか?」という判定は次のようにできます。
同様に、isinstance()
という組み込み関数を利用することもできます。
次のプログラムを実行して、その結果を確認してください。また、その結果とプログラムを突き合わせて内容を理解してください。
%reset -f
a = 10
# 型を確認する
print(f'変数aの型は {type(a)} です')
print('---')
# 代表的な型 str int bool float list
print(f'変数aの isinstance(a,str) は {isinstance(a,str)} です')
print(f'変数aの isinstance(a,int) は {isinstance(a,int)} です')
print(f'変数aの isinstance(a,bool) は {isinstance(a,bool)} です')
print(f'変数aの isinstance(a,float) は {isinstance(a,float)} です')
print(f'変数aの isinstance(a,list) は {isinstance(a,list)} です')
print('---')
# if文に組み込み① → isinstance() 関数
if isinstance(a,str) :
print('変数aは、文字列型(str)です')
else:
print('変数aは、文字列型(str)ではないです')
# if文に組み込み② → is 演算子
if type(a) is str :
print('変数aは、文字列型(str)です')
else:
print('変数aは、文字列型(str)ではないです')5.1.1 演習2 ( 目標時間: 8分)
上記プログラムの 第02行目 の a=10
を次のように書き換え、その実行結果を確認してください。
a=10.0a=True※ 実行結果に注意!a='abc'a=[]a=[10,20,30]a=0b1001※0bで開始するのは2進数a=0xFF5※0xで開始するのは16進数a=int(3.14)
中級者向け「isinstance」と「isとtype」による判定の違い
演習2において 第02行目 を a=True
としたときに予想外の結果がでたと思います。そのため、最初のうちは、is
と type の組み合わせを利用することをお勧めしします。
%reset -f
a = True
# bool型であるか?
print( type(a) is bool) # True
print( isinstance(a, bool) ) # True
# int型であるか?
print( type(a) is int ) # False
print( isinstance(a, int) ) # True ?!両者の違いを理解するためには、中級レベルの理解 (「継承」などのオブジェクト指向プログラミングの基礎理解) が必要です。現時点では、皆さんの理解の範疇を超えると思うので、授業では扱いません。詳しく知りたい人は、生成AIを利用してください。プロンプトの例を示します。
Pythonで「a=True」のとき、「type(a) is int」はFalseになるのに、「isinstance(a, int)」はTrueになるのはなぜですか?
5.2 型が違うと何が変わるのか?
型によって、その変数 (オブジェクト) から
呼び出すことができる「メソッド」が違ってきます。例えば、変数
a が 文字列型(str)
であれば、英字の小文字を大文字に変換する a.upper()
のようなメソッドを呼び出せますが、それ以外の
整数型 (int) や 浮動小数点数型
(float) では (自分で確認しましょう🫠)
が発生します。
「メソッド」とは何か
メソッドとは、オブジェクト指向プログラミングの用語になります。現時点では「変数名のあとにドット
. を付けて呼びだす関数」ぐらいに考えてください。
例として、次のコードを実行して結果を確認してください。その後、第02行目を
a=10 に書き換えて (つまり、変数
a を「文字列型」から「整数型」に変えて)
、その実行結果を確認してください。
上記のプログラムは、次のように改良することができます。実行して結果を確認してください。その後、a=10
に書き換えて、その実行結果を確認してください。
%reset -f
a='windows'
if type(a) is str : # 変数aの型が文字列 (str) ならば
print( a.upper() )
else :
print('変数aは文字列型ではないので upper メソッドを持っていません。')5.2.1 演習3 ( 目標時間: 10分)
以下のプログラムに追記して、変数 a が
- 「文字列型」であれば文字列を3回出力する処理 (例えば
Wow!が格納されていればWow!Wow!Wow!を出力)、 - 「整数型」または「浮動小数点数型」であれば5倍した値を出力する処理、
- 「リスト型」であればそのまま出力、
- それ以外の型 (例えば 真偽値型(bool) ) であれば
Error!を出力する処理
にしてください。
ここでは、elif (既に第06回講義で学習済み)
を使用することを期待しています。また、if
の条件文には、AND条件 and (学習済み)、OR条件
or (学習済み)
を使うことができました。例えば if a%3==0 and a%5==0
は a
が「3の倍数」かつ「5の倍数」のとき真になります。
6 関数 (Fuction) 初級
プログラムにおいて ある処理を行なうための一連の命令をまとめたもの を 関数 (Function) と呼びます。関数を利用することで、そのプログラムは読みやすくなり、また、修正や変更も容易になります。
これまでに print() や input()
などを何度も使用してきましたが、これらはPythonが最初から提供している「組み込み関数」というものになります。また、math.sin()
や math.radians()
は、数学ライブラリをインポートすること (つまり import math をすることで)
で使用可能になる関数です。
さらに、Pythonをはじめとして各種プログラムでは、プログラマ自身で関数を定義して、それを呼び出して使用することができます。
例えば「税抜き価格を引数として与えると、税込み価格 (端数切捨て) を計算して返す関数」は、次のように記述できます。実際に実行して、その結果を確認してください。ここでは食料品を対象に「税率8%」を考えています。
%reset -f
# 自作関数 add_tax_to_price を定義
def add_tax_to_price(price):
x = price * 1.08
x = int(x)
return x # x を戻り値として呼び出し側に返す
p1 = 73
p2 = add_tax_to_price(p1)
print(f'ガリガリ君 {p1}円(税込み{p2}円)')
p1 = 12
p2 = add_tax_to_price(p1)
print(f'うまい棒 {p1}円(税込み{p2}円)') ここで def は Define
(日本語で「定義」の意味) の略語になります。
6.1 演習4 ( 目標時間: 15分)
上記のプログラムについて
引数なし で関数を呼びだすと (つまり、第10行目や第14行目で
p2 = add_tax_to_price()とすると) 、どのようになるか。結果について推測したうえで、実際にコードを実行して確認してください。括弧なしで関数を呼びだすと (つまり
p2 = add_tax_to_priceとすると) どのようになるか。結果について推測したうえで、実際にコードを実行して確認してください。第02行目を
def add_tax_to_price(p):に書き換えたとき、プログラムが書き換え前と同じ動作をするように、その他の部分を修正してください。第02行目を
def get_total_price(price):に書き換えたとき、プログラムが書き換え前と同じ動作をするように、その他の部分を修正してください。次のように「関数の呼び出し」を「関数の定義」よりも前に記述するとどうなるか。結果について推測したうえで、実際にコードを実行して確認してください。
%reset -f
# 関数呼び出しを先に記述する
p1 = 73
print(f'ガリガリ君 {p1}円(税込み{add_tax_to_price(p1)}円)')
# 関数定義をあとに記述する
def add_tax_to_price(price):
return int(price * 1.08)6.2 演習5 ( 目標時間: 10分)
引数として、0 から 5 までの 整数値
を与えると、それに対応して「☆☆☆☆☆」「★☆☆☆☆」・・・「★★★★☆」「★★★★★」という文字列を返してくる関数
star
を定義してください。また、その動作確認してください。
なお、引数として0未満の整数値が渡されたときは「☆☆☆☆☆」、6以上の整数値が渡されたときは「★★★★★」を戻り値としてください。また、整数値以外の引数を受け取ったときは「ERROR」という文字列を戻り値としてください。
%reset -f
# 目的の処理をする関数に書き換える
def star(n):
r = '★'*5
return r
#
print(star(4)) # => ★★★★☆
print(star(-4)) # => ☆☆☆☆☆
print(star(10)) # => ★★★★★
print(star('5')) # => ERROR
print(star(['5'])) # => ERROR
print(star('1.5')) # => ERROR- ヒント: 型の判定には
isinstanceやtype、isなどを使用する。
6.3 複数の引数を持つ関数
関数では、複数の引数を受け取ることもできます。例えば、次に示すものは 2点の座標 x1, y1, x2, y2 を与えたとき、その距離を計算する関数の記述例です。実際に実行して、その結果を確認してください。
%reset -f
# 距離を計算する関数
def get_distance(x1,y1,x2,y2):
return ( (x2-x1)**2 + (y2-y1)**2 )**0.5
p1_x, p1_y = 10, 10
p2_x, p2_y = 15, 25
d = get_distance( p1_x, p1_y, p2_x, p2_y )
print(f'距離は {d:.1f}')7 アサート文
アサート (assert)
は主にデバッグやエラーチェックを目的に使用する機能です。例えば、次のように
assert 条件文
という形式で使用します。ちなみに、第03行目の
.pop() は、既に第10回講義で学習済みです。
%reset -f
arr = [0,1,0,1,0,1,0] # 長さ7のリストを初期化
arr.pop() # リスト末尾の要素を取り除く
# arr の長さが 6 であることを「念のために確認したい」
assert len(arr) == 6
# (以降、継続処理)
print('後続処理')assert は、それに続く条件式が 真
(True)
であることを「確認」する目的として使用します。
もし、条件式が 偽(False) となる場合、プログラムはエラーメッセージを生成して強制停止します。一方で、真 (True) となる場合は 何も出力せずに処理を継続 します。
上記プログラムの場合、リスト arr が
pop() メソッドによって「長さ 6
になっていること」を念のために確認するために
第06行目 に assert
文を書いています。
ここで、第02行目 を
arr=[0,1,0,1,0,1,0,1] # 長さ7のリストを初期化
に書き換えて再度実行してみてください。今度は
(自分で確認しましょう🫠) が発生します。
つまり、assertは「ここでは、この変数は、こうなっているはず!」を念のために確認する機能を提供します。
このようなことは、if と
print、さらにプログラムを停止する
sys.exit() を組み合わせても可能ですが、
assert と比較すると手間になります。また、Jupyter環境
(Colab.環境) では sys.exit()
は意図した動作をしません。
assertはデバッグ用途
assert
は、主にデバッグのために使用する機能であることを忘れないでください。製品レベルのエラー処理には、後の講義で学習する
例外処理 と print
による文字列出力を組み合わせて使用します。
例外処理では、予期しないエラーが発生した場合でも、プログラムの処理を継続させることが可能となる仕組みを提供します。
7.1 演習6 ( 目標時間: 3分)
変数 a
がリスト型であることを「確認」するためのアサート文を指定の位置に記述してください。また、その動作確認をしてください
(a=10 や a='10' に書き換えて
assert が機能するか確認してください) 。
8 SQLiteとの連携
水曜日の「情報2」の授業のなかで RDB や SQL について触れたので「Python と SQLite が簡単に連携できること」を紹介しておきます。詳しいことは、今後の授業のなかで触れていきます。
Pythonには、SQLite3データベースに接続するための
sqlite3 という標準ライブラリが備えられています。
例えば、次のようなクエリに相当する処理は、
-- テーブル「社員表」が存在しているなら削除
DROP TABLE IF EXISTS 社員表;
-- ①フィールド「社員番号」「名前」「部署」「住所」を持ったテーブル「社員表」を作成
CREATE TABLE 社員表(社員番号,名前,部署,住所);
-- ②テーブル「社員表」にレコードを挿入
INSERT INTO 社員表 VALUES(2009001,'田中一郎','営業部','神奈川県伊勢原市');
INSERT INTO 社員表 VALUES(2009002,'山本二郎','開発部','神奈川県横浜市');
INSERT INTO 社員表 VALUES(2009003,'佐藤三郎','開発部','神奈川県横浜市');
INSERT INTO 社員表 VALUES(2009004,'ウチのシロ','帰宅部','神奈川県犬山市');
-- ③テーブル「社員表」から全項目(*)を選択して表示
SELECT * FROM 社員表;
以下のPythonプログラムによって記述することができます。実際に実行して確認してみてください。
%reset -f
import sqlite3
# DBとの接続の開始
conn = sqlite3.connect('test.db')
cur = conn.cursor() # DBのカーソル(Cursor)取得
# DBの作成
cur.execute("DROP TABLE IF EXISTS 社員表")
cur.execute("CREATE TABLE 社員表(社員番号,名前,部署,住所)")
cur.execute("INSERT INTO 社員表 VALUES(2009001,'田中一郎','営業部','神奈川県伊勢原市')")
cur.execute("INSERT INTO 社員表 VALUES(2009002,'山本二郎','開発部','神奈川県横浜市')")
cur.execute("INSERT INTO 社員表 VALUES(2009003,'佐藤三郎','開発部','神奈川県横浜市')")
cur.execute("INSERT INTO 社員表 VALUES(2009004,'ウチのシロ','帰宅部','神奈川県犬山市')")
conn.commit() # 処理を実行
# データの更新
# cur.execute("UPDATE 社員表 SET 名前='ウチのミケ', 住所='神奈川県猫山市' WHERE 社員番号=2009004")
# conn.commit()
cur.execute('SELECT * FROM 社員表')
table = list(cur)
for record in table:
print(*record,sep='|') # タプル(=リストのようなもの) のアンパック
# print(table[0][1]) # => 田中一郎
# print(table[3][2]) # => 帰宅部
# DBとの接続を切る
conn.close()このプログラムでは、DBの新規作成を行なっていますが、通常は、データベースの新規作成などは他のソフトウェアでおこないます。プログラムでは、既存のデータベースに接続して必要なデータを読み込んだり、データの更新処理を行ないます。
9 斜方投射のシミュレーションと可視化
ここまで学習してきたことを組み合わせて「斜方投射」の簡易シミュレーションと可視化に挑戦してみましょう。このセクションでは Jupyter環境(Colab.環境)を使用することを想定 します。
9.1 確認
ある時刻において位置 \(x (\mathrm{m})\)、速度 \(v(\mathrm{m/s})\) の物体がある。この物体について、微小時間 \(dt\) 秒後の位置を求めよ。答え:\(x+v\cdot dt\)
ある時刻において速度 \(v(\mathrm{m/s})\)、加速度 \(-g(\mathrm{m/s^2})\) の物体がある。この物体について、微小時間 \(dt\) 秒後の速度を求めよ。答え:\(v-g\cdot dt\)
ある時刻において位置 \(x (\mathrm{m})\)、速度 \(v(\mathrm{m/s})\)、加速度 \(a(\mathrm{m/s^2})\) の物体がある。この物体について、微小時間 \(dt\) 秒後の位置を求めよ。答え:\(x+v\cdot dt+0.5\cdot a \cdot dt^2\)
- ただし、\(dt\) が非常に小さいときは \(x+v\cdot dt\) で近似できる。
9.2 基本プログラム
前回の宿題 として、以下のプログラムについては 既に60分を費やして読み込んでいることを前提 とします。
このプログラムでは「斜方投射」したときの 物体の位置 (X座標とY座標) を
0.1秒間隔 で計算して、それをリスト
arr_x と arr_y
に格納し、最後にそれを可視化 (グラフ化) しています。
シミュレーションの時間範囲は、第11行目と第12行目のコード
iter=80 と dt=0.1
から計算できるように、時刻 \(0(\mathrm{s})\) から時刻 \(8.0(\mathrm{s})\)(厳密に言えば\(7.9(\mathrm{s})\))
となります。
実際にコードを実行して、その結果を確認してください。
%reset -f
import math
import matplotlib.pyplot as plt # 可視化支援ライブラリ
# パラメータ設定
v0 = 20.0 # 初速度(m/s)
theta = 60 # 水平方向から上方にθ(deg)に向けて投射
g = 9.8 # 重力加速度m/s^2
# シミュレーションの準備・設定
dt = 0.1 # 位置を計算する時間間隔
iter = 80 # シミュレーション繰返し回数
theta = math.radians(theta) # deg -> rad 変換
arr_x=[0]*iter # X位置を格納するリストの初期化
arr_y=[0]*iter # Y位置 〃
assert len(arr_x) == len(arr_y)
arr_x[0] = x = 0 # t=0 のX位置
arr_y[0] = y = 0 # 〃 のY位置
vx = v0 * math.cos(theta) # 初速度のX成分
vy = v0 * math.sin(theta) # 〃 のY成分
# シミュレーション
for i in range(1,iter):
vy = vy - g * dt # Y方向の速度更新
x = x + vx * dt # X位置の更新計算
y = y + vy * dt # Y位置 〃
# 地面衝突の反発 (バウンド) の処理
if y < 0:
y = 0
vy = -vy * 0.8 # 反発係数
arr_x[i] = x # 更新されたX位置をリストに格納
arr_y[i] = y # 〃 Y位置を 〃
# 可視化(現状でここから先は深く理解する必要はない)
fig,ax = plt.subplots(dpi=120)
ax.scatter(arr_x,arr_y,marker='o',s=20,alpha=0.5)
ax.axhline(0,c='black',lw=0.5)
ax.set_aspect('equal', adjustable='box')
ax.set_ylim(-1,30) # Y軸の表示範囲
plt.show()- 斜方投射の初期位置を \((0,12)\) に変更してプログラムを実行せよ。また、そのシミュレーションが適切なものであるか検証せよ。検証後はプログラムを元に戻しておくこと。
- 斜方投射の角度を \(45(deg)\) および \(30(deg)\) に変更してプログラムを実行せよ。また、そのシミュレーションが適切なものであるか検証せよ。最もX方向で遠くまで飛ばせる角度について考察せよ。検証後はプログラムを元に戻しておくこと。
- 反発係数を \(0.9\) および \(0.7\) に変更してプログラムを実行せよ。また、そのシミュレーションが適切なものであるか検証せよ。検証後はプログラムを元に戻しておくこと。
- シミュレーションの時間範囲 ( 時刻 \(0.0\) から \(8.0\) まで ) を変えずに、その時間間隔を \(0.2(\mathrm{s})\) に変更してプログラムを実行せよ。また、そのシミュレーションが適切なものであるか検証せよ。同様に、時間間隔を \(0.05(\mathrm{s})\) とした場合についても実行せよ。検証後はプログラムを元に戻しておくこと。
- \(x=50\) の位置に壁が存在するとしてX方向にも衝突 (反発) が生じるようにせよ。
9.3 アニメーション
第43行目 以降がアニメーション対応にするための変更箇所になります。GIFアニメ画像としても出力可能です、興味がある学生は声をかけてください。
%reset -f
import math
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import IPython
# パラメータ設定
v0 = 20.0 # 初速度(m/s)
theta = 60 # 水平方向から上方にθ(deg)に向けて投射
g = 9.8 # 重力加速度m/s^2
# シミュレーションの準備・設定
dt = 0.1 # 位置を計算する時間間隔
iter = 80 # シミュレーション繰返し回数
theta = math.radians(theta) # deg -> rad 変換
arr_x=[0]*iter # X位置を格納するリストの初期化
arr_y=[0]*iter # Y位置 〃
assert len(arr_x) == len(arr_y)
arr_x[0] = x = 0 # t=0 のX位置
arr_y[0] = y = 0 # 〃 のY位置
vx = v0 * math.cos(theta) # 初速度のX成分
vy = v0 * math.sin(theta) # 〃 のY成分
# シミュレーション
for i in range(1,iter):
vy = vy - g * dt # Y方向の速度更新
x = x + vx * dt # X位置の更新計算
y = y + vy * dt # Y位置 〃
# 地面衝突の反発 (バウンド) の処理
if y < 0:
y = 0
vy = -vy * 0.8 # 反発係数
arr_x[i] = x # 更新されたX位置をリストに格納
arr_y[i] = y # 〃 Y位置を 〃
# アニメーション
fig,ax = plt.subplots(dpi=120)
ss = 5
def frame(i):
ax.clear()
ax.set_aspect('equal', adjustable='box')
ax.set_ylim(-1,30)
ax.set_xlim(0, round(max(arr_x),-1)+5)
ax.axhline(0,c='black',lw=0.5)
ax.text(0.01,0.98,f't={i*dt:.2f}',va='top',transform=ax.transAxes)
for t in range(ss):
ax.scatter(arr_x[i+t],arr_y[i+t],
marker='o',s=20,c='tab:blue',alpha=t/(ss+1))
ani = animation.FuncAnimation(fig, frame, interval=100,frames=iter-ss)
plt.close()
IPython.display.HTML(ani.to_jshtml())10 宿題
次回講義に「小テスト」を実施します。今回の授業で扱った「関数」に関する Pythonプログラム を正しく記述できるようになっておいてください。