x形式オブジェクトをunityで表示する試み

assimpライブラリを使用して、x形式のオブジェクトをunity中へ読み込んでみたテストです。試してから1年以上放置していましたが、もったいないので公開します。

内房線アドオン同梱のTc208-2100f_Sotobo.x を表示させた例を次図に示します。

使い方は下記のとおりです。

  1. 下記コードを適当なC#スクリプトとして保存する
    • start関数中のfilepathを読み込みたいxファイルのパスへ書き換える
  2. 空のオブジェクトを作成して、1で作成したスクリプトファイルをアタッチする
  3. playすると、2で作成したオブジェクトがfilepathのxオブジェクトに置き換えられる

注意:テクスチャファイルはdds(DXT1)フォーマットのみ対応しています。png, bmpには未対応です。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Assimp;
using System.IO;

public class Assimp2 : MonoBehaviour
{
    public struct DdsHeader
    {
        public System.String dwMagic;
        public System.UInt32 dwSize;
        public System.UInt32 dwFlags;
        public System.UInt32 dwHeight;
        public System.UInt32 dwWidth;
        public System.UInt32 dwDepth;
        public System.UInt32 dwPitchOrLinearSize;
        public System.UInt32 dwMipMapCount;
        public System.UInt32 dwPfSize;
        public System.UInt32 dwPfFlags;
        public System.String dwFourCC;
        public System.UInt32 dwRGBBitCount;
        public System.UInt32 dwAlphaBitMask;
        public System.UInt32 dwCaps;
        public System.UInt32 dwCaps2;
    }
    DdsHeader readDdsHeader(byte[] bytes)
    {
        int pointer = 0;
        DdsHeader header = new DdsHeader();
        System.Text.Encoding encascii = System.Text.Encoding.ASCII;
        if (System.BitConverter.ToUInt32(bytes, pointer) == 0x20534444)
        {
            header.dwMagic = encascii.GetString(bytes, pointer, 4);
            pointer += 4;
            header.dwSize = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwFlags = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwHeight = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwWidth = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwPitchOrLinearSize = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwDepth = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwMipMapCount = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            pointer += 4 * 11;
            header.dwPfSize = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwPfFlags = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwFourCC = encascii.GetString(bytes, pointer, 4);
            pointer += 4;
            header.dwRGBBitCount = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwAlphaBitMask = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwCaps = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;
            header.dwCaps2 = System.BitConverter.ToUInt32(bytes, pointer);
            pointer += 4;

            Debug.LogFormat("dwMagic: {0}", header.dwMagic);
            Debug.LogFormat("dwSize: {0}", header.dwSize);
            Debug.LogFormat("dwFlags: {0}", header.dwFlags);
            Debug.LogFormat("dwHeight: {0}", header.dwHeight);
            Debug.LogFormat("dwWidth: {0}", header.dwWidth);
            Debug.LogFormat("dwPitchOrLinearSize: {0}", header.dwPitchOrLinearSize);
            Debug.LogFormat("dwDepth: {0}", header.dwDepth);
            Debug.LogFormat("dwMipMapCount: {0}", header.dwMipMapCount);
            Debug.LogFormat("dwPfSize: {0}", header.dwPfSize);
            Debug.LogFormat("dwPfFlags: {0}", header.dwPfFlags);
            Debug.LogFormat("dwFourCC: {0}", header.dwFourCC);
            Debug.LogFormat("dwRGBBitCount: {0}", header.dwRGBBitCount);
            Debug.LogFormat("dwRGBAlphaBitMask: {0}", header.dwAlphaBitMask);
            Debug.LogFormat("dwCaps: {0}", header.dwCaps);
            Debug.LogFormat("dwCaps2: {0}", header.dwCaps2);
        }
        return header;
    }
    // Start is called before the first frame update
    void Start()
    {
        byte[] readPngFile(string path)
        {
            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                BinaryReader bin = new BinaryReader(fileStream);
                byte[] values = bin.ReadBytes((int)bin.BaseStream.Length);
                Debug.LogFormat("{0}, {1}", path, bin.BaseStream.Length);
                bin.Close();
                return values;
            }

        }
        Texture readByBinary(byte[] bytes)
        {

            DdsHeader header = readDdsHeader(bytes);
            if (header.dwFourCC == "DXT1")
            {
                Debug.LogFormat("load {0}, ({1},{2})", header.dwFourCC, (int)header.dwWidth, (int)header.dwHeight);
                Texture2D texture = new Texture2D((int)header.dwWidth, (int)header.dwHeight, TextureFormat.DXT1, false);
                byte[] texData = new byte[bytes.Length - 128];
                Debug.LogFormat("len: {0}, {1}", bytes.Length - 128, texData.Length);
                System.Buffer.BlockCopy(bytes, 128, texData, 0, bytes.Length - 128);
                Debug.LogFormat("{0}", texData[texData.Length - 1]);

                texture.LoadRawTextureData(texData);
                texture.Apply();
                Texture2D flippedTexture = new Texture2D(texture.width, texture.height);
                for (int y = 0; y < flippedTexture.height; y++)
                {
                    for (int x = 0; x < flippedTexture.width; x++)
                    {
                        flippedTexture.SetPixel(x, flippedTexture.height - y, texture.GetPixel(x, y));
                    }
                }
                flippedTexture.Apply();
                return flippedTexture;
            }
            else
            {
                Debug.LogFormat("load {0}, ({1},{2})", header.dwFourCC, (int)header.dwWidth, (int)header.dwHeight);
                Texture2D texture = new Texture2D((int)header.dwWidth, (int)header.dwHeight, TextureFormat.DXT5, false);

                byte[] texData = new byte[bytes.Length - 128];
                Debug.LogFormat("len: {0}, {1}", bytes.Length - 128, texData.Length);
                System.Buffer.BlockCopy(bytes, 128, texData, 0, bytes.Length - 128);
                Debug.LogFormat("{0}", texData[texData.Length - 1]);

                texture.LoadRawTextureData(texData);
                texture.Apply();

                Texture2D flippedTexture = new Texture2D(texture.width, texture.height);
                for (int y = 0; y < flippedTexture.height; y++)
                {
                    for (int x = 0; x < flippedTexture.width; x++)
                    {
                        flippedTexture.SetPixel(x, flippedTexture.height - y, texture.GetPixel(x, y));
                    }
                }
                flippedTexture.Apply();
                return flippedTexture;
            }

        }

