オフラインでLLM環境の構築:Docker + Ollama + DeepSeekをRTX 4090で動かす
はじめに
自作PCを組み、RTX 4090が手元にあるので、GPUを活用したなにかをしたいなあと企んでいます。
近年、ChatGPTなどのLLM(大規模言語モデル)の進化が著しいですが、患者情報などの機密データを外部サーバーに送信するのは現実的ではありません。
そこで、ローカル環境(オフライン環境)でLLMを実行する方法を検討しました。今後アプリケーション開発や検証を行う場合、GUIよりもPython経由でアクセスできるほうが利便性が高いため、ollama-python も使用できるように環境を構築します。

概要
通常、ChatGPTなどのクラウド型LLMは、ユーザーの入力データをサーバーに送信し、処理を行います。しかし、機密情報や個人情報を扱う場合、外部送信のリスクが懸念されます。
そこで、公開されているLLMモデルを自分のPCにダウンロードすることで、外部通信を行わずにLLMを実行できます。これがローカルLLM です。
Ollamaは、ローカルLLMの管理・実行を簡単に行えるツールです。利用可能なモデルには、Metaの Llama、Googleの Gemma、DeepSeekの DeepSeek LLM などがあります。
今回は、Windows(WSL)上のDocker環境に Ollama をインストールし、DeepSeek-R1 を動作させます。
参考
環境
Docker環境
以下の要領でDocker環境を作ります。 DockerFile
FROM ubuntu:20.04 # 必要なパッケージをインストール RUN apt-get update && apt-get install -y \ curl \ python3 \ python3-pip \ && rm -rf /var/lib/apt/lists/* # Ollamaのインストール RUN curl -fsSL https://ollama.com/install.sh | sh RUN pip install ollama requests ENV PATH="/root/.ollama/bin:$PATH" CMD ["bash"]
devcontainer.json
{ "name": "Existing Dockerfile", "build": { // Sets the run context to one level up instead of the .devcontainer folder. "context": "..", // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename. "dockerfile": "../DockerFile" }, "runArgs": [ "--gpus", "all" ], "mounts": [ "source=${localWorkspaceFolder}/ollama_models,target=/root/.ollama,type=bind" ], "customizations": { "vscode": { "extensions": [ "ms-python.python" ] } } }
自分はVSCodeのdev container+Docker desktopで環境を管理しています。 マウント先を指定しないと、後でモデルをダウンロードした際に、コンテナに入るたびにダウンロードをやり直すことになってしまいます。 このへんの使い方は以下のブログで参照できます。
実行してみる
コンテナ内で、
ollama serve &
を実行すると、ollamaが起動状態になります。
root@56eb47cbcdf5:/workspaces/test_ollama# ollama serve & [1] 40933 root@56eb47cbcdf5:/workspaces/test_ollama# 2025/03/27 07:52:10 routes.go:1230: INFO server config env="map[CUDA_VISIBLE_DEVICES: GPU_DEVICE_ORDINAL: HIP_VISIBLE_DEVICES: HSA_OVERRIDE_GFX_VERSION: HTTPS_PROXY: HTTP_PROXY: NO_PROXY: OLLAMA_CONTEXT_LENGTH:2048 OLLAMA_DEBUG:false OLLAMA_FLASH_ATTENTION:false OLLAMA_GPU_OVERHEAD:0 OLLAMA_HOST:http://127.0.0.1:11434 OLLAMA_INTEL_GPU:false OLLAMA_KEEP_ALIVE:5m0s OLLAMA_KV_CACHE_TYPE: OLLAMA_LLM_LIBRARY: OLLAMA_LOAD_TIMEOUT:5m0s OLLAMA_MAX_LOADED_MODELS:0 OLLAMA_MAX_QUEUE:512 OLLAMA_MODELS:/root/.ollama/models OLLAMA_MULTIUSER_CACHE:false OLLAMA_NEW_ENGINE:false OLLAMA_NOHISTORY:false OLLAMA_NOPRUNE:false OLLAMA_NUM_PARALLEL:0 OLLAMA_ORIGINS:[http://localhost https://localhost http://localhost:* https://localhost:* http://127.0.0.1 https://127.0.0.1 http://127.0.0.1:* https://127.0.0.1:* http://0.0.0.0 https://0.0.0.0 http://0.0.0.0:* https://0.0.0.0:* app://* file://* tauri://* vscode-webview://* vscode-file://*] OLLAMA_SCHED_SPREAD:false ROCR_VISIBLE_DEVICES: http_proxy: https_proxy: no_proxy:]" time=2025-03-27T07:52:10.197Z level=INFO source=images.go:432 msg="total blobs: 7" time=2025-03-27T07:52:10.215Z level=INFO source=images.go:439 msg="total unused blobs removed: 0" time=2025-03-27T07:52:10.237Z level=INFO source=routes.go:1297 msg="Listening on 127.0.0.1:11434 (version 0.6.2)" time=2025-03-27T07:52:10.237Z level=INFO source=gpu.go:217 msg="looking for compatible GPUs" time=2025-03-27T07:52:10.396Z level=INFO source=types.go:130 msg="inference compute" id=GPU-57aceec9-3dd3-35af-fb2c-50ecd3a25ea3 library=cuda variant=v12 compute=8.9 driver=12.7 name="NVIDIA GeForce RTX 4090" total="24.0 GiB" available="22.5 GiB"
別のターミナルで
ollama run deepseek-r1:32b
のようにモデルを指定して実行すると、対話モードに入れます。

初回はモデルのダウンロードが始まるので1時間以上時間がかかります。 (初回のダウンロード以降、インターネット接続が不要になります)
使用できるモデルは以下から確認、検索できます。
Pythonから実行する
ollama serve &
でollamaを起動状態にしておきます。 以下のテストコードを実行すれば、APIにアクセスして出力を得ることができます。
from ollama import chat from ollama import ChatResponse response: ChatResponse = chat(model='llama3.2', messages=[ { 'role': 'user', 'content': 'Why is the sky blue?', }, ]) print(response['message']['content']) # or access fields directly from the response object print(response.message.content)
そのほか
このへんはちゃんと理解していないですが、ollamaはGPUを認識すると、それを占有してから不足分をCPUに割り当てるようです。たぶん。
deepseek-r1:32bを動かすときにタスクマネージャーを確認すると以下のようになっています。

また、初回ダウンロード後でも、ollama runするのにかなり時間がかかります。 起動を待つのがデフォルトで5分で、しばしばタイムアウトになります。 export OLLAMA_LOAD_TIMEOUT=15m0s のように設定するとタイムアウトすることはなくなります。 起動が遅い問題はDocker環境内特有の問題(?)らしいです。未検証です。
以上です。 こんなどうこうよりもまず臨床であるなあ。
RTX4090 windows WSL2 dockerでtensorflow環境を作る
ChatGPTに聞けば大体のエラーが解決する状況で、技術ブログを書く意味などあるのでしょうか。
今回、タイトルの通りに環境構築を頑張っていましたが、すこーしだけ詰まり、chatGPTに聞いても解決しなかったので一応記事として残しておきます。詰まったところ以外は、ChatGPTに聞けば教えてくれるので適当に書きます。
私が書いた記事は読む人もなく、静かに埋もれ消えゆくが、それでも、広大なる言語モデルの学びの一滴となり、そのパラメーターをわずかに書き換え、環境構築に悩むひとびとの背中を押すのです。
結論
latestのtensorflow docker imageを脳死でpullするだけではdocker環境からGPUを認識できません。
NvidiaDriver, Cuda、対応するtensorflowのバージョンを確認して、適切なdocker imageを探す必要があります。
docker pull tensorflow/tensorflow:2.13.0rc2-gpu
を使いましょう。それだけ。
概要
WSL2~Docker Desktopの導入まで
WSL2
WSLというのは、windowsパソコンで、Linux環境をとても簡単に使えますよ。というやつです。 Windows PowerShellを開き、以下を実行します。usernameとpasswordを設定してください。
wsl --install
Windows PowerShellを開いて、以下を実行するとwsl環境に入れます。
wsl
Docker Desktopのインストール
普通のソフトウェアと同様にインストール
Docker Desktop→設定→Resources→WSL integration → Enable integration with my default WSL distroにチェックを入れて、UUbuntuを選択します。

確認。 wslに入って、dockerコマンドを実行してみる。
wsl docker run hello-world
こんな感じになればOK
PS C:\Users\AAA> wsl
AAA@AAA-home:/mnt/c/Users/AAA$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Download complete
Digest: sha256:305243c734571da2d100c8c8b3c3167a098cab6049c9a5b066b6021a60fcb966
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Nvidia Driverのインストール
普通のソフトウェアのインストールと同様。 場合によってはいつの間にか入っていたりする。
NVIDIA Container Toolkitのインストール
cudaのバージョン合わせのごちゃごちゃをしなくてよいのがdockerのうれしさなのですが、その代わりにNVIDIA Container Toolkitを使用する必要があります。
公式のインストールガイドがわかりよいです。

wslに入って、以下を実行すればよろしい。
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
tensorflowのDocker image
デフォルトで、最新のimageを持ってくると、GPUを認識できません。 GPUをcudaのバージョン依存のもろもろは、ここで調整する必要があります。 dockerを使用はしていないが↓がとても丁寧。
要するに、tensorflowが最新のcudaにまだ対応しておらんようです。 なので、latest imageを使用すると、nvidia-smiは機能しますが、tensorflowがGPUを認識しません。 自分のGPU→cuda, Nvidiaドライバの対応→tensorflowのバージョン の順番に決めていけばいいです。 決まったら、hubのリストから適切なimageを探します。
頑張って探す↓
https://hub.docker.com/r/tensorflow/tensorflow/tags
自分は、
docker pull tensorflow/tensorflow:2.13.0rc2-gpu
でうまくいきました。
確認。
wsl nvidia-smi docker pull tensorflow/tensorflow:2.13.0rc2-gpu docker run -it --gpus all 9e81a648bca3
AAA@AAA-home:/mnt/c/Users/AAA$ docker pull tensorflow/tensorflow:2.13.0rc2-gpu 2.13.0rc2-gpu: Pulling from tensorflow/tensorflow 20d547ab5eb5: Download complete 98936854e6e0: Download complete f4df3073462b: Download complete 56e0351b9876: Download complete ad96c12fed87: Download complete 45d1be9ec31b: Download complete 9bbe44e6478e: Download complete b08eef4b90c8: Download complete 36cf074838a5: Download complete aa315b7808f0: Download complete ed0785269bb8: Download complete 6580bd400b80: Download complete 7882189dc767: Download complete d9fc3f86fea2: Download complete c3bec927edaa: Download complete ee594d3d1ae9: Download complete ece84004a3cd: Download complete f6694f81f1cc: Download complete Digest: sha256:9e81a648bca3501a73a4101c4a850209e4292088d2f389512e58e7ee12be0825 Status: Downloaded newer image for tensorflow/tensorflow:2.13.0rc2-gpu docker.io/tensorflow/tensorflow:2.13.0rc2-gpu AAA@AAA-home:/mnt/c/Users/kazuharu$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE tensorflow/tensorflow latest-gpu-jupyter a671d13af415 3 weeks ago 11.8GB tensorflow/tensorflow latest-gpu 1f16fbd9be8b 3 weeks ago 11.3GB nvidia/cuda 12.2.0-base-ubuntu22.04 ecdf8549dd5f 12 months ago 341MB tensorflow/tensorflow 2.15.0rc0-gpu 4a0ac12d0ffd 12 months ago 11.2GB tensorflow/tensorflow 2.13.0rc2-gpu 9e81a648bca3 17 months ago 9.97GB nvcr.io/nvidia/k8s/cuda-sample nbody 59261e419d6d 2 years ago 456MB AAA@AAA-home:/mnt/c/Users/AAA$ docker run -it --gpus all 9e81a648bca3 ________ _______________ ___ __/__________________________________ ____/__ /________ __ __ / _ _ \_ __ \_ ___/ __ \_ ___/_ /_ __ /_ __ \_ | /| / / _ / / __/ / / /(__ )/ /_/ / / _ __/ _ / / /_/ /_ |/ |/ / /_/ \___//_/ /_//____/ \____//_/ /_/ /_/ \____/____/|__/ WARNING: You are running this container as root, which can cause new files in mounted volumes to be created as the root user on your host machine. To avoid this, run the container by specifying your user's userid: $ docker run -u $(id -u):$(id -g) args... /sbin/ldconfig.real: /lib/x86_64-linux-gnu/libcudadebugger.so.1 is not a symbolic link /sbin/ldconfig.real: /lib/x86_64-linux-gnu/libcuda.so.1 is not a symbolic link
よい感じ。 最後に、tensorflowからGPUを認識できるかチェック。
python3 -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
以下の通り
root@a7221f2c9a83:/# python3 -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
2024-11-19 08:07:25.094835: I tensorflow/core/util/port.cc:110] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2024-11-19 08:07:25.114735: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
2024-11-19 08:07:25.821671: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:07:25.824830: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:07:25.825000: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
まあとりあえずOK
root@a7221f2c9a83:/# python3 -c "
import tensorflow as tf
from tensorflow.keras import layers, models;
model = models.Sequential([
layers.Dense(128, activation='relu', input_shape=(100,)),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
]);
model.compile(optimizer='adam', loss='categorical_crossentropy');
x = tf.random.normal((1000, 100));
y = tf.keras.utils.to_categorical(tf.random.uniform((1000,), maxval=10, dtype=tf.int32), num_classes=10);
model.fit(x, y, epochs=5, batch_size=32)
"
2024-11-19 08:10:54.763876: I tensorflow/core/util/port.cc:110] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2024-11-19 08:10:54.783711: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
2024-11-19 08:10:55.494032: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.497499: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.497752: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.499740: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.500037: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.500308: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.595095: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.595572: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.595611: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1726] Could not identify NUMA node of platform GPU id 0, defaulting to 0. Your kernel may not have been built with NUMA support.
2024-11-19 08:10:55.596648: I tensorflow/compiler/xla/stream_executor/cuda/cuda_gpu_executor.cc:981] could not open file to read NUMA node: /sys/bus/pci/devices/0000:01:00.0/numa_node
Your kernel may have been built without NUMA support.
2024-11-19 08:10:55.596686: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1639] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 21458 MB memory: -> device: 0, name: NVIDIA GeForce RTX 4090, pci bus id: 0000:01:00.0, compute capability: 8.9
Epoch 1/5
2024-11-19 08:10:56.331115: I tensorflow/compiler/xla/stream_executor/cuda/cuda_blas.cc:606] TensorFloat-32 will be used for the matrix multiplication. This will only be logged once.
2024-11-19 08:10:56.343800: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7fe6c15e07e0 initialized for platform CUDA (this does not guarantee that XLA will be used). Devices:
2024-11-19 08:10:56.343827: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): NVIDIA GeForce RTX 4090, Compute Capability 8.9
2024-11-19 08:10:56.346762: I tensorflow/compiler/mlir/tensorflow/utils/dump_mlir_util.cc:255] disabling MLIR crash reproducer, set env var `MLIR_CRASH_REPRODUCER_DIRECTORY` to enable.
2024-11-19 08:10:56.353786: I tensorflow/compiler/xla/stream_executor/cuda/cuda_dnn.cc:432] Loaded cuDNN version 8600
2024-11-19 08:10:56.412279: I ./tensorflow/compiler/jit/device_compiler.h:186] Compiled cluster using XLA! This line is logged at most once for the lifetime of the process.
32/32 [==============================] - 1s 3ms/step - loss: 2.4236
Epoch 2/5
32/32 [==============================] - 0s 3ms/step - loss: 2.1865
Epoch 3/5
32/32 [==============================] - 0s 3ms/step - loss: 2.0418
Epoch 4/5
32/32 [==============================] - 0s 2ms/step - loss: 1.9089
Epoch 5/5
32/32 [==============================] - 0s 2ms/step - loss: 1.7685
mycobot320(pro) (37万円)を購入しました。開封とレビュー。
こんにちは!はるなしです。
えーあいやらロボットやらを作るのが好きな医学生です。
このたび、mycobot320(pro)を購入したのでそのレビュー記事です。
mycobot280の記事はいろいろありますが、320は情報少なく、購入に際してかなり悩みました。280を所有している人が、320を検討する際の参考になればと思って書いています。
専門の人ではないので書き方等もやもやするとこあるかもしれませんが、お許しください。検証の仕方で間違いがあれば指摘してください。
開示すべき利益相反はありません。
mycobot 320(pro)を購入しました。 pic.twitter.com/qKg78IuPte
— はるなし (@kk_mdimm) 2022年8月2日
誰向けの記事なのか
mycobot280を所有している人で、320の購入を検討している方を想定しています。どんな感じで届くのか、性能は実際どんなもんなのか、また、私の印象(感想)を書きます。
ダイレクトティーチングやROSでの制御もやりますが、詳しい方法は書きません。レビューが目的で、実装のための記事ではありません。
もくじ
- 概要
- 前情報
- 開封
- 動かしてみる
- その他
概要
・印象として、280よりかなり大きい
・パワーは280と比べ物にならないくらい強い
・バックラッシュ(関節のあそび)はある程度ある
・位置決め精度は申し分ない。
・280で環境をつくれていればすぐにでも移行できる(ROS)
個人的には値段に対して、かなり満足しています。
前情報
私が購入したのはmycobot 320 M5です。以前はmycobot pro の名称だったようです。スイッチサイエンス社経由で購入しました。
重量は3 kg、ペイロードは1 kg、作業半径は320 mmとなっており、値段は約37万円(2022年8月)です。私が調べたうちでは、市販されているものでこの金額・このスペックは破格の安さです。
購入の背景として、私がやりたいことに対して280の性能が追いつかなくなっており、悩んでいました。特に重さがかかったときの位置決め性能の悪さと、反力(?)がかかったときの280の「遊び」(バックラッシュ)の大きさが悩みでした。
私個人としては、320にホンマにパワーが有るのか、遊びはどれくらいあるのだろうか、というのが主な心配事でした。
開封
スイッチサイエンスで注文して、振り込み当日に発送、次の日の午前中に到着しました。はやい。14時までに振り込みをすればその日のうちに発送されるそうです。(2022年8月)
到着。

