パソコン練習日記

やってみたことを記録しています。Bloggerからこちらに引っ越して来ました。一部、画像がリンク切れしていますがひとつひとつ直すのは心が折れたのでそのままにします。

Logicoolのハンコン G29の値をC#で取得

やりたいことがあるので、ハンコンのアクセル開度やハンドルの値をC#で取得したいのです。

 

 

ということで

ちゃんと取得できるようになるまでの記録です。

実際に動いたプログラムはここに置いています。

github.com

 

まずは、ChatGPTにサンプル作ってとお願い。

「とりあえずハンドル角度とアクセル開度取得のプログラムお願いします。」

で、もらったのが以下。

ちなみにSharpDX.DirectInputをNuGetでインストールが必要。

using System;
using SharpDX.DirectInput;

class Program
{
    static void Main()
    {
        // DirectInputインスタンスを作成
        var directInput = new DirectInput();

        // 接続されているすべてのジョイスティックを取得
        var joystickGuids = directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices);
        Joystick joystick = null;

        // G29を検索
        foreach (var guid in joystickGuids)
        {
            var deviceInstance = directInput.GetDeviceDescriptor(guid.InstanceGuid);
            if (deviceInstance.ProductName.Contains("G29"))
            {
                joystick = new Joystick(directInput, guid.InstanceGuid);
                break;
            }
        }

        if (joystick == null)
        {
            Console.WriteLine("G29が見つかりませんでした。");
            return;
        }

        joystick.Acquire();

        while (true)
        {
            joystick.Poll();
            var joystickState = joystick.GetCurrentState();

            // ハンドルの角度 (通常はX軸)
            int wheelPosition = joystickState.X;

            // アクセルの開度 (通常は1つ目のスライダー)
            int acceleratorPosition = joystickState.Sliders[0];

            Console.WriteLine($"Wheel: {wheelPosition}, Accelerator: {acceleratorPosition}");
        }
    }
}

 

G29の検索する処理までちゃんと入っている。

素晴らしい。これは、一撃で終わるんじゃないか?と思いきやエラー。

 

エラー    CS1061    'DirectInput' に 'GetDeviceDescriptor' の定義が含まれておらず、型 'DirectInput' の最初の引数を受け付けるアクセス可能な拡張メソッド 'GetDeviceDescriptor' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください    logicoolG29    E:\work\logicoolG29\logicoolG29\Program.cs    18    アクティブ

 

エラーを伝えると修正を教えてくれる。

foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices))
{
    if (deviceInstance.ProductName.Contains("G29"))
    {
        joystick = new Joystick(directInput, deviceInstance.InstanceGuid);
        break;
    }
}

 

接続しているのに見つからんかった。

 

ChatGPTに相談したら

G29は実際にはDeviceType.JoystickよりもDeviceType.DrivingやDeviceType.Gamepadとして認識されることがあります。

ってことで、修正を作ってくれる。何回かやり取りして以下の修正案

class Program
{
    static void Main()
    {
        // ...

        var joystick = FindG29(directInput);

        if (joystick == null)
        {
            Console.WriteLine("G29が見つかりませんでした。");
            return;
        }

        // ...
    }

    static Joystick? FindG29(DirectInput directInput)  // static を追加
    {
        foreach (var deviceType in new { DeviceType.Driving, DeviceType.Gamepad, DeviceType.Joystick })
        {
            foreach (var deviceInstance in directInput.GetDevices(deviceType, DeviceEnumerationFlags.AllDevices))
            {
                if (deviceInstance.ProductName.Contains("G29"))
                {
                    return new Joystick(directInput, deviceInstance.InstanceGuid);
                }
            }
        }
        return null;
    }
}

 

取れた。と思ったけど、
アクセルの値は、実はクラッチの値。

ステアリングはあってる。

 

 

色々試したいので、ブレーキとクラッチも追加

// ハンドルの角度 (通常はX軸)
int wheelPosition = joystickState.X;

// アクセルの開度
int acceleratorPosition = joystickState.Sliders[0];

// ブレーキの開度
int brakePosition = joystickState.Sliders[1];

// クラッチの開度 (RotationZを使用)
int clutchPosition = joystickState.RotationZ;

Console.WriteLine($"Wheel: {wheelPosition}, Accelerator: {acceleratorPosition}, Brake: {brakePosition}, Clutch: {clutchPosition}");

