宇宙船の惑星スイングバイのシュミレーション DeepSeekとChatGDPで作成

宇宙船の惑星スイングバイ

宇宙船が惑星や月の重力を利用して軌道や速度を変更する航法です。推進剤をほとんど消費せずに速度を大きく変更できるため、燃料の補給が困難な惑星探査において重要な役割を果たしています。

シュミレーション

DeepSeekでjavascriptでシュミレーション作成

シュミレーションHTML(swinby.html)

スイングバイシュミレーション

スマホはswingbyiphoneから開いてください

DeepSeekを使ったシュミレーションのプログラムです。
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>宇宙船スイングバイシミュレーション</title>
    <style>
        canvas {
            border: 1px solid black;
            display: block;
            margin: 0 auto;
        }
        #controls {
            text-align: center;
            margin-top: 10px;
        }
        button {
            padding: 10px 20px;
            font-size: 16px;
        }
        label {
            font-size: 16px;
            margin-right: 10px;
        }
        input[type="range"] {
            width: 200px;
        }
    </style>
</head>
<body>
    <canvas id="spaceCanvas" width="800" height="600"></canvas>
    <div id="controls">
        <button id="startButton">スタート</button>
        <button id="stopButton">ストップ</button>
        <button id="resetButton">リセット</button>
        <div>
            <label for="speedSlider">宇宙船の速度:</label>
            <input type="range" id="speedSlider" min="0.1" max="5" step="0.1" value="2">
            <span id="speedValue">2</span>
        </div>
        <div>
            <label>実際の速度:</label>
            <span id="actualSpeedValue">0</span>
        </div>
    </div>
    <script>
        const canvas = document.getElementById('spaceCanvas');
        const ctx = canvas.getContext('2d');

        // 中心の星(仮想的な中心点)の設定
        const centerStar = {
            x: canvas.width / 2,
            y: canvas.height / 2,
            radius: 20,
            mass: 100000
        };

        // 惑星の初期設定
        const planet = {
            x: canvas.width / 2 + 200, // 初期位置を中心から離す
            y: canvas.height / 2,
            radius: 20, // 惑星のサイズを小さくする
            mass: 10000,
            orbitRadius: 200, // 公転半径
            orbitSpeed: 0.02, // 公転速度(ラジアン/フレーム)
            angle: 0 // 公転角度
        };

        // 宇宙船の初期設定
        const spaceship = {
            x: 100,
            y: 100,
            radius: 5,
            vx: 2, // 初期速度
            vy: 0,
            mass: 1
        };

        const G = 0.1; // 重力定数(シミュレーション用)

        let animationId = null; // アニメーションIDを保持する変数
        let isRunning = false; // アニメーションの実行状態を管理するフラグ

        // 速度スライダーの要素を取得
        const speedSlider = document.getElementById('speedSlider');
        const speedValue = document.getElementById('speedValue');
        const actualSpeedValue = document.getElementById('actualSpeedValue');

        // スライダーの値が変更されたときのイベントリスナー
        speedSlider.addEventListener('input', () => {
            const speed = parseFloat(speedSlider.value);
            spaceship.vx = speed; // 宇宙船の速度を更新
            speedValue.textContent = speed; // 表示を更新
        });

        // 宇宙船をリセットする関数
        function resetSpaceship() {
            spaceship.x = 100;
            spaceship.y = 100;
            spaceship.vx = parseFloat(speedSlider.value);
            spaceship.vy = 0;
        }

        // 宇宙船の速度を計算する関数
        function calculateSpeed() {
            return Math.sqrt(spaceship.vx * spaceship.vx + spaceship.vy * spaceship.vy);
        }

        // 惑星の公転を更新する関数
        function updatePlanetOrbit() {
            planet.angle += planet.orbitSpeed; // 公転角度を更新
            planet.x = centerStar.x + Math.cos(planet.angle) * planet.orbitRadius; // X座標を更新
            planet.y = centerStar.y + Math.sin(planet.angle) * planet.orbitRadius; // Y座標を更新
        }

        // アニメーションの更新
        function update() {
            // 惑星の公転を更新
            updatePlanetOrbit();

            // 惑星と宇宙船の距離を計算
            const dx = planet.x - spaceship.x;
            const dy = planet.y - spaceship.y;
            const distance = Math.sqrt(dx * dx + dy * dy);

            // 重力による加速度を計算
            const force = (G * planet.mass) / (distance * distance);
            const angle = Math.atan2(dy, dx);
            const ax = force * Math.cos(angle);
            const ay = force * Math.sin(angle);

            // 宇宙船の速度を更新
            spaceship.vx += ax;
            spaceship.vy += ay;

            // 宇宙船の位置を更新
            spaceship.x += spaceship.vx;
            spaceship.y += spaceship.vy;

            // 画面外に出た場合の処理
            if (spaceship.x < 0 || spaceship.x > canvas.width || spaceship.y < 0 || spaceship.y > canvas.height) {
                resetSpaceship();
            }

            // 実際の速度を表示
            actualSpeedValue.textContent = calculateSpeed().toFixed(2);
        }

        // 描画関数
        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 中心の星を描画
            ctx.beginPath();
            ctx.arc(centerStar.x, centerStar.y, centerStar.radius, 0, Math.PI * 2);
            ctx.fillStyle = 'yellow';
            ctx.fill();

            // 惑星を描画
            ctx.beginPath();
            ctx.arc(planet.x, planet.y, planet.radius, 0, Math.PI * 2);
            ctx.fillStyle = 'blue';
            ctx.fill();

            // 宇宙船を描画
            ctx.beginPath();
            ctx.arc(spaceship.x, spaceship.y, spaceship.radius, 0, Math.PI * 2);
            ctx.fillStyle = 'red';
            ctx.fill();
        }

        // アニメーションループ
        function animate() {
            update();
            draw();
            if (isRunning) {
                animationId = requestAnimationFrame(animate);
            }
        }

        // スタートボタンのイベントリスナー
        document.getElementById('startButton').addEventListener('click', () => {
            if (!isRunning) {
                isRunning = true;
                animate();
            }
        });

        // ストップボタンのイベントリスナー
        document.getElementById('stopButton').addEventListener('click', () => {
            if (isRunning) {
                isRunning = false;
                cancelAnimationFrame(animationId);
            }
        });

        // リセットボタンのイベントリスナー
        document.getElementById('resetButton').addEventListener('click', () => {
            resetSpaceship();
            isRunning = false;
            cancelAnimationFrame(animationId);
            draw(); // リセット後の状態を描画
            actualSpeedValue.textContent = calculateSpeed().toFixed(2); // 速度を更新
        });

        // 初期描画
        draw();
        actualSpeedValue.textContent = calculateSpeed().toFixed(2); // 初期速度を表示
    </script>