        // https://rikoubou.hatenablog.com/entry/2016/02/01/212504
        // https://answers.unity.com/questions/555984/can-you-load-dds-textures-during-runtime.html

        Texture loadImageformBynary(byte[] bytes)
        {
            Texture2D texture = new Texture2D(4, 4);
            texture.LoadImage(bytes);
            return texture;
        }


        AssimpContext importer = new AssimpContext();
        string filePath = "hogehoge"; // 読み込みたいxファイルへのパスを指定
        Scene scene = importer.ImportFile(filePath,
            PostProcessSteps.MakeLeftHanded |
            PostProcessSteps.FlipWindingOrder |
            PostProcessSteps.Triangulate);

        List<UnityEngine.Material> matelialList = new List<UnityEngine.Material>();


        Debug.LogFormat("MaterialCount: {0}", scene.MaterialCount);

        foreach (Assimp.Material mat in scene.Materials)
        {
            UnityEngine.Material unityMatelial = new UnityEngine.Material(Shader.Find("Standard"));

            Debug.LogFormat("ColorDiffuse: {0},{1},{2},{3}", mat.ColorDiffuse[0], mat.ColorDiffuse[1], mat.ColorDiffuse[2], mat.ColorDiffuse[3]);
            Debug.LogFormat("Shininess: {0}", mat.Shininess);
            Debug.LogFormat("ColorSpecular: {0},{1},{2},{3}", mat.ColorSpecular[0], mat.ColorSpecular[1], mat.ColorSpecular[2], mat.ColorSpecular[3]);
            Debug.LogFormat("ColorEmissive: {0},{1},{2},{3}", mat.ColorEmissive[0], mat.ColorEmissive[1], mat.ColorEmissive[2], mat.ColorEmissive[3]);
            if (mat.HasTextureDiffuse)
            {
                Debug.LogFormat("TextureFilePath: {0}", mat.TextureDiffuse.FilePath);
                unityMatelial.mainTexture = readByBinary(readPngFile(Path.Combine(Path.GetDirectoryName(filePath), mat.TextureDiffuse.FilePath)));
                unityMatelial.shader = Shader.Find("Standard");

                unityMatelial.SetOverrideTag("RenderType", "TransparentCutout");
                unityMatelial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                unityMatelial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                unityMatelial.SetInt("_ZWrite", 1);
                unityMatelial.EnableKeyword("_ALPHATEST_ON");
                unityMatelial.DisableKeyword("_ALPHABLEND_ON");
                unityMatelial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                unityMatelial.renderQueue = 2450;
                //https://programming.sincoston.com/unity-transparent-image/
                //https://qiita.com/polikeiji/items/e56febcfdf886524352c

            }

            unityMatelial.color = new Color(mat.ColorDiffuse[0], mat.ColorDiffuse[1], mat.ColorDiffuse[2]);


            matelialList.Add(unityMatelial);
        }