初手の印象、「でかい、重い」です。
280と違って、固定するための吸盤と緊急停止ボタンがついています。

とにかく大きいです。
280と並べてみました。

最初の組み立てに関しては、スイッチサイエンス社の動画を参考にしました。これがなかったら少し戸惑ったかも。
吸盤で固定というのが不安でしたが、実際固定してみるとかなりしっかりしています。外れそうな感じは一切ないです。
動かしてみる
案外公式がわかりやすいです。280と変わらない。
ダイレクトティーチングで動かしてみる。
ダイレクトティーチング。ぬるぬるしてる。素晴らしい。けっこう静か。 pic.twitter.com/2R3dUb5Dhw
— はるなし (@kk_mdimm) 2022年8月2日
slider_controlで動かす
slider_control
— はるなし (@kk_mdimm) 2022年8月2日
すんなり。 pic.twitter.com/GzUvGqxx1y
moveitとsync_plan.pyで動かす
(ほんとうにMoveitしているわけではない)
moveitと公式提供のsync_planで動かせた。すんなり。はんなり。 pic.twitter.com/p9V4v2ZUyO
— はるなし (@kk_mdimm) 2022年8月2日
パワーは?
250gほどのパーツを取り付けても余裕です。
ホントは1kgの負荷などもするべきなのですが、万が一でも破損したら泣いちゃうので手加減しました。
すげーーー!!楽々だ!すげえ!何でもできるぞ。やり直したい実験いっぱいある!!! pic.twitter.com/utU2VgxNSs
— はるなし (@kk_mdimm) 2022年8月2日
遊び(バックラッシュ)はどうなのか
slider_controlで位置決めをした後に確かめてみます。
遊びの原因はほとんどjoint1?? pic.twitter.com/0ijOZRzI8A
— はるなし (@kk_mdimm) 2022年8月4日
280と比べて各関節はかなりしっかりしている、が、ぶれるにはぶれます。いろいろ触ってみると、一番下(joint1)の遊びだけやたら大きいよう。
joint1の回転軸方向に力がかかるとかなり動いてしまいそうだが。他の関節はほとんどぶれない。
その他
レゴ・テクニカルパーツとの互換はありません。が、付属のネジでパーツをむりやり削って、取り付けることは一応可能ではありました。
こんなん想定していないと思うので非推奨ですが、一応可能ではあったという情報だけ。