</body>
</html>
スマホ対応(ChatGDP)で作りました。
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>宇宙船スイングバイシミュレーション</title>
    <style>
        canvas {
            border: 1px solid black;
            display: block;
            margin: 0 auto;
            max-width: 100%;
            height: auto;
        }
        #controls {
            text-align: center;
            margin-top: 10px;
        }
        button {
            padding: 10px 20px;
            font-size: 16px;
            margin: 5px;
        }
        label {
            font-size: 16px;
            margin-right: 10px;
        }
        input[type="range"] {
            width: 100%;
            max-width: 200px;
        }
    </style>
</head>
<body>
    <canvas id="spaceCanvas"></canvas>
    <div id="controls">
        <button id="startButton">スタート</button>
        <button id="stopButton">ストップ</button>
        <button id="resetButton">リセット</button>
        <div>
            <label for="speedSlider">宇宙船の速度:</label>
            <input type="range" id="speedSlider" min="0.1" max="5" step="0.1" value="2">
            <span id="speedValue">2</span>
        </div>
        <div>
            <label>実際の速度:</label>
            <span id="actualSpeedValue">0</span>
        </div>
    </div>
    <script>
        const canvas = document.getElementById('spaceCanvas');
        const ctx = canvas.getContext('2d');

        // 恒星
        const centerStar = { x: 0, y: 0, radius: 20, mass: 100000 };

        // 惑星
        const planet = { x: 0, y: 0, radius: 15, mass: 10000, orbitRadius: 0, orbitSpeed: 0.02, angle: 0 };

        // 宇宙船
        const spaceship = { x: 100, y: 100, radius: 5, vx: 2, vy: 0, mass: 1 };

        const G = 0.1; // 重力定数
        let isRunning = false;
        let animationId = null;

        // キャンバスのリサイズ
        function resizeCanvas() {
            canvas.width = window.innerWidth * 0.9;
            canvas.height = window.innerHeight * 0.7;
            centerStar.x = canvas.width / 2;
            centerStar.y = canvas.height / 2;
            planet.orbitRadius = Math.min(canvas.width, canvas.height) * 0.3;
            draw();
        }
        window.addEventListener('resize', resizeCanvas);
        resizeCanvas();

        // 惑星の公転を更新
        function updatePlanetOrbit() {
            planet.angle += planet.orbitSpeed;
            planet.x = centerStar.x + Math.cos(planet.angle) * planet.orbitRadius;
            planet.y = centerStar.y + Math.sin(planet.angle) * planet.orbitRadius;
        }

        // 宇宙船の速度を計算
        function calculateSpeed() {
            return Math.sqrt(spaceship.vx ** 2 + spaceship.vy ** 2);
        }

        // 宇宙船のリセット
        function resetSpaceship() {
            spaceship.x = 100;
            spaceship.y = 100;
            spaceship.vx = parseFloat(speedSlider.value);
            spaceship.vy = 0;
        }

        // 物理計算
        function update() {
            updatePlanetOrbit();

            const dx = planet.x - spaceship.x;
            const dy = planet.y - spaceship.y;
            const distance = Math.sqrt(dx ** 2 + dy ** 2);

            // 重力の計算
            if (distance > planet.radius) {
                const force = (G * planet.mass) / (distance ** 2);
                const angle = Math.atan2(dy, dx);
                const ax = force * Math.cos(angle);
                const ay = force * Math.sin(angle);
                spaceship.vx += ax;
                spaceship.vy += ay;
            }

            // 宇宙船の移動
            spaceship.x += spaceship.vx;
            spaceship.y += spaceship.vy;

            // 画面外に出た場合の処理
            if (spaceship.x < 0 || spaceship.x > canvas.width || spaceship.y < 0 || spaceship.y > canvas.height) {
                resetSpaceship();
            }

            actualSpeedValue.textContent = calculateSpeed().toFixed(2);
        }

        // 描画
        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 恒星
            ctx.beginPath();
            ctx.arc(centerStar.x, centerStar.y, centerStar.radius, 0, Math.PI * 2);
            ctx.fillStyle = 'yellow';
            ctx.fill();

            // 惑星
            ctx.beginPath();
            ctx.arc(planet.x, planet.y, planet.radius, 0, Math.PI * 2);
            ctx.fillStyle = 'blue';
            ctx.fill();

            // 宇宙船
            ctx.beginPath();
            ctx.arc(spaceship.x, spaceship.y, spaceship.radius, 0, Math.PI * 2);
            ctx.fillStyle = 'red';
            ctx.fill();
        }

        // アニメーションループ
        function animate() {
            update();
            draw();
            if (isRunning) {
                animationId = requestAnimationFrame(animate);
            }
        }

        // UIイベント
        document.getElementById('startButton').addEventListener('click', () => {
            if (!isRunning) {
                isRunning = true;
                animate();
            }
        });

        document.getElementById('stopButton').addEventListener('click', () => {
            isRunning = false;
            cancelAnimationFrame(animationId);
        });

        document.getElementById('resetButton').addEventListener('click', () => {
            resetSpaceship();
            isRunning = false;
            cancelAnimationFrame(animationId);
            draw();
            actualSpeedValue.textContent = calculateSpeed().toFixed(2);
        });

        document.getElementById('speedSlider').addEventListener('input', () => {
            spaceship.vx = parseFloat(speedSlider.value);
            speedValue.textContent = speedSlider.value;
        });

        draw();
    </script>
</body>
</html>

 

文字で読むよりシュミレーションで見る方がよくわかりますね。
チャットに「宇宙船が公転する惑星によるスイングバイのシュミレーションプログラムをJavascriptで作って。」と入力して作りました。
スタートボタンなど配置やスピードの変更などを追加しました。
AIは、全くエラー構文を作らずにプログラムを作っています。
ここまで、20分くらいでした。
ただDeepseekの回答が途切れることがありました。その都度、新規に始めて続けました。
チャットに入力する際、日本語は普通に使えますが漢字変換後の確定のためのエンターキーで送信されてしまうので注意が必要です。
スマホ版はDeepseekではうまくできませんでした。そこでChatGDPで作ってもらいました。作成速度は同じくらいですが、安定していました。