        UnityEngine.Material mate = new UnityEngine.Material(Shader.Find("Standard"));

        MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
        meshRenderer.sharedMaterials = matelialList.ToArray();




        MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();

        submesh(scene, meshFilter);

    }

    // Update is called once per frame
    void Update()
    {

    }

    void submesh(Scene scene, MeshFilter meshFilter)
    {
        List<Vector3> verts_u = new List<Vector3>();
        List<int> tris_u = new List<int>();
        List<Vector3> norms_u = new List<Vector3>();
        List<Vector2> uvs_u = new List<Vector2>();
        UnityEngine.Mesh mesh = new UnityEngine.Mesh();

        List<int> subMeshVertList = new List<int>();
        Dictionary<int, List<int>> subMeshVertDict = new Dictionary<int, List<int>>();
        Dictionary<int, int> subMeshMaterialDict = new Dictionary<int, int>();
        int subMeshVertIndex = 0;
        int subMeshIndex = 0;

        foreach (Assimp.Mesh m in scene.Meshes)
        {


            List<Vector3D> verts = m.Vertices;
            List<Vector3D> norms = (m.HasNormals) ? m.Normals : null;
            List<Vector3D> uvs = m.HasTextureCoords(0) ? m.TextureCoordinateChannels[0] : null;

            List<Face> faces = m.Faces;
            List<int> tris = new List<int>();

            subMeshVertList.Add(subMeshVertIndex);
            subMeshMaterialDict.Add(subMeshIndex, m.MaterialIndex);

            Debug.LogFormat("verts: {0}", verts.Count);
            Debug.LogFormat("norms: {0}", norms.Count);
            Debug.LogFormat("uvs: {0}", uvs.Count);
            Debug.LogFormat("faces: {0}", faces.Count);
            Debug.LogFormat("MaterialIndex: {0}", m.MaterialIndex);

            for (int i = 0; i < verts.Count; i++)
            {
                verts_u.Add(new Vector3(verts[i][0], verts[i][1], verts[i][2]));
            }

            for (int i = 0; i < norms.Count; i++)
            {
                norms_u.Add(new Vector3(norms[i][0], norms[i][1], norms[i][2]));
            }

            for (int i = 0; i < uvs.Count; i++)
            {
                uvs_u.Add(new Vector2(uvs[i][0], uvs[i][1]));
            }


            for (int i = 0; i < faces.Count; i++)
            {
                for (int j = 0; j < faces[i].IndexCount; j++)
                {
                    tris_u.Add(faces[i].Indices[j] + subMeshVertIndex);
                    tris.Add(faces[i].Indices[j] + subMeshVertIndex);
                }
            }


            subMeshVertDict.Add(subMeshIndex, tris);
            subMeshVertIndex += verts.Count;
            subMeshIndex += 1;

        }

        Debug.LogFormat("subMeshVertDict.Count: {0}", subMeshVertDict.Count);

        mesh.SetVertices(verts_u.ToArray());
        mesh.SetNormals(norms_u.ToArray());
        mesh.SetUVs(0, uvs_u.ToArray());

        mesh.subMeshCount = subMeshVertDict.Count;

        foreach (int i in subMeshVertDict.Keys)
        {
            mesh.SetTriangles(subMeshVertDict[i], i);
            Debug.LogFormat("{0}", i);
        }


        meshFilter.mesh = mesh;
    }

    void combineMesh(Scene scene, MeshFilter meshFilter)
    {
        // https://ekulabo.com/unity-mesh-material-combine

        CombineInstance[] combineInstanceAry = new CombineInstance[(int)scene.MeshCount];

        Debug.LogFormat("meshes: {0}", scene.MeshCount);

        int meshnumber = 0;

        foreach (Assimp.Mesh m in scene.Meshes)
        {
            List<Vector3D> verts = m.Vertices;
            List<Vector3D> norms = (m.HasNormals) ? m.Normals : null;
            List<Vector3D> uvs = m.HasTextureCoords(0) ? m.TextureCoordinateChannels[0] : null;

            List<Vector3> verts_u = new List<Vector3>();
            List<int> tris_u = new List<int>();
            List<Vector3> norms_u = new List<Vector3>();
            List<Vector2> uvs_u = new List<Vector2>();

            UnityEngine.Mesh mesh = new UnityEngine.Mesh();

            //Debug.LogFormat("vertslen: {0}", verts.Count);

            for (int i = 0; i < verts.Count; i++)
            {
                verts_u.Add(new Vector3(verts[i][0], verts[i][1], verts[i][2]));
            }

            for (int i = 0; i < norms.Count; i++)
            {
                norms_u.Add(new Vector3(norms[i][0], norms[i][1], norms[i][2]));
            }

            for (int i = 0; i < uvs.Count; i++)
            {
                uvs_u.Add(new Vector2(uvs[i][0], uvs[i][1]));
            }

            List<Face> faces = m.Faces;

            for (int i = 0; i < faces.Count; i++)
            {

                for (int j = 0; j < faces[i].IndexCount; j++)
                {
                    tris_u.Add(faces[i].Indices[j]);
                }
            }


            mesh.vertices = verts_u.ToArray();
            mesh.triangles = tris_u.ToArray();
            mesh.normals = norms_u.ToArray();
            mesh.uv = uvs_u.ToArray();
            mesh.triangles = tris_u.ToArray();



            combineInstanceAry[meshnumber].mesh = mesh;
            combineInstanceAry[meshnumber].transform = UnityEngine.Matrix4x4.Translate(new Vector3(0, 0, 0));
            meshnumber++;
        }

        Debug.LogFormat("{0}", meshnumber);
        var combinedMesh = new UnityEngine.Mesh();
        combinedMesh.name = "test";
        combinedMesh.CombineMeshes(combineInstanceAry);
        meshFilter.mesh = combinedMesh;

        Debug.LogFormat("{0}", combinedMesh.subMeshCount);
    }
}