とりあえず以上です。
追加でやったことなどは適宜追記していきます。
本業の研究にすでに使い始めている関係もあり、ところどころ甘いのですが、参考になれば幸いです。
個人的にはかなり満足しています。安いわけではないですが、価格に対しての性能は充分なのではと感じます。280で作った環境からROSですぐに動かせたのも好印象でした。
なにか指摘、やってほしい検証などあれば対応します。
お読みいただきありがとうございました。
iPhoneとMacがあるならあなたもARアプリを作れます RealityKitとBlenderで初めてのARアプリを作る【初心者向け】
はじめに
こんにちは!はるなしです。
最近はAR(拡張現実)の技術が面白いと感じていて、医療に応用できないかな、というところも見据えてかんたんなARアプリの開発を行っています。
僕はswift(Appleの製品で動くアプリを作るための言語)を使ってアプリ開発をしています。Appleが提供しているARKit、RealityKitというフレームワーク(ARアプリを作るための便利道具箱)を使うことで簡単にARアプリを作ることが可能で、今回は初心者向けに、簡単なARアプリ作成の記事を書こうと思います。
少しでも興味があるならば、ぜひ実際に手を動かしてアプリを作って欲しいです。特にARのアプリは実際に体験しないと凄さがわからないし、開発の難しさも自分でやらないとわからないです。自分で作ってみれば、何に応用できそうか、また限界はどのあたりにあるのかの勘所がつかめて、世界の解像度が上がると思います。想像したり、勉強したり、喋るだけではなく、「作ること」が重要だと僕は思います。
書くこと、書かないこと
書くこと
・簡単なARアプリ(自分で用意した3D モデルを平面上に出す)の作成
・しつこいくらいスクショを使った初心者向けの解説(真似するだけで作れる、を目指す)
書かないこと
・プログラミング言語(swift)の詳細
対象
最適
・macでアプリ開発の勉強は簡単にしたことあるけど、特に自分でなにか作ったことはないひと。
・swiftに限らず、なにかプログラミング言語を勉強したことがあるひと
少し頑張れば作れる
・アプリ開発は全くやったことがない。AR開発に興味がある
・プログラミング完全初心者
想定していない
・windowsパソコンしかもっていない(今回はapple限定です)
・つよのひと。
作るアプリ
平面に、Blenderで編集した3D球体を出現させるアプリ。

