トップページ
このブログのコンセプト
業務等で活用しやすい『機能単位』でノウハウをまとめる
イラスト1つでやりたいことがわかる構成とする
詳細な機能の記事(各種ライブラリに関する使い方説明など) は他サイトのリンクにとどめる
カテゴリ
pythonによるデータ分析
データ読み込み
題目 | 説明 | リンク |
---|---|---|
数値データの読み込み | 指定したフォルダの各種ファイル(csv/xlsx/json等)から数値データを読み込む | リンク |
画像・動画データの 読み込み |
指定したフォルダの画像・動画ファイル(jpg/png/avi等)から数値データを読み込む | リンク |
Webサイトからの データ取得 |
WEBサイトから情報を取得する | リンク |
命名規則・作成日などの 条件付きファイル探索 |
条件にマッチしたファイルだけを探索して取得する | リンク |
前処理
題目 | 説明 | リンク |
---|---|---|
画像データの前処理 | 画像データを処理しやすいように整える(サイズ・ノイズ除去など) | リンク |
数値データの前処理 | 数値データのノイズ・欠損値を処理する | リンク |
数値データマージ・削減 | データの内容に応じてマージ・削減する処理 | リンク |
特徴抽出/パターン認識
題目 | 説明 | リンク |
---|---|---|
物体検出① | 簡易的な物体検出を行う(テンプレートマッチング/色検出/エッジ検出) | リンク |
物体検出② | YoloV3を用いたWebカメラ画像の物体検出 | リンク |
統計処理 | 入力データの特性を算出して可視化する | TBD |
機械学習 | データの特性を学習し、適切に分類する | TBD |
GUI出力/ユーザー要求処理
題目 | 説明 | リンク |
---|---|---|
GUI | tkinterを用いたGUI実装 | リンク |
グラフ表示 | matplotlibを用いたデータの可視化 | リンク |
グラフ表示(アニメーション) | matplotlibのアニメーション描画 | リンク |
exe化 | pyinstllerを用いたpythonスクリプトの実行ファイル化 | リンク |
ユーザー入力の受理 | pygameを用いたキーボード/ゲームパッド操作取得 | リンク |
電子工作プロトタイピング
前提知識
題目 | 説明 | リンク |
---|---|---|
開発環境 | プロトタイプ用ハード・開発環境に関する考え方 | リンク |
Raspberry Pi開発環境(ハード) | 必要なハードウェアについて | リンク |
Raspberry Pi開発環境(ソフト) | Ubuntu mate/ROSの導入方法について | リンク |
ソフトウェアアーキテクチャ | プロトタイピング時のソフトウェアアーキテクチャについて | リンク |
環境構築
題目 | 説明 | リンク |
---|---|---|
Pythonソフト構造 | 複数機能・ファイルから成り立つプロジェクトの構築 | リンク |
Python処理タイミング | 各機能の動作タイミングの設計方法 | TBD |
Arduinoソフト構造 | 複数機能・ファイルから成り立つプロジェクトの構築 | リンク |
Arduino処理タイミング | 各機能の動作タイミングの設計方法 | リンク |
通信機能
題目 | 説明 | リンク |
---|---|---|
ArduinoとPCの通信 | シリアル通信(USBケーブル) | リンク |
PCとの接続 | リモートデスクトップ/カメラ画像の送信/信号の送信 | TBD |
クラウドサービスとの接続 | IFTTT連携 (Google Home/スマートフォン) | TBD |
ROS開発
題目 | 説明 | リンク |
---|---|---|
ROS基礎 | 概念/用語/コマンドの使い方 | リンク |
ROS基礎2 | プロジェクト構築 | リンク |
PCとの通信 | Ubuntu PCとRaspberry piとの接続/制御信号の通信 | リンク |
ロボットモデルの記述 | URDFファイルにロボットのモデルを記述する | リンク |
移動ロボット基礎 | シミュレーション上でロボットを移動させる | リンク |
移動ロボットの走行経路 | ロボットの走行経路を設定する | リンク |
移動ロボットの経路追従 | 走行経路を追従する車速・角速度の制御 | リンク |
センシング
題目 | 説明 | リンク |
---|---|---|
カメラセンシング | Raspberry pi カメラを使った画像処理 | リンク |
各種センサ実装 | 各種センサの実装 | TBD |
loggingを用いた動作ログ出力
概要
pythonのライブラリloggingを用いた動作ログの出力方法についてまとめる
logger
loggingはpython標準のログ出力用ライブラリであり、ソフトの動作(デバッグ用情報、エラー、例外など)の発生時刻やレベルを管理してログファイルに出力することができる。
loggerモジュールは下記の手順で使用する。
1. loggerの設定
loggerはログの生成・受け渡し等を管理するオブジェクトである。ログを出力ために、ソフトの最初でloggerを生成する。loggerはエラーの種類によって出力する対象を下記の5つのレベルで分類できる。
エラーレベル | 値 | 使用例 |
---|---|---|
DEBUG | 10 | 開発時のみ使用するメッセージ |
INFO | 20 | 想定内の動作の確認用メッセージ(ソフトの起動/終了など) |
WARNING | 30 | 動作に影響のないエラー(正常値範囲外となる信号など) |
ERROR | 40 | 機能に影響のあるエラー(動作条件を満たせない信号異常) |
CRITICAL | 50 | プログラムの動作に影響のある致命的なエラー |
loggerが出力するレベルの閾値をlogger.setLevel関数で制限できる。setLevelで設定した値以下のエラーレベルの警告が無視されるようになる。開発時と正式運用で出力するログのレベルを調整したい場合に活用できる。
filename = "test" logger = logging.getLogger(filename) logger.setLevel(10) #DEBUG情報は表示しない
2. handlerの設定
handlerはloggerから受け取ったエラー情報の出力をするオブジェクトである。handlerに対して、エラー時に出力するメッセージのフォーマット設定をすることができる。
一例として、ログファイルにエラーの発生時刻・エラーレベル・logger呼び出し時に引数にセットした文字列を出力したい場合には次のように設定できる。
#フォーマッタの設定 fmt = logging.Formatter('[%(asctime)s] (%(levelname)s) %(message)s') #ファイルハンドラの作成 fh = logging.FileHandler(filename, encoding='utf-8') #ファイルハンドラにフォーマッタを設定 fh.setFormatter(fmt) #ファイルハンドラをロガーに設定 self.logger.addHandler(fh)
クラスを使った簡易化
上記設定後に各モジュールがloggerを読み込んで出力用の関数(logger.debug("TEST") 等)を呼び出すとログ出力をすることができる。 しかし、実装が煩雑になるため関連処理をクラスにまとめておくと使用しやすくなる。下記ページで公開されているコードが参考になった。
上記ページのLogManクラスをlogMan.pyとして保存しておいたときに、ログ出力を呼び出すときのコードを下記に示す。 注意点として、exceptionを呼び出す際にはエラー内容は自動的に表示されるため文字列には何も設定する必要はない
import os from logMan import LogMan if __name__ == '__main__': lm = LogMan(os.path.abspath('.')+"/log/log.txt",stdout=True) lm.info("Program started!!") #error A lm.error("Error A!!") #warning B lm.error("WARNING B!!") #exception try: x = 1/0 except: lm.exception("EXCEPTION X") lm.info("Program Finished!!")
生成されるログファイル
[2023-02-26 16:44:08,760] logMan.py (INFO) Program started!! [2023-02-26 16:44:08,761] logMan.py (ERROR) Error A!! [2023-02-26 16:44:08,761] logMan.py (ERROR) WARNING B!! [2023-02-26 16:44:08,762] logMan.py (ERROR) EXCEPTION X Traceback (most recent call last): File "d:\WS\VS_project\BlogProject\BlogProject\loggintTest.py", line 18, in <module> x = 1/0 ZeroDivisionError: division by zero [2023-02-26 16:44:08,763] logMan.py (INFO) Program Finished!!
参考記事
plotlyによる3Dグラフ描画
概要
pythonのライブラリ plotlyを用いて3Dグラフおよびアニメーションの表示をする方法について記述する
3Dグラフの表示
plotly で3次元の散布図を描画する例を下記に示す。scatter_3dを呼び出し3dxyzの座標を与えればグラフを描画できる。
import plotly.graph_objects as go import plotly.express as px import numpy as np import pandas as pd x = np.arange(20) y = np.random.rand(20) *20 z = np.random.rand(20) *5 # plotly expresを使う場合 # df = pd.DataFrame({ 'x_data' : x, # 'y_data' : y, # 'z_data' : z}) # # # fig = px.scatter_3d(df, x='x_data', y='y_data', z='z_data') # fig.show() # graph objectを使う場合 fig = go.Figure(data=[go.Scatter3d(x=x,y=y,z=z,mode='markers')]) fig.show()
散布図ではなく平面図として描画したい場合には、Surfaceを用いる。 Surfaceではxyzの各辺の成分を代入して3D平面をプロットすることができる。
# -*- coding: utf-8 -*- import plotly import plotly.graph_objects as go z=[ [0.0,0.0,0.0,0.0,0.0] ,[0.0,1.0,2.0,3.0,0.0] ,[0.0,2.0,10.0,6.0,0.0] ,[0.0,1.0,2.0,3.0,0.0] ,[0.0,0.0,0.0,0.0,0.0] ] fig = go.Figure(data=[go.Surface(z=z,x=[-5.0,-2.5,0.0,2.5,5.0],y=[-20,-10.0,0.0,10.0,20.0])]) fig.update_layout( title='Surface' ,scene=dict( xaxis=dict(title='x') ,yaxis=dict(title='y') ,zaxis=dict(title='z') ) ) fig.show()
複数グラフの描画(画像上に散布図を表示)
上記を組み合わせて複数のグラフを同時に描画することができる。 ここで、3DSurfaceのcolormapとして画像データを出力するようにすると、3D空間に平面として画像を表示しその上にデータをプロットすることができる。
# -*- coding: utf-8 -*- import plotly import plotly.graph_objects as go from PIL import Image import numpy as np from PIL import Image img_as_8bit = lambda x: np.array(Image.fromarray(x).convert('P', palette='WEB', dither=None)) dum_img = Image.fromarray(np.ones((3,3,3), dtype='uint8')).convert('P', palette='WEB') idx_to_color = np.array(dum_img.getpalette()).reshape((-1, 3)) colorscale=[[i/255.0, "rgb({}, {}, {})".format(*rgb)] for i, rgb in enumerate(idx_to_color)] im = np.array(Image.open('D:/VS_WS/pytest/image/Mandrill.bmp')) trace=go.Surface( z=np.zeros([256,256])-50, surfacecolor=img_as_8bit(im), cmin=0, cmax=255, hoverinfo= 'none', #画像の各画素にホバーしたときの説明を非表示にする colorscale=colorscale, showscale=False #右のカラーバーを非表示にする ) trace2=go.Scatter3d(x=[0, 10, 50, 100, 200], y=[0, 30, 70, 150, 200], z=[0,-10, 30, -20, 10], mode='markers', marker_color='rgba(0, 255, 0, .8)', ) fig = go.Figure( data=[trace,trace2], layout_title_text="3D Face Mesh", ) fig.show() fig.write_html("3Dtry.html")
参考記事
Postgres SQLの導入・環境設定・DBの読み込み
概要
PostgreSQLの導入とDBの基本操作についてまとめる
PostgreSQLの導入
Ubuntu 20へのPostgreSQLの導入は下記コマンドを実行する。
sudo apt update sudo apt install postgresql postgresql-contrib
合わせてPostgreSQLのGUI管理ツールである"pgadmin4"をインストールする。
sudo curl https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo apt-key add sudo sh -c 'echo "deb https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list && apt update' sudo apt install pgadmin4
インストール後にメールアドレスとパスワードを設定する。
sudo /usr/pgadmin4/bin/setup-web.sh
pgadmin4でDB情報にアクセスするためには、postgreSQLの管理用ロールである"postgres"のユーザー名を変更する必要がある。 下記コマンドでパスワードを変更する。 (xxxxxxxに設定したいパスワードを入力)
sudo -u postgres psql -c "ALTER ROLE postgres WITH password 'xxxxxxx'"
また、デフォルトではDBのアクセス設定とubuntuのユーザー名が一致していないとエラーとする設定としているため/etc/postgresql/12/main/pg_hba.confの 下記行を変更する。
# "local" is for Unix domain socket connections only local all all md5
上記設定を完了後に下記コマンドでpostgreSQLのサービスを再起動してブラウザでhttp://127.0.0.1/pgadmin4/にアクセスする。
sudo service postgresql restart
pgadminの左の"Servers"を右クリックしてCreate->Serverを選択し、下記設定を入力する。 (HostName以降の設定はConnectionタブに切り替えて入力)
Name: PostgreSQL 12 ServerGroup: Servers HostName/address: localhost Port: 5432 Username: postgres Password: xxxxxxx (↑の手順で入力したもの) Store password: Checked
正しく設定できると下記のようにDB情報が表示される。
roleの作成
最初から登録してあるroleの"postgres"はユーザー登録等に使うスーパーユーザー権限を持つ管理者用のroleである。 データベース操作は他roleで行ったほうが良いためroleを追加する。pgadmin4の”Login/Group Rolesを右クリックして新規roleを追加する。 この際、"Privileges"タブから新規DBを作成する権限を付与する。
DBの読み込み
DBの基本操作の題材として、postgreSQLチュートリアル用に下記サイトでサンプルDBを公開している。
上記サイトからdvdrental.zipをダウンロードする。その後、読み込み用のDBをpgadminから新規作成する。(ownerを↑で作成したroleにしておく) その後下記コマンドを用いてサンプルDBをリストアする。
pg_restore -d newdb --role=user -O -x '/home/path/dvdrental.tar'
正しく読み込めると下記のようにサンプルDBが表示できる。
参考書
参考サイト
plotlyによるグラフ描画
概要
pythonのライブラリ plotlyを用いて数値データをグラフ描画する。
plotly
plotlyはブラウザでインタラクティブに操作可能なグラフを生成することができる。 本記事では基本的な使い方と設定方法についてまとめる。
基本的なグラフの描画
plotlyのインストールは下記pipコマンドで行う。
pip install plotly
基本的なグラフの描画方法は公式チュートリアルの下記ページにまとめてある。
[https://plotly.com/python/line-charts/:embed:cite]
上記にはplotly expressという高レベルapiによる描画方法と従来のplotlyの描画方法(Graph objects)による方法が記述されている。 それぞれの方法でy=x2の線・散布図・棒グラフを下記のように記述することができる。
import plotly.graph_objects as go import plotly.express as px import pandas as pd import numpy as np x = np.arange(10) #plotly expressによる描画 df = pd.DataFrame({ 'x_axis_label' : x, 'y_axis_label' : x**2}) fig = px.line(df, x="x_axis_label", y="y_axis_label", title='plot test') #散布図 #fig = px.scatter(df, x="x_axis_label", y="y_axis_label", title='plot test') #散布図 #fig = px.bar(df, x="x_axis_label", y="y_axis_label", title='plot test') #棒グラフ #graph objectによる描画 #fig = go.Figure(data=go.Scatter(x=x, y=x**2, mode="lines")) #線グラフ #fig = go.Figure(data=go.Scatter(x=x, y=x**2, mode="markers")) #散布図 #fig = go.Figure(data=go.Bar(x=x, y=x**2)) #棒グラフ #描画設定 fig.update_layout( title_text='plot test', title_x=0.5, #グラフタイトルを中央に寄せる xaxis_title_text='x axis label', #x軸ラベル yaxis_title_text='y axis label', #y軸ラベル title_font_size=30, #タイトルフォントサイズ title_font_family='Times New Roman', #タイトルフォント title_font_color='red' #タイトル色 ) fig.show()
plotly expressで描画する場合はpandas data frameを引数として指定する必要があるため、numpyのデータをpandasに変換する処理が必要となる。 また、タイトル名・軸名等は引数として設定することができる。graph objectの描画ではnumpyのデータを引数として指定する。グラフタイトルなどの設定はupdate_layoutによって設定する。
複数のグラフの描画
同じ軸設定で複数のグラフを表示する場合は下記のように実装できる。
import plotly.graph_objects as go import plotly.express as px import pandas as pd import numpy as np x = np.arange(10) #plotly expressによる描画 # df = pd.DataFrame({ 'x_axis_label' : x, # 'y_data' : x**2, # 'y_data2' : x**2 -2.0, # 'y_data3' : x**2 * 0.5,}) #fig = px.line(df, x="x_axis_label", y=["y_data","y_data2","y_data3"], title='plot test') #線グラフ #graph objectによる描画 fig = go.Figure() fig.add_trace(go.Scatter(x=x, y=x**2, mode="lines")) fig.add_trace(go.Scatter(x=x, y=x**2-2.0, mode="lines")) fig.add_trace(go.Scatter(x=x, y=x**2 * 0.5, mode="lines")) #描画設定 fig.update_layout( title_text='plot test', title_x=0.5, #グラフタイトルを中央に寄せる xaxis_title_text='x axis label', #x軸ラベル yaxis_title_text='y axis label', #y軸ラベル title_font_size=30, #タイトルフォントサイズ title_font_family='Times New Roman', #タイトルフォント title_font_color='red' #タイトル色 ) fig.show()
plotly expressでは描画したいデータのy軸を含むcolumn名を指定すれば良い。 graph objectでは描画したいデータをfig.add_traceで追加する。
異なる種類のグラフを同じ画面で描画することもできる。
import plotly.graph_objects as go import plotly.express as px import pandas as pd import numpy as np x = np.arange(10) #plotly expressによる描画 df = pd.DataFrame({ 'x_axis_label' : x, 'y_data' : x**2, 'y_data2' : x**2 -2.0, 'y_data3' : x**2 * 0.5,}) fig = px.line(df, x="x_axis_label", y=["y_data"], title='plot test') #線グラフ fig2 = px.scatter(df, x="x_axis_label", y=["y_data2"],color_discrete_sequence=["red"]) #線グラフ fig3 = px.bar(df, x="x_axis_label", y=["y_data3"],color_discrete_sequence=["green"]) #線グラフ fig.add_trace(fig2.data[0]) fig.add_trace(fig3.data[0]) #graph objectによる描画 #fig = go.Figure() #fig.add_trace(go.Scatter(x=x, y=x**2, mode="lines")) #fig.add_trace(go.Scatter(x=x, y=x**2-2.0, mode="lines")) #fig.add_trace(go.Scatter(x=x, y=x**2 * 0.5, mode="lines")) #描画設定 fig.update_layout( title_text='plot test', title_x=0.5, #グラフタイトルを中央に寄せる xaxis_title_text='x axis label', #x軸ラベル yaxis_title_text='y axis label', #y軸ラベル title_font_size=30, #タイトルフォントサイズ title_font_family='Times New Roman', #タイトルフォント title_font_color='red' #タイトル色 ) fig.show()
plotly express で各グラフの色を変えるためにはcolor_discrete_sequenceオプションを使うことに注意する。
グラフの保存
描画したグラフはhtmlや画像(png/jpeg等)で保存することができる。 保存する場合は下記関数を呼び出す。
fig.write_html("path/to/file.html") fig.write_image("ファイル名(パス含む).拡張子")
htmlの保存時に必要なライブラリがエラーが発生する場合がある。警告に従って下記コマンドで必要なライブラリをインストールして解消できる。
pip3 install kaleido
参考記事
matplotlibによる3Dグラフ描画
この記事の目的
matplotlibを用いて3Dグラフを描画する方法についてまとめる
matplotlibを用いた3D線グラフ・散布図の描画
matplotlibで3Dグラフを描画する場合は下記のように実装する。
- (1) 3D描画用モジュールのインポート
matplotlibのインポート時に3次元描画に関するライブラリ(mpl_toolkitsのAxes3D)をインポートする。
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D
- (2) 3D軸設定
描画する軸の設定時引数projection='3d'を付与することで3次元軸を追加する。
ax = fig.add_subplot(1,1,1,projection='3d') #subplotの追加 (行/列/描画対象インデックス,3次元軸の追加)
- (3) plot,scatter関数を3次元データを引数として呼び出す・
描画用関数(線グラフであればplot、散布図であればscatter)を呼び出す時にxyzの各座標を引数として呼び出す。 その際、xyzのデータ数は一致させる必要がある。
# xy平面にsin関数を描画する xs = np.linspace(-np.pi, np.pi, 100) ys = np.sin(xs) ax.plot(xs, ys, zs=0, zdir='z', label='sin (x, y)')
上記を組み合わせて3次元軸にsin・cosを描画するサンプルコードを下記に示す。
import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D fig = plt.figure() ax = fig.add_subplot(1,1,1,projection='3d') #subplotの追加 (行/列/描画対象インデックス,3次元軸の追加) # xy平面にsin関数を描画する xs = np.linspace(-np.pi, np.pi, 100) ys = np.sin(xs) ax.plot(xs, ys, zs=0, zdir='z', label='sin (x, y)') # xz平面にcos関数を描画する xs = np.linspace(-np.pi, np.pi, 100) ys= np.zeros([100]) zs = np.cos(xs) ax.scatter(xs, ys, zs, zdir='z', label='cos (x, y)',color="red") ax.legend() ax.set_xlim(-np.pi, np.pi) ax.set_ylim(-np.pi, np.pi) ax.set_zlim(-np.pi, np.pi) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show()
3次元グラフの底面に画像を描画する
3次元でxyzを描画する際、グラフの底面に地図などの平面画像を描画したい場合がある。 その場合、画像をsurfaceとして読み込んで描画することで平面画像とグラフを同時に描画することが可能になる。
画像の読み込みは下記のように行う。
from PIL import Image from pylab import ogrid img = Image.open('mapImage.png') testImg = np.zeros([256,256,4]) testImg[:,:,0:3]= np.array(img.resize((256, 256)))/255 testImg[:,:,3]= 0.5 X1, Y1 = ogrid[0:testImg.shape[0], 0:testImg.shape[1]] X1 = X1 - 128 Y1 = Y1 - 128 ax.plot_surface(X1, Y1, np.atleast_2d(-50.0), rstride=5, cstride=5, facecolors=testImg)
上記例ではPILライブラリで画像を読み込んでから256×256に初期化する。 ここで、画像を0-1のfloatにするため全体を255で除算している。 また、画像の4次元目は透明度なので、0-1で任意の値に指定する。(0が透明、1が不透明) その後、pylabのogrid関数でsurface用のXY座標を取得する。ここで画像の中心を0にするために-128を引いて調整している。 最後にplot_surface関数で画像を描画している。np.atleast_2dの引数はz軸の値として任意に指定する。
サンプルコードと結果を下記に示す。
import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D from PIL import Image from pylab import ogrid fig = plt.figure() ax = fig.add_subplot(1,1,1,projection='3d') #subplotの追加 (行/列/描画対象インデックス,3次元軸の追加) #画像の読み込み img = Image.open('mapImage.png') testImg = np.zeros([256,256,4]) testImg[:,:,0:3]= np.array(img.resize((256, 256)))/255 testImg[:,:,3]= 0.5 # 画像を挿入(0など任意の値にどうぞ) X1, Y1 = ogrid[0:testImg.shape[0], 0:testImg.shape[1]] X1 = X1 - 128 Y1 = Y1 - 128 ax.plot_surface(X1, Y1, np.atleast_2d(-50.0), rstride=5, cstride=5, facecolors=testImg) # xy平面にsin関数を描画する xs = np.linspace(-np.pi, np.pi, 100) ys = np.sin(xs) ax.plot(xs*50, ys*50, zs=0, zdir='z', label='sin (x, y)') # xz平面にcos関数を描画する xs = np.linspace(-np.pi, np.pi, 100) ys= np.zeros([100]) zs = np.cos(xs) ax.scatter(xs*50, ys, zs*50, zdir='z', label='cos (x, y)',color="red") ax.legend() ax.set_xlim(-150, 150) ax.set_ylim(-150, 150) ax.set_zlim(-150, 150) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show()
参考サイト
C言語用コーディングスタイルの設定(VS Code)
この記事の目的
C言語用のコーディングスタイルの設定方法について記述する。
clang_format によるコーディングフォーマット設定
clang_formatはC言語用のフォーマットツールであり、本ツールを用いることでコードを設定値に応じた書式に自動で変換することができる。 VS codeを用いた使用方法を下記に示す。
- 1 Clang-formatの導入
Ubuntuの場合下記コマンドを用いてaptからclang-formatをインストールする。
sudo apt install clang-format
Windowsの場合下記サイトから最新のLLVMをダウンロードし、インストールする。 LLVMをパスに通す設定があるので、"Add LLVM to the system Path for all user" を選択してパスを通す。
次にVS codeを起動し、拡張機能 clang-formatをインストールする。
上記完了後、VS codeでフォルダを開く際のルートディレクトリに".clang-format"を作成して設定を記述する。
例として下記ファイルを保存する。
# ベースとするコーディングスタイル BasedOnStyle: Google # インデント幅4つ IndentWidth: 4 # タブは使わない UseTab: Never # インクルードはソートしない SortIncludes: false # 関数の戻り値の型の後に改行を入れる(ただし宣言ではでは入れない) AlwaysBreakAfterReturnType: AllDefinitions # 関数定義のカッコだけ改行、ifとかwhileとかは改行しない。elseの前は改行する BreakBeforeBraces: Stroustrup # "case"の行でインデントを入れない IndentCaseLabels: false
ファイルを保存する際にフォーマッタを実行したい場合は下記設定を有効にする。 editor.formatOnSave
また、フォーマッタのみを実行したい場合は"shift+ alt + f"でフォーマッタによる変換を実行することができる。
フォーマッタのルールについては下記サイトを参考として設定する。
エディタ設定(改行・スペース等)
上記に加えて、VS Codeの改行・スペース等の設定も統一しておくとコード修正時のトラブルが少なくなる。
VS Codeの改行コード設定はsetting.jsonに下記記述を追加することで設定できる。
# 改行コードを\nに統一(Linux用設定) "files.eol": "\n"
また、tabキーについてはvs codeでtabをスペース4つに置き換える設定をすることができる。 ただし、C言語での開発の場合makefileはtabで入力しないと実行エラーになる箇所があるので下記の様に設定すると良い。
"editor.insertSpaces": true, "editor.tabSize": 4, "[makefile]": { "editor.insertSpaces": false, "editor.detectIndentation": false }
git設定
上記によりvs code でコードが修正された場合の書式は統一されるが、他エディタでの修正が行われた場合にWindows用の改行コードが混在してそのまま gitにpushされる可能性がある。これを防ぐためには、gitに..gitattributesファイルを用意し改行コードを強制的に変換する設定をしておくとより安全である。
*.sh text eol=lf makefile text eol=lf *.c text eol=lf *.cpp text eol=lf *.h text eol=lf
Visual Studio Code C言語開発環境の設定 (Linux/gcc)
この記事の目的
Visual studio codeを用いてLinux上でgccを用いたC言語開発をする時の設定方法について記述する。
1. 必要なツールのインストール
下記コマンドでgcc(build-essentialはコンパイラ・ライブラリ・makeツール)、gdb(デバッグ用ツール)をインストールする
sudo apt install build-essential sudo apt install gdb
Visual studio codeには下記拡張機能をインストールする。
- c/c++ extention pack (C開発環境、関連ツール一式) marketplace.visualstudio.com
2. make環境の構築(makffile)
VS codeにはC言語プロジェクト用にビルド設定する機能があるが、本機能で環境構築するとプロジェクトのビルドがターミナルから実行できない。 よって、GNU makefileでビルド環境を構築し、VS codeでは拡張機能makefiletoolでそれを読み込んで実行できるようにする。
makefileの設定は下記サイト等を参考に行う。
本記事では例として、下記の2つのcファイルと1つのヘッダファイルについてmakefileの設定を記述する。
main.c
#include <stdlib.h> #include <stdio.h> #include "func.h" int main(void) { int indx =0; for (indx=0; indx<5000; indx++) { fprintf(stderr,"count: %d\n",func(indx)); } return 0; }
func.c
#include <stdlib.h> #include <stdio.h> int func(int cnt) { return cnt*2; }
include/func.h
#ifndef FUNC_H #define FUNC_H int func(int cnt); #endif //FUNC_H
#生成する実行ファイル名 TARGET = testPrj #.oファイル生成用の中間フォルダ OBJSDIR = ./Objs #ヘッダインクルードフォルダ MYINCDIR = ./include #コンパイル対象とするCファイル OBJS = main.o \ func.o\ #コンパイル用コマンド (c++ならばg++に変更) CC = gcc #Wall:警告をすべて出力、-g:デバッグ情報出力、GNU_SOURCE:非標準拡張機能の有効化 CFLAGS = -Wall -g -std=c99 -D_GNU_SOURCE #lm:算術計算ライブラリ有効化 LDFLAGS = -lm INCDIR = -I$(MYINCDIR) OBJS_ALL = $(addprefix $(OBJSDIR)/, $(OBJS)) all: mkdir -p $(OBJSDIR) make $(TARGET) $(OBJS): %.o: %.c $(CC) $(CFLAGS) -c $< $(INCDIR) -o $@ mv $@ $(OBJSDIR)/$@ $(TARGET): $(OBJS) $(CC) -o $@ $(OBJS_ALL) $(LDFLAGS) clean: rm -f *.o rm -f $(OBJSDIR)/*.o rm $(TARGET)
ターミナルで下記コマンドを実行すると、正しくビルド・実行できるかを確認できる。
make sudo ./testPrj
3. VS codeの makefiletools設定
上記を設定後、Visual studio codeからbuildができるようにmakefileとリンク設定する。 makefileの設定はVS codeの『ファイル』⇛『ユーザー設定』⇛『設定』で検索バーに"makefile"と入力すると出てくる画面で"makefile:Configurations"を選択する。ここで、設定に保存先として"ユーザー"ではなく"ワークスペース"に切り替えておいたほうが良い。 上記手順後に表示されるsettings.jsonのmakefile.configurationsで下記のように記述する。
"makefile.configurations": [ { "name": "testprj", "makeDirectory": "./prj" } ]
上記でnameはmake設定の識別名、makeDirecgtoryはmakefileの相対パス(VS codeのルート設定フォルダから)を記入する。 上記設定後、拡張機能mekefile toolsのbuilt対象をtesprjに変更して実行ボタンを押すとVS codeからプロジェクトのビルドが可能になる。
4. インクルードパスの設定
VS codeではソースコードを分析してエラー・警告を表示する機能があるがインクルードパスが適切に設定されていないと正しい探索が行われない。 インクルードパスの設定をするためにコマンドパレットから『C/C++構成の編集(JSON)』を選択し、"includePath"にヘッダファイルがあるフォルダを追加する。
"includePath": [ "${workspaceFolder}/**", "${workspaceFolder}/prj/include" ],
4. デバッグ環境設定
コードの実行中の変数値の確認、ブレークポイントを用いたデバッグを実行するため、GDBの設定を行う。 VS code左側の拡張機能から『実行とデバッグ』を選択し、『launch.json』ファイルを作成しますボタンを押し、C++/GDB用のjsonを作成する。
作成された設定のプログラムのパスを変更する。
"configurations": [ { "name": "(gdb) 起動", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/prj/testPrj", 以下略 } ]
上記を設定後にgdbの起動メニューを実行すると、break pointを使ったデバッグ、変数値の確認がVS Code上からできるようになる。