AtsExでCabIlluminanceの挙動をさぐってみる

Mi5000氏の下記ツイートに触発されて遊んでみたのでメモ。

“AtsExでCabIlluminanceの挙動をさぐってみる” の続きを読む

ATSプラグインが依存するランタイムライブラリを調べる

BVE TrainsimのAdd Onを新しく導入するとき、ATSプラグインが依存しているランタイムライブラリがインストールされていことが原因と考えられるエラーが発生して、シナリオをプレーできないことがあります。このような場合に、該当するATSプラグインそのものからライブラリの依存関係をたどる方法がないか調べたので、以下にメモします。

  1. Dependencies(https://github.com/lucasg/Dependencies)を入手する
  2. DependenciesGUI.exeを起動して、調べたいATSプラグインを読み込む
  3. 依存関係のリストに表示されたライブラリ名称から、どのランタイムパッケージが必要か推測する
    • ライブラリ名とランタイムパッケージの関係は、下記参考サイト3, 4, 5などを参照する
    • 例: MSVCR110.dllが含まれるなら、「Visual Studio 2012 の Visual C++ 再頒布可能パッケージ」のインストールが必要

参考サイト

  1. 「Visual C++ アプリケーションの依存関係の理解」
  2. 「Visual C++ での配置」
  3. 「Visual C++ ランタイムDLL名に対応する 再頒布可能パッケージの対応表」
  4. 「Visual C++ ランタイム ライブラリ」
  5. 「【2023年対応】 Microsoft Visual C++ ランタイムライブラリ 再頒布可能パッケージのまとめ 2005~2022まで」

AtsExによる自線線形の表示

おーとま氏開発のAtsEXを利用する練習として、読み込んだシナリオの自線線形を表示するマッププラグインを作成しました。

このマッププラグインを組み込んだシナリオを実行すると、次図のように別ウィンドウが開かれ、上段に軌道平面図、下段に縦断面図が表示されます。自列車の現在位置を赤点で表示し、平面図には現在位置の距離程(KP)、曲率半径(R)を表示しています。(縦断面図への勾配(GR)の表示は未対応です)

プラグインの本体、ソースコード、サンプルシナリオは以下からダウンロードできます。このシナリオを動作させるにはAtsEX v1.0.31118.2 以降(入力デバイスプラグイン版)が必要ですので、インストールガイドを参照してあらかじめインストールをお願いします。

なお、zipファイルをダウンロードしたら、ファイルを右クリック→[プロパティ]を開いて、[許可する]にチェックを入れてから、zipファイルを展開してください。この手順を飛ばした場合、シナリオを実行できない場合があります。

ハマりポイント

  • 自線の軌道半径の取得
    • e.Scenario.Route.MyTrack.CurvesCurve クラスのリストが格納されていることは分かったものの、Curvatureにアクセスする方法がわからず
    • (Curve)myTrack.Curves.GoToAndGetCurrent(userVehicleLoc.Location)).CurvatureとしてCurveクラスにキャストすることでアクセスできたが、これで正しいのかよくわからないまま
    • GoToAndGetCurrentで対応する距離程のデータを抽出できることに気づくまで、Curvesリストをスキャンしてデータを抽出しようとしていた
  • 自線の勾配データ
    • いまだに取得方法がわからない