必要なもの・事前準備
必要なもの
mac or macbook 、iPhone or iPad
事前準備
Xcode(13.1)のダウンロード
→普通にApp Storeにあります。めちゃくちゃにダウンロードに時間がかかります(1日くらい)。導入の解説記事はいっぱいあるので参考に。※1
初めてのアプリをつくる
さっそくXcodeを開いてみましょう。
・Create a new Xcode projectをクリック

・Augumented Reality App (ARアプリのテンプレートが準備されている)
→Nextをクリック

・ProductNameを適当につける
interfaceはstoryboard
LanguageはSwiftに設定
→Next

・好きな場所に保存する
→Create

・こんな画面です。

じつは、テンプレートを使用したので、アプリはすでに完成しています。
どんなアプリが準備されているのか確認します。macとiPhone or iPadを接続して、さっそくビルド(アプリを実際のデバイスで動かすこと)してみましょう。iphoneをMacにつなぐと信頼しますか?と聞かれるので信頼する、で。
・上の方にデバイスの名前(iPod touchとか)が表示されている部分があります。そこをクリックすると、デバイスがたくさん選べます。その中から自分の「〇〇のiPhone」を選択しましょう。表示されない場合は接続し直したり、xcodeを再起動すると認識してくれます。

・選択できたら左上の再生ボタンをクリックするとアプリをデバイスに転送し始めます。初回は時間がかかることが多いので気長に待ちましょう。※2,3