クラッチのところがブレーキ。アクセルのところがクラッチがとれているのはいいとして、アクセルの値が取れていない。

 

まぁ、でもどうせアクセルだから

AccelerationXとか、AccelerationYとかAcceleration系の値のどれかが正解だろ?

と思いながら

// アクセルの開度
int acceleratorPosition =

に入るものを変えて見ていったけど、ぜんぜん正解にたどり着かない。

 

やり方を変えて見る。

ブレークポイントおいて、変数の中を見てみる。

 

これを見て、アクセルだけオンとオフの状態を比較すれば、それだろ。と

 

で、これがアクセルオフ

{X: 32864, Y: 65535, Z: 0, RotationX: 0, RotationY: 0, RotationZ: 65535, Sliders: 65535;0, PointOfViewControllers: -1;-1;-1;-1, Buttons: False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False, VelocityX: 0, VelocityY: 0, VelocityZ: 0, AngularVelocityX: 0, AngularVelocityY: 0, AngularVelocityZ: 0, VelocitySliders: 0;0, AccelerationX: 0, AccelerationY: 0, AccelerationZ: 0, AngularAccelerationX: 0, AngularAccelerationY: 0, AngularAccelerationZ: 0, AccelerationSliders: 0;0, ForceX: 0, ForceY: 0, ForceZ: 0, TorqueX: 0, TorqueY: 0, TorqueZ: 0, ForceSliders: 0;0}

 

これがアクセルオン

{X: 32864, Y: 0, Z: 0, RotationX: 0, RotationY: 0, RotationZ: 65535, Sliders: 65535;0, PointOfViewControllers: -1;-1;-1;-1, Buttons: False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False, VelocityX: 0, VelocityY: 0, VelocityZ: 0, AngularVelocityX: 0, AngularVelocityY: 0, AngularVelocityZ: 0, VelocitySliders: 0;0, AccelerationX: 0, AccelerationY: 0, AccelerationZ: 0, AngularAccelerationX: 0, AngularAccelerationY: 0, AngularAccelerationZ: 0, AccelerationSliders: 0;0, ForceX: 0, ForceY: 0, ForceZ: 0, TorqueX: 0, TorqueY: 0, TorqueZ: 0, ForceSliders: 0;0}

 

Yが変わってる。Yじゃね?

ってことで修正。

using System;
using SharpDX.DirectInput;

class Program
{
    static void Main()
    {
        // DirectInputのインスタンスを作成
        var directInput = new DirectInput();

        // 接続されているすべてのジョイスティックを取得
        var joystickGuids = directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices);
        var joystick = FindG29(directInput);

        if (joystick == null)
        {
            Console.WriteLine("G29が見つかりませんでした。");
            return;
        }

        joystick.Acquire();

        while (true)
        {
            joystick.Poll();
            var joystickState = joystick.GetCurrentState();

            // ハンドルの角度 (通常はX軸)
            int wheelPosition = joystickState.X;

            // アクセルの開度 (通常はY軸)
            int acceleratorPosition = joystickState.Y;

            // クラッチの開度 (RotationZを使用する場合)
            int clutchPosition = joystickState.Sliders[0];

            // ブレーキの開度
            int brakePosition = joystickState.RotationZ;

            Console.WriteLine($"Wheel: {wheelPosition}, Accelerator: {acceleratorPosition}, Brake: {brakePosition}, Clutch: {clutchPosition}");
        }
    }

    static Joystick? FindG29(DirectInput directInput)  // static を追加
    {
        foreach (var deviceType in new { DeviceType.Driving, DeviceType.Gamepad, DeviceType.Joystick })
        {
            foreach (var deviceInstance in directInput.GetDevices(deviceType, DeviceEnumerationFlags.AllDevices))
            {
                if (deviceInstance.ProductName.Contains("G29"))
                {
                    return new Joystick(directInput, deviceInstance.InstanceGuid);
                }
            }
        }
        return null;
    }
}

 

で、実行。

ちなみに、Gifにしているからカクカクしているけど、

実際は、0.001秒に30回ほど値を取得して表示している。

 

これでとりあえず、C#でG29の値が取れることはわかったので、

次に進もうと思う。

 

[blog:g:4207112889945342980:banner][blog:g:11696248318754550877:banner][blog:g:11696248318754550880:banner]