今後やってみたいこと

  • 勾配情報の表示
  • DirectXによる描画への対応
    • OpenBVEでの表示のような、メイン画面への重ね書きを想定

ナブコ技報・鉄道用ブレーキと関係ありそうな記事

ナブコ技報 No. 60 (1980)に掲載のNo. 1 (1962) – No. 59 (1980)総目次から、鉄道用ブレーキと関係がありそうな記事をピックアップした。表題だけで判断しているので、ピックアップ漏れや、関係ない記事が紛れている可能性があることに注意していただきたい。

一部の電車に採用されている自動空気ブレーキ制御弁である、M-60制御弁、No. 67制御弁に関係する情報を集めるのが主なモチベーション。三圧力式制御弁である、ということはいくつかの資料から確認できているが、メーカー名も含めそれ以上の情報に乏しい。

論文・開発レポート

  • No.2
    • 定容量空気溜から絞りを通って大気に排出される空気圧力の変化
  • No. 10
    • 圧力空気を絞りを通して大気に排出するときの圧力の変化 “GK11423に寄せて”
  • No. 13
    • 山陽新幹線は油圧ブレーキか
  • No. 18
    • 段制御空気ブレーキ装置(ナブコード式)の周波数特性
  • No. 19
    • 滑走検知器の解析
    • ナブコシューのできるまで
  • No. 20
    • 自動空気ブレーキ併用電磁直通空気ブレーキ装置の緩解不良防止策
  • No. 22
    • 山陽新幹線試験電車用 電磁-油圧ブレーキ装置
  • No. 23
    • 万博モノレール用HRDブレーキ装置の性能
  • No. 26
    • エアブレーキの技術ーその特徴と将来ー
  • No. 28
    • 接着管座について
  • No. 29
    • K-A制御弁自動試験機
  • No. 30
    • 札幌式案内軌条現車試験
  • No. 34
    • アナログ指令式空気ブレーキの開発
  • No. 37
    • 回生ブレーキ補足装置
  • No. 39
    • K制御弁自動試験機
  • No. 40
    • 国鉄貨車コキ50,000用空気ブレーキ装置 ゴム部品の耐寒性能向上対策について
  • No. 42
    • SELR空気ブレーキ装置のベンチテスト結果
  • No. 43
    • JNRの改良ATS装置について
    • HRDA-1ブレーキ装置
  • No. 45
    • 車両用滑走防止装置
    • 踏面ブレーキ用鉄系焼結合金制輪子の性能
  • No. 46
    • 車両用ブレーキ制御弁の変遷
    • HRDAブレーキ装置
    • 貨車用新型制御弁の開発
    • 鉄道車両空制検修用各種自動試験機
  • No. 47
    • HRAブレーキシステム
  • No. 49
    • 新交通システム車用空気ブレーキ装置
  • No. 51
    • C45, C46ブレーキ制御装置自動試験装置
  • No. 53
    • 福岡地下鉄向けHRDAブレーキ装置
    • 空制弁類汎用自動試験装置の施策
  • No. 55
    • 新型制御弁 E制御弁について
  • No. 59
    • 東大阪生駒電鉄VVVF電車用 HRDA-1ブレーキ装置