・カメラを許可して・・・

ばばーーん!!
これは「デバイス起動後に最初に検知した水平面に四角い箱を置く」アプリです。
けっこう「そこにある感」がありませんか??iPhone,iPadをうりうり動かして遊んでください。
※1「Xcode ダウンロード 初心者」とかでいろいろ出てきます
※よくあるエラー The run destination 〇〇のiPad is not valid for Running the scheme 'sample_app'.The run destination 〇〇のiPad is not valid for Running the scheme 'sample_app'.
→iPhone,iPadのOSのバージョンが低すぎる、と怒っている。
左上のアプリ名クリックして、Deployment info のiOS を自分のデバイスに合わせてあげると解決します。

※よくあるエラー Could not launch “sample_app”
設定→一般→デバイス管理→Apple Development〜→青字のApple Development〜をタ ップ→信頼する
を設定したあともう一回再生ボタンを押してください
何がおこっているのか
アプリ作れたはいいですが、なんで動いているのかよくわからんですね。
このテンプレートアプリの仕組みを少し調べてみましょう。
・まず、左の「Experience」をクリックしてください。
・見覚えのある四角い箱です。右上の「open in reality composer」をクリックしてください


・こんなかんじ。

・Reality Composerは(おおまかには)表示する3Dモデルを編集するための画面です。黒い立方体があって、よく見ると、「アンカー」が「水平方向」と設定されていますね。
・この3Dモデルが配置されていろんな設定がされているものを「シーン」と呼びます。たとえば、ここに球体をもう一個追加したら、平面に立方体と球体が置かれます。(右上の「追加」から。)
・「シーン」には名前がついています。右上でシーンの名前が確認できます。このシーンの名前は「Box」です。
・ほかにも、立方体をクリックすると3Dモデルの大きさや「素材」を変更できます。
(ぜひ、いろいろと追加、変更してみて、もう一度再生マークからアプリをビルドし直してください。変更が反映されます。)

