A Practical Investigation of Optimal Strategies on the Flüela Pass
フルエラ峠における最適戦略の実践的検討

Author

Stefan Wolf, Raphael Bertschinger

Published

2016

Published in: Workshop Modelling in Endurance Sports, pp. 11–13


Data: 2024/03/26, 佐々木毅然

keywords: 最適ペーシング戦略 (Optimal Pacing Strategy), 自転車シミュレーター (Cycling Simulator), 臨界パワーモデル (Critical Power Model),最適制御 (Optimal Control),実験検証 (Experimental Validation)

1. 背景, 目的

  近年,持久力系スポーツにおいて,数理モデルに基づくペーシング戦略の最適化が注目されているが,既存研究は理論的なものが多く,実用的な応用例が少ない。本研究は,実コースデータを用いて,シミュレーションによる最適戦略のフィードバックを行い,その効果を検証することを目的とする。

2. 実験方法

2.1. 対象者:6名。男女,身体,体重,組成および年齢等の記載無し。
2.2. 実験機材:自転車シミュレータ(Cyclus2 brakeおよび同ソフトウェア[4])。ビジュアルフィードバックシステム。 https://www.cyclus2.com/en/home.htm
2.3. 実験手順:フリューエラ峠(スイス)の東側登りコースをシミュレーション
a. 漸増負荷運動による無酸素性作業閾値測定試験〔対象者の無酸素性作業閾値(AT)の推定〕
b. ライド I: 練習走行(適切なベンチマークを得るため。できる限りAT値での走行が望まれた。)
c. ライドII: 自己ペーシング走行(対象者が自由にペースを選択)
d. ライドIII: 最適戦略フィードバック下走行(計算した最適ペーシング戦略に従う)
e. ライドIV: 検証戦略フィードバック下走行(自己ペーシングより高出力の検証用ペーシング)
2.4. 測定項目:総レースタイム,推定出力と実出力の二乗平均平方根誤差(RMSE)
2.5. 統計解析:記載無し。
2.6. 最適戦略の導出:物理モデル(ペダル踏力,空力抗力,摩擦,重力,慣性の平衡)とMorton臨界パワーモデル[5]を組み合わせて,生理能力のモデリングによる最適制御問題を定義して,GPOPS II[6]を使用して解いた。
2.7. パラメータ推定:ステップテスト,ライドI,IIを通して,レース終了時に嫌気性作業能力がゼロになるようパラメータを設定した。

3. 結果および考察

 全対象者が提案された最適戦略に従った結果,自己ペースのライドIIと比較して総レースタイムが約1.9%短縮された。また,6人中3人の対象者が検証戦略IVを実行できた。これは、かれらがライドIIで疲労困憊に至らなかったため,よりエネルギーを消費する検証タスクを最後まで維持できた可能性があることを示唆した。しかし,日々のパフォーマンス変動も結果に影響を与えた可能性も考えられる。それにもかかわらず,検証戦略に従えなかった3人の対象者は,最適戦略が自己ペース戦略よりも利点があることを示している。また、提案された出力と実験中の出力との間のRMSEは、最適戦略フィードバックの走行(ライドIII)よりも検証走行(ライドIV)で有意に高かったことが表2に示された。

4. まとめ

 本研究では実コースでの最適ペーシング戦略の実現可能性と有効性が示された。しかし,戦略そのものとフィードバックの効果を分離することが課題として残った。

Code
# 必要なライブラリをインストールして読み込み
library(ggplot2)
#| echo = false

# 予測値と実際の値のサンプルデータ
actual <- c(100, 150, 200, 250, 300)
predicted <- c(110, 140, 210, 240, 310)
data <- data.frame(Index = 1:length(actual), Actual = actual, Predicted = predicted)

# RMSEを計算する関数
rmse <- function(actual, predicted) {
  sqrt(mean((predicted - actual)^2))
}

# RMSEを計算
rmse_value <- rmse(data$Actual, data$Predicted)
print(paste("RMSE:", rmse_value))
[1] "RMSE: 10"
Code
# データを可視化 折れ線グラフ
ggplot(data, aes(x = Index)) +
  geom_line(aes(y = Actual, colour = "Actual"), linewidth = 1) +
  geom_line(aes(y = Predicted, colour = "Predicted"), linewidth = 1.5) +
  geom_segment(aes(xend = Index, y = Actual, yend = Predicted, colour = "Error"),
               linewidth = 1.5, linetype = "dashed") +
  labs(title = "Actual vs Predicted Values with RMSE(image)", x = "Index", y = "Value") +
  theme_minimal() +
  scale_colour_manual("", values = c("Actual" = "blue", "Predicted" = "red", "Error" = "gray50"),
                      limits = c("Actual", "Predicted", "Error")) +
  theme(axis.title.x = element_text(size = 14, face = "bold"),
        axis.title.y = element_text(size = 14, face = "bold"),
        axis.text.x = element_text(size = 12, face = "bold"),
        axis.text.y = element_text(size = 12, face = "bold"),
        axis.line = element_line(linewidth = 0),  # x軸とy軸の線を太くする
        plot.title = element_text(face = "bold"),
        panel.grid = element_line(linewidth = 0.3, color = "black"), # グリッド線を太くする
        legend.text = element_text(face = "bold"),
        legend.title = element_text(face = "bold")) +
    geom_hline(yintercept = 100, linewidth = 0.7, colour = "black")  # y=0に水平線を

Code
# RMSEのデータを作成(ここでは仮のデータを使用)
data <- data.frame(
  Ride = c("Ride II", "Ride IV"),
  RMSE = c(10, (10-0.19))  # 仮のRMSE値
)

# 棒グラフでRMSEをプロットし、有意差を表す
# データを可視化 棒グラフ
# ggplot(data, aes(x = Ride, y = RMSE)) +
#   geom_bar(stat = "identity", aes(fill = Ride), colour = "black", alpha = 0.7) +
#   scale_fill_manual(values = c("Ride II" = "lightgray", "Ride IV" = "gray21")) +
#   labs(title = "RMSE for Each Ride", x = NULL, y = "RMSE") +  # x軸ラベルを非表示にする
#   theme_minimal() +
#   # annotate("text", x = "Ride IV", y = max(data$RMSE) + 1, label = "*", size = 6, fontface = "bold") + 統計検定を行っていないので、星印を表示させない。
#   theme(text = element_text(family = "Times New Roman", face = "bold"),
#         axis.text.x = element_text(size = 14, face = "bold"),  # x軸のテキストを大きく、太字にする
#         axis.text.y = element_text(size = 14, face = "bold"),  # y軸のテキストを大きく、太字にする
#         plot.title = element_text(size = 16, face = "bold"),  # タイトルを大きく、太字にする
#         legend.position = "none",  # 凡例を非表示にする
#         axis.title.x = element_blank()) + # x軸のタイトルを非表示にする
#   geom_hline(yintercept = 0, linewidth = 0.7, colour = "black")  # y=0に水平線を引く
 

# Defalut in color
# 棒グラフでRMSEをプロット 棒グラフグレー
# ggplot(data, aes(x = Ride, y = RMSE, fill = Ride)) +
#   geom_bar(stat = "identity") +
#   labs(title = "RMSE for Each Ride", x = "Ride", y = "RMSE") +
#   theme_minimal()