解説

  • No. 53
    • JNR200系統新幹線電車のブレーキシステムについて
  • No. 57
    • VVVF電車用ブレーキ装置の概説
  • No. 59
    • 南米向け郊外電車用ブレーキ装置
    • 鉄車輪支持式リニアモータ電車について

新製品紹介

  • No. 11
    • E-5ブレーキ弁
  • No. 12
    • 新型キハ用ブレーキ弁
    • 新型キハ用圧力差検出器
  • No. 29
    • A急ブレーキ弁
  • No. 33
    • KU-1型制御弁

トピックス

  • No. 2
    • DD20液圧式ディーゼル機関車用空気ブレーキ装置
  • No.4
    • 新幹線ブレーキ装置
  • No. 36
    • アルゼンチン向ME27Bブレーキ弁
  • No. 39
    • 台湾鉄路局新車用ブレーキ装置
  • No. 40
    • 国鉄新型ディーゼル動車のブレーキについて
  • No. 57
    • 台湾国鉄客車にE制御弁が採用

ここでも活躍するナブコの製品

  • No. 23
    • 万国博跨座式モノレールに採用されたHRD2ブレーキ装置
  • No. 30
    • 案内軌条式高速電車用HRD-1ブレーキ装置
  • No. 43
    • 自動運転装置によって制御されるHRDブレーキ装置
  • No. 46
    • SED電磁直通ブレーキ装置及びDP-45 DSドアエンジン
  • No. 53
    • ユーカリが丘線新交通 “VONA”のブレーキ装置
  • No. 57
    • 新開通した埼玉新交通システムのブレーキシステム
  • No. 59
    • レールバスのブレーキ装置

特許・実用新案紹介

  • No. 22
    • ブレーキ制御弁装置
  • No. 28
    • 車両用ブレーキ装置
  • No. 29
    • エアブレーキ用制御弁
  • No. 39
    • ブレーキ制御装置

補足情報

国立国会図書館には21号〜94号を所蔵している。ただし、22,23,26,30,31,33,37,45号は未収蔵。

タペットクリアランス測定など

mastodon, 旧twitterへの更新通知テストを兼ねてます。

2023-08-11