・他のファイルも確認しましょう。Reality composer(Experience.rcproject)はバツで閉じてください
・左の「View Controller」をクリックしてください。
コードが書かれていますね!!

・あまりびびらないでください。やってることは簡単です。(まだ理解できなくてOKです。なんとなくの把握だけ。)以下、ちょっと解説します。
・@IBOutlet var arView: ARView!
デバイス(iPhone,iPad)の画面に映すものを「arView」というものにまとめて取り扱いますよ、という意味。いきなり抽象的でよくわかんないですね。「arView」とはデバイスが認識する世界(平面とか画像マーカーとか)のことで、そこに準備した3Dモデルを追加していきます。
・override func viewDidLoad()
「アプリが起動されたときに以下のことを行いますよ」という意味。
・let boxAnchor = try! Experience.loadBox()
Experienceファイルから「Box」というシーンを読み込んで、boxAnchorという変数の中に入れますよ、という意味。先程確認したシーンには「Box」と名前がついていたことを思い出してください。
・arView.scene.anchors.append(boxAnchor)
「arView」に「boxAnchor」を追加しています。
ようするに画面上に読み込んだシーンを表示しますよ、ということです。
なんか難しいですね!!簡単のために厳密さは犠牲になっています。要するにExperienceファイルにある「シーン」を読み込んで、画面に表示していますよ、という処理です。
発展させる
ここまででけっこう盛り沢山でしたが、もうすこし頑張りましょう。
いままでの開発で、Reality Composerから立方体やら球体やらを追加することはできそうですが、実際になにか作りたいときに、それでは物足りないです。
どんなアプリを作るのかはアイデア次第ですが、もっと複雑な形の3Dモデルを取り扱いたいですよね。たとえば解剖の3Dモデルとか、3DCTとか、そんなんです。
これから、「Blender」と呼ばれる3Dモデルを編集するソフトを使って、球体をARアプリ上に表示させましょう。最終的な完成品はテンプレートアプリと変わりなく見えますが、内容はかなり高度になっています。自分で3Dモデルを用意しているので、配布されているモデルや、複雑な形をアプリ上で表現することができます。
おおまかには
・Blender上で3Dモデルの用意
・ファイルの書き出し
・ファイルの変換
・Xcodeに読み込み
・コードを少し書き換える
という流れです。難しいことはしないですが、Blenderを勉強すれば難しいこともできるようになります。
それではやっていきましょう。
3Dモデルの準備
・Blenderというソフトをダウンロードしてください
簡単なんで詳細省きます
・起動して、「全般」を開きます

・最初から、立方体が用意されてるかと思います。(されてない場合もあるかも)
さすがに同じもの表示してもつまらないので、右クリックから削除してください

・削除できたら左上の「追加」「メッシュ」「UV球」を選択します
(好きなやつでいいです)

・Blenderの機能を使ったらいろんな形の3Dもでるを作ったり、誰かが作った3Dモデルを利用できたりする(自分で作るよりこっちのほうが重要)のですが、今回は簡単のために球体追加しただけで次に進みます。
・いまからBlenderで編集したファイルを、Xcodeが読み込めるように変換してあげます。変換するだけなので難しいこと考えずに手順に従ってください。
・追加した球体を選択した状態(クリックして、周囲が黄色くなった状態)で左上の「ファイル」「エクスポート」「Universal Scene Description」を選択してください。

・好きな場所を選んでファイルに名前をつけ、「USDをエクスポート」をクリックします。あとからファイルを開く必要があるのでどこに保存したか覚えておいてください。今回はわかりやすさのためにデスクトップに置いています。

・さっき保存したファイルを開きます。usdcファイルとして保存されています

・じつはこのままではまだダメで、もう一度変換をする必要があります。手がかかるのです。usdcファイルを開き、左上の「File」「Export」を選択します

・「File Format」を「Universal Scene Description Package」に変更し、「where」から保存場所を指定し、「save」をクリックします。

・道のりながかったですがこれでファイルの準備はOKです。次に準備したファイルをXcodeに取り込み、アプリに反映させます。
アプリを更新する
Blenderで準備した3Dモデルをアプリに反映させます。大まかな作業としては、まず新しい「シーン」を作成し、「ViewController」を書き換えて新しいシーンを読み込みます。
・Xcodeに戻ります。左からExperience、Open in Reality Composerをクリックしてください。

・Reality Composerが開けたら、上の「シーン」を選択、「+」を押してください。

・「アンカーを選択」が出ると思うので、「水平方向」を選択します

・こんなかんじ。
白い箱と「選択して編集」は最初から用意されている3Dモデルです。不要なのでクリックして選択したあと削除します。

・用意したファイルをReality Composerに読み込みます。右上の「追加」「読み込む」をクリックして、さっき準備したファイルを選択します。

・するとRealityComposerに球体が読み込まれます。
実は、Blenderではメートル単位でモデルを作成しているので巨大な球体が追加されます。「追加されないな??」と思ったら、視点を遠くからにして動かしてみてください。

・サイズを調整します。球体をクリックして選択し、「サイズ調整」で大きさを変更します。僕は10%まで縮小しました。
・球体を原点に移動させます。○が書かれているところが原点です。球体を選択すると矢印が現れ、軸に沿って移動ができるので原点にドラッグしてください。

・シーンに名前をつけます。ViewControllerからシーンを読み込めるように、新しく作ったシーンに名前をつけます。右上に「シーン」と書かれているのでこれを「mySphere」に変更しましょう。

※このとき、球体を選択「しないで」名前をつけてください。球体を選択した状態だと、「シーン」ではなくて「モデルそのもの」に名前がついてしまいます。
・いよいよ大詰めです。Reality Composer を閉じて、ViewControllerを開いてください。

・解説したとおり、テンプレートのアプリでは「Box」というシーンを読み込んでいました。これを準備した「mySphere」に変更します。
・まず
let boxAnchor = try! Experience.loadBox()
の.loadBox()を削除します。
削除したところから続けて.loadと入力すると、入力候補が出てきます。
.loadmySphere()を選択してください。
Xcodeは賢いので、追加されたシーンを認識して、「こっちのシーンと入れ替えたいんやろ」というのを予測してくれるのです。※

※設定によっては予測候補が出現しない場合があります。そのときは.loadmySphere()と手打ちしてください。
※Type 'Experience' has no member 'loadmySphere'というエラーが出るときには、RealityComposerを開き直して、シーンの名前が変更されているか確認してください
・これでやっと完成です!!
最初と同じようにiPhone,iPadとつないで、再生ボタンからビルドしてみましょう。

・できました!!!

・けっこう大変だったかもしれません。お疲れさまです。
今後何をすればいいか
・今回の開発で一番基本のアプリ開発はできたと思います。
・もちろん、他にもできることはまだまだいっぱいあります。(画像マーカーとか)需要ありそうなら続編も書きます。
・つかれたので今後、は追記で書きます・・・
M1 MacBookでTensorFlowとXGBoostを動かす!!
M1がすごい、ということでsurfaceからmacbookに乗り換えました。大学の勉強関係で使うには素晴らしいのですが、プログラミングの環境構築に関しては悪夢でした。文字通り悪夢でした。
悪夢を乗り越えどうにかこうにかtensorflowとxgboostを動かしたので、mac初心者、環境構築なんもわからん、の環境構築を紹介したいと思います。
何もわからんまま環境構築、ではなく少しわかって環境構築したいので僕が勉強したこともちょいちょい挟んで書きます。
メニューは
1,最初の確認
2,HomeBrew導入
3,MiniForgeでTensorFlow-MacOSを動かす
4,CMakeによるビルドでXGBoostを動かす
です。いろんな方の記事を参考にしました。いろいろ間違っていることも書くかもしれないので、指摘してくださると幸いです。(とくに用語に関してひどいと思いますが、簡単を優先するのである程度お許しを。)
1,最初の確認
すばらしきM1 MacBookですが、インテルのCPU→アップル製CPUに変わった※ことでいろいろとめんどくさい事が起こります。
かんたんには、従来のアプリやパッケージはインテル向けに作られているので、それをM1で動かそうとすると色々噛み合わなくて困るわけです。
参考(動画めちゃわかりやすい)
※ほんとはCPUが変わったというよりコンピューターを動かす上でのCPUとかいろんなものをひっくるめた設計(アーキテクチャ)が変わっている
ちょっとこの辺確認してみます。Rosettaはすでに入っている前提です※2。
まず、アプリケーション→ターミナルを開いて
uname -m
というコマンドを打ちます。システムの情報を教えてくれるコマンドです。

arm 64ってのが「M1で動いてますよ」という意味です
次にアプリケーション→ターミナルを右クリックして情報を見る→Rosettaを使用して開く、にチェックします。