エストレヤ、ODO: 35538.6km

  • タペットクリアランス測定
    • オルタネータカバーを開いて圧縮上死点を探す
      • 一応スパークプラグも外して確認
    • 吸気 0.10-0.15mm(マニュアル指定値)
    • 排気0.15-0.20mmの範囲内(指定値は0.17-0.22mm)
      • 0.02mmシクネスゲージがないのでこの範囲で測定
    • とりあえず現状維持
  • タペットカバーOリング交換
    • 吸気側オイル滲みあった
    • 吸気、排気とも弾力失われている
  • ドライブチェーン遊び
    • 35mm
    • 交換時と変化なし
  • ドライブスプロケットオイルシール
    • 漏れなさそう
  • エンジンオイル補充
    • 0.5L?
    • Verity 4T BIKE 10W-40 MA
    • レベルゲージ1/2ぐらい
  • スパークプラグ
    • 前回交換より5000km走行
    • だいぶ角が丸まっているのでそろそろ交換か?
    • 8/14 交換 DR9EA -> DR9EA

フロントスプロケットオイルシール交換

2023-08-05

エストレヤ、ODO: 35466.5 km

フロントタイヤ、ドライブチェーン交換時に指摘されたので実行。以前からエンジンオイルの減りが早く、チェーン周りのオイル汚れが目立ってはいた。

分解すると、オイルシール下端にオイル溜まりがあり、アウトプットシャフトカラーが無抵抗で抜ける状態。カラーのOリング劣化が漏れの主因か? オイルシールの劣化は素人目にはわからず。

カラーOリング(92055 – 920551293)、オイルシール(92049 – 920491159)を交換。オイルシールの圧入はフロントスプロケットを裏返しにして実行。オイルシール面にはリチウムグリス塗布。

ニュートラルスイッチの交換、タペット調整もするつもりだったが酷暑により断念。

二輪整備記録

mastodonへの投稿通知テストを兼ねてます。

2023-07-29

エストレヤ BJ250A-B6 (1998)

ODO: 35461.1km

ドライブチェーン、フロントタイヤ交換

チェーン: DID520VX3

フロントタイヤ: IRC GS-19

エンジンオイルの漏れ大、チェーンにかかっておりシール劣化の危険あり。ドライブスプロケットのオイルシール劣化?

Tsutsuji Trackcomputer v1.7.1

Tsutsuji Trackcomputer version 1.7.1をリリースしました。(version 1.7.0はバグが見つかったためリリースを中止しました)

https://github.com/konawasabi/tsutsuji-trackcomputer/

インストール・アップデート方法

tsutsuji trackcomputerを新しくインストールする方法は、https://konawasabi.riceball.jp/2022/06/01/tsutsuji-kobushi-installguide/ を参照してください。

以前のバージョンのtsutsuji-trackcomputer をお持ちの方は、pip install -U tsutsuji-trackcomputer コマンドにてアップデートが可能です。

なお、今回のアップデートに合わせてkobushi-trackviewer version 1.1.5をリリースしました。tsutsuji-trackcomputer version 1.7.1を正しく動作させるにはこちらのアップデートも必要です。なお、上記のコマンドを実行すれば、kobushi-trackviewerも自動でアップデートされます。

本バージョンでの変更点

本バージョンでは、Track構文で記述した他軌道データの読み込み、およびgenerate機能での変換に対応しました。

次のサンプルデータ(v1-7-1_sample.zip)に含まれるv1-7-1_sample.cfgをtsutsujiで読み込むと、図1に示すような軌道データが表示されます。このデータでは、自軌道(Curve, Gradient構文で記述)としてup, downの2線を、他軌道(track構文で記述)としてthird、fourth の2線を定義しています。なお、third軌道はup軌道を、fourth軌道はdown軌道をそれぞれ基準としています。

図1、サンプルデータ読み込み例

読み込んだ他軌道データは、自軌道より少し細いラインでプロットされます。自軌道データと同様に、Measure機能での計測、ラインカラーの変更、generate機能での座標変換が可能です。

なお、generateを実行した場合、他軌道データのtrackkeyは次の要領で変換されます。

他軌道キー: fourth、基準となる自軌道キー: downの場合、@OT_down@_fourth