で、もういっかいターミナル開き直して uname -m を入力すると

x86_64に変わっています。Rosettaが有効になっているので、ホントはM1だけど、インテルのCPUとして認識できてますよ、という意味です。
なんとなくイメージ湧きますでしょうか。
参考
※2 Rosettaが必要なアプリを使おうとすると「Rosetta入れますね」と自動でやってくれます。僕はANKIというアプリを入れたらRosettaが入りました。
あと、事前知識として必要なのは
コマンドラインの基礎
PATHってなに??
ビルドってなに?(イメージ)
https://wa3.i-3-i.info/word12775.html
などなどです。目を通しておくと「ちょっとわかる」になる。
2,HomeBrew導入
ここが非常にわかりやすかったです
arm64(M1)版とx86(Rosetta経由)版両方を入れます。入れる場所が違います。
arm版を入れる
ターミナルをRosettaから開く、のチェックを外してから開く
arm版は/opt以下に入っていないといけないので、場所を指定してインストールする
cd /opt
sudo mkdir homebrew
sudo chown $USER /opt/homebrew
curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew

PATHを通します。
シェルはzshなので.zshrcを編集します。
ホームディレクトリに戻る
cd
touch .zshrc
で設定ファイルを作る
ls -a
で確認

ファインダーから確認。
.zshrcは隠しファイルなので表示されていない場合は
shift+command+. で表示

.zshrcに
export PATH=/opt/homebrew/bin:$PATH
を追加します。

再びターミナル
バージョン確認、最新にアップデートしておく。

x86版のhomebrewをインストール
Rosettaを使用して開く、にチェックしてターミナルを開き直す。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
これで入ります。
export PATH=/opt/homebrew/bin:/usr/local/bin:$PATH
をzshrcに追加。
確認↓
opt/にarm版のhomebrew
usr/localにx86版のhomebrewが入っている
参考
3,MiniForgeでtensorflow-macosを動かす
やっとこさ本題。
この記事を参照。ありがたや。
やってることおなじなのですが、一応書かせてください。
MiniForge(Anacondaの軽量版みたいなもの)を入れます。
arm64で

wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh
bash Miniforge3-MacOSX-arm64.sh
なんか色々聞かれるが全部enterかyes
miniforgeのPATHの確認↓
echo $PATH

自動でconda環境にならないようにする
conda config --set auto_activate_base false
以下、上で紹介した記事(Apple Silicon(M1) Mac+tensorflow-macosでディープラーニングする)と全く同じなので割愛します。
conda create --name python38 python=3.8
conda activate python38
から
・・・
pip install tensorboard
pip install --upgrade -t "$env/lib/python3.8/site-packages/" --no-dependencies --force "$libs/tensorflow_macos-0.1a2-cp38-cp38-macosx_11_0_arm64.whl"
をひたすら打ち込みます。
VSCodeからtensorflowが動くか確認
(VSCodeはuniversal版を入れました)
tf_test.py
とか作る。Pythonの拡張は言われたやつを適当に入れとく。
実際に学習してみる
tf_test.py
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
環境指定すると右上の実行ボタンから実行できる。
ターミナルからも。


動きましたー!めでたし。
4,XGBoostによるビルドでCMakeで動かす
Cmakeなるものを使ってビルドします。
これはあんましわかっていないのでなにか変なことをしているかも。
参考
VSCodeから作業ディレクトリに入って
さっきのconda環境に入る。
以下コマンドを実行していく。
git cloneで左にxgboostのディレクトリが出てくるので、ディレクトリの構造を参照しながら進めてください。
brew install cmake
git clone --recursive https://github.com/dmlc/xgboost
cd xgboost
mkdir build
cd build
cmake ..
make -j4
cd ..
cd python-package
ここで、python3をフルパスで指定できるように
which python3
でPythonのパスを調べて、
![]()
python3のパスのあとに
setup.py install
で実行する。
これで準備OK
sklearnを入れる。
conda install scikit-learn
サンプルコード
import xgboost as xgb
print(xgb)
print('OK!!)
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
dataset = datasets.load_breast_cancer()
X, y = dataset.data, dataset.target
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.3,
shuffle=True,
random_state=42,
stratify=y)
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
xgb_params = {
'objective': 'binary:logistic',
'eval_metric': 'logloss',
}
bst = xgb.train(xgb_params,
dtrain,
num_boost_round=100,
)
y_pred_proba = bst.predict(dtest)
y_pred = np.where(y_pred_proba > 0.5, 1, 0)
acc = accuracy_score(y_test, y_pred)
print('Accuracy:', acc)
実行すると・・・

こんなかんじで動きます。
やったー。
M1での環境構築、本当に地獄でした。いまはpipで入らない、とかいろいろありますがそのうち解消されるのでしょう。いろんな方の記事を参考にしてどうにか自分でやりきることができました。ありがとうございます。
PATHってなに?とかコマンドってなんで実行できるの?とかいろいろと勉強にはなりました。この記事が誰かの役に立ったなら幸いです。