이전 프로젝트에서 ai 결제했으니 딸깍~ 모드 ㅋㅋ

[링크 : https://github.com/minimonk82/forza_horizon_4_telemetry]

 

이전에 시도해보지 못했던 지도 그리기와 각도 변환이 아주 수월하게 진행된다.

1차 개발

 

먼가 과거 갤로퍼 생각나서 

[링크 : https://cafe.daum.net/dongdou/1BWM/39430?svc=cafeapi]

 

그런 디자인으로 일단 변경

 

생각해보니 나중에 9축 센서로 충격량이랑 저장해서 보고 싶으니 그런 기능도 추가!

Posted by 구차니

먼가 이렇게 작성해주는데 솔찍히 설명해달라고 해도 먼 소리인지 모르겠다.

/* Convert a world-space direction to a frame aligned with vehicle heading.
 * Telemetry axes: X=right, Y=up, Z=forward; yaw rotates about world Y.
 */
static void world_to_heading_local(float yaw, float wx, float wy, float wz,
                                   float *lx, float *ly, float *lz)
{
    const float c = cosf(yaw);
    const float s = sinf(yaw);
    *lx = c * wx - s * wz;
    *ly = wy;
    *lz = s * wx + c * wz;
}

 

헷갈릴 만해요. 핵심은 벡터를 돌리는 것과 좌표축을 돌려서 같은 벡터를 표현하는 것이 반대 방향이라는 점이에요. 자동차 방향 기준으로 바꾸는 건 두 번째라서, yaw를 빼는 회전을 적용합니다. 회전행렬의 역변환은 전치행렬과 같다는 설명은 Illinois 대학 로보틱스 자료 (https://motion.cs.illinois.edu/RoboticSystems/CoordinateTransformations.html)에 있고, 회전축 변환 그림 (https://ethz.ch/content/dam/ethz/special-interest/mavt/robotics-n-intelligent-systems/multiscaleroboticlab-dam/documents/trm/HS2019/TRM19.pdf)도 도움이 됩니다.

저장소에서 사용한 축은 X=오른쪽, Y=위, Z=앞입니다. 차가 세계 좌표에서 yaw만큼 돌아 있다고 생각해볼게요.

세계 좌표:   X 오른쪽, Z 앞
자동차 좌표: x 오른쪽, z 앞

세계의 방향을 차 기준으로 보려면 자동차가 향한 만큼 좌표축을 반대로 돌려서 바라봅니다. 그 결과가 다음 식이에요.

x =  cos(yaw) × X - sin(yaw) × Z
z =  sin(yaw) × X + cos(yaw) × Z
y =  Y

예를 들어 차가 오른쪽으로 90° 돌아서 세계의 +X 방향을 향한다고 해보죠. 이때 세계의 +X 방향 벡터 (1, 0, 0)을 차 기준으로 바꾸면:

x = cos(90°)×1 - sin(90°)×0 = 0
z = sin(90°)×1 + cos(90°)×0 = 1

즉 (1, 0, 0)이 자동차 좌표에서는 (0, 0, 1)이 됩니다. 세계에서 오른쪽이던 방향이, 그 방향을 바라보는 자동차 입장에서는 앞쪽이라는 뜻이에요.

행렬은 이 두 계산을 한 번에 적은 표기입니다.

[ x ]   [ cos(yaw)  0  -sin(yaw) ] [ X ]
[ y ] = [    0      1      0     ] [ Y ]
[ z ]   [ sin(yaw)  0   cos(yaw) ] [ Z ]

참고로 앞서 추가한 화면 예시처럼 세계의 “앞” 벡터 (0, 0, 1) 자체를 yaw로 되돌리면, 자동차 기준 앞 (0, 0, 1)이 됩니다. 실제로 변환을 확인하려면 (1, 0, 0) 같은 세계 방향도 함께 넣어보면 차이를 더 쉽게 볼 수 있어요.

이 식은 방향 벡터를 변환합니다. yaw, pitch, roll 세 값을 통째로 벡터처럼 넣는 식은 아니에요. Euler 각은 3차원 회전의 표현이라 회전 순서를 알아야 서로 다른 좌표계 사이에서 정확히 변환할 수 있습니다.

 

 

예전에 주워들었던 쿼터니안 적용


typedef struct {
    float w, x, y, z;
} Quaternion;

static Quaternion quaternion_multiply(Quaternion a, Quaternion b)
{
    Quaternion q = {
        a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z,
        a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y,
        a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x,
        a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w
    };
    return q;
}

static Quaternion quaternion_axis_angle(float ax, float ay, float az, float angle)
{
    const float half = angle * 0.5f;
    const float s = sinf(half);
    Quaternion q = {cosf(half), ax*s, ay*s, az*s};
    return q;
}

/*
 * Convert a world vector to body coordinates using the full vehicle attitude.
 * Convention/assumption: vehicle-to-world attitude is
 * q = q_yaw(Y) * q_pitch(X) * q_roll(Z), applied roll, then pitch, then yaw.
 * With Hamilton quaternions, world->vehicle is q^-1 * v * q.
 */
static void world_to_vehicle_local_quaternion(float yaw, float pitch, float roll,
                                               float wx, float wy, float wz,
                                               float *lx, float *ly, float *lz)
{
    const Quaternion q_yaw = quaternion_axis_angle(0.0f, 1.0f, 0.0f, yaw);
    const Quaternion q_pitch = quaternion_axis_angle(1.0f, 0.0f, 0.0f, pitch);
    const Quaternion q_roll = quaternion_axis_angle(0.0f, 0.0f, 1.0f, roll);
    const Quaternion q = quaternion_multiply(
        quaternion_multiply(q_yaw, q_pitch), q_roll);
    const Quaternion q_inverse = {q.w, -q.x, -q.y, -q.z};
    const Quaternion v_world = {0.0f, wx, wy, wz};
    const Quaternion v_local = quaternion_multiply(
        quaternion_multiply(q_inverse, v_world), q);
    *lx = v_local.x;
    *ly = v_local.y;
    *lz = v_local.z;
}

 

아 증말.. 먼소리냐고 ㅠㅠ

쿼터니안은 3차원 회전을 숫자 4개 (w, x, y, z)로 표현합니다. 각 축 회전은 각도의 절반으로 만듭니다.

q = (cos(각도/2), 축x·sin(각도/2), 축y·sin(각도/2), 축z·sin(각도/2))

코드는 차량 자세를 q = q_yaw × q_pitch × q_roll로 구성한다고 가정합니다. 그리고 world 벡터 (X, Y, Z)를 스칼라부가 0인 쿼터니안 v = (0, X, Y, Z)로 놓고 다음처럼 변환합니다.

v_local = conjugate(q) × v_world × q

쉽게 말하면, 차량을 world에서 돌린 회전을 벡터에 역순으로 적용해 차량 좌표로 되돌리는 것입니다. 회전 순서는 결과에 영향을 줍니다. 쿼터니안으로 벡터를 회전하는 q × v × q⁻¹ 방식은 University of Maryland 강의 자료 (https://www.cs.umd.edu/class/fall2022/cmsc828X/LEC/quaternion.pdf), 좌표계 변환에 역회전을 적용하는 원리는 Illinois 대학 로보틱스 자료 (https://motion.cs.illinois.edu/RoboticSystems/CoordinateTransformations.html)에서 설명합니다.

HUD에는 world의 위쪽 (0, 1, 0)을 차량 기준으로 변환한 값도 표시하도록 했습니다. 차체가 수평이면 대략 (0, 1, 0)이고, 차가 기울면 X/Z 성분이 생깁니다.

주의할 점은 저장소가 yaw·pitch·roll의 정확한 회전 조합 순서와 부호 규칙을 정의하지 않는다는 것입니다. 그래서 yaw(Y) × pitch(X) × roll(Z)를 가정으로 명시했습니다. 컴파일은 성공했지만, 실제 게임에서 평지·pitch만 있는 자세·roll만 있는 자세를 비교해 부호와 순서를 확인해야 합니다.
Posted by 구차니

아래 소스를 참고하고

[링크  : https://github.com/geeooff/forza-data-web/blob/main/Console/ForzaDataConsole.cs]

 

원본 포맷도 참고해서

[링크 : https://support.forzamotorsport.net/hc/en-us/articles/21742934024211-Forza-Motorsport-Data-Out-Documentation]

 

몇가지 단위 수정함

영국놈들(!) 이라서 출력이 watt가 아니라 hp(horse power)로 되어있고

속도고 mph를 기본으로 던져주고

온도고 섭씨가 아니라 화씨.. 어우

[링크 : https://github.com/minimonk82/forza_horizon_4_telemetry]

 

아무튼.. 서보를 이용해서 서스펜션 길이를 가지고 장난질 치면 조금 수월하게 작업할수 있으려나?

라즈베리 파이 pico로 시리얼로 서스펜션 길이만 전송하고

pwm 4개 채널로 서보 제어해서 적당하게 맞춰봐야겠다.

Posted by 구차니

내부 ui에서 출력되는 것과 비교중

tirewear 등은 안 맞는것 같고

suspension도 딱 맞지 않는 느낌.

 

아래는 그냥 nc로 엔터쳐서 아무값도 안가 오류난 건데 아무튼..

타이어/서스펜션은 앞-좌/우 , 뒤-좌/우 라서 두 줄에 우겨넣어 출력함

 

[링크 : https://github.com/minimonk82/forza_horizon_4_telemetry]

Posted by 구차니

게임내에서 제공되는 텔레메트리 정보인데

프로토콜에서 제공되는 내용보다 더 다양한거 같다?

켜놓으면 재미있긴 한데 지도가 사라져서 아쉽..

 

없어 보이는 데이터로는

손상 /  타이어 온도 / 타이어 정보(압력)

 

여기부터는 udp telemetry에 있는 값들 같다.

Posted by 구차니

수직 동기화 켜면 30 / 60fps 가능하고

수직 동기화 끄고 프레임 속도 고정 해제(가변) 하면

120fps 정도 까지 올라가는데 그럴 때에는 8ms 주기로 온다.

어디서 주워듣기로는 물리엔진은 2배 빠르게 계산한다는데 그거랑 별개로

데이터 전송 주기는 프레임 속도에 맞추는 건가?

 

단순하게 roll/pitch를 이용해서 기울기를 표현하려고 했더니

서킷에서 기울기에 따라 roll이 올라가야 할 것 같은데.. 싶은 부분에서 pitch가 올라가고 그러는걸 보면

yaw/roll/pitch는 global 좌표에서의 값으로 생각된다.

'모종의 음모 > motion simulator' 카테고리의 다른 글

forza horizon 4 telemetry 검증중  (0) 2025.10.02
forza horizon 4 - telemetry ui  (0) 2025.09.28
github 에 작성중인 코드 푸시!  (0) 2024.12.28
yaw roll pitch  (0) 2024.12.27
HS-311 서보  (0) 2024.12.26
Posted by 구차니

어우. 올리기 빡세네

 

[링크 : https://github.com/minimonk82/forza_horizon_4_telemetry]

'모종의 음모 > motion simulator' 카테고리의 다른 글

forza horizon 4 - telemetry ui  (0) 2025.09.28
forza horizon 수직동기화와 telemetry 정보  (0) 2025.01.01
yaw roll pitch  (0) 2024.12.27
HS-311 서보  (0) 2024.12.26
f1 2015 telemetry udp  (0) 2024.12.08
Posted by 구차니

telemetry 정보에서 자동차임에도 불구하고

yaw roll pitch가 나와서 어떻게 매칭을 해야 하나 고민했는데

 

yaw는 이동방향, 나침반으로 어딜 보고 있냐를 표시하면 될 것 같고

이전 각도와의 차이로 차의 회전 방향을 알 수 있을테니 얜 미분을 해야하나?

 

roll은 측면으로 구르는 각도(그래서 roll cage 인가?)

좌우로 기운 도로를 달리게 되면 요 녀석의 값이 달라질 것 같고

 

pitch는 앞뒤로 오르막 내리막 길을 가게 되면 값이 달라질 것 같다.

 

정리하면.. 모션 시뮬레이터에서는 roll과 pitch로 운전석의 기울기를 표현하면 될 것 같고

yaw의 미분 값의 방향으로 시계, 반시계 방향의 운동량을 표현하면 될 것 같다.

 

가속도 값으로는 z 축은 의자 자체를 떨구거나 올리기 힘들테니 6축 아니면 힘들 것 같고

x 축은 앞뒤로 기울기고

y 축은 좌우로 기울이면 될테니

 

사용자가 느끼는 관성의 방향은

x 축 <-> yaw,

y 축 <-> pitch 와는 반대의 방향으로 나타나게 되겠네?

그러면.. 감각을 속이려면 yaw, roll 보단

x,y 가속도 값이 더 중요할 것 같다.

Vertical axis (yaw)
The yaw axis has its origin at the center of gravity and is directed towards the bottom of the aircraft, perpendicular to the wings and to the fuselage reference line. Motion about this axis is called yaw. A positive yawing motion moves the nose of the aircraft to the right.[1][2] The rudder is the primary control of yaw.[3]

The term yaw was originally applied in sailing, and referred to the motion of an unsteady ship rotating about its vertical axis. Its etymology is uncertain.[4]

Lateral axis (pitch)
The pitch axis (also called transverse or lateral axis),[5] passes through an aircraft from wingtip to wingtip. Rotation about this axis is called pitch. Pitch changes the vertical direction that the aircraft's nose is pointing (a positive pitching motion raises the nose of the aircraft and lowers the tail). The elevators are the primary control surfaces for pitch.[3]

Longitudinal axis (roll)
The roll axis (or longitudinal axis[5]) has its origin at the center of gravity and is directed forward, parallel to the fuselage reference line. Motion about this axis is called roll. An angular displacement about this axis is called bank.[3] A positive rolling motion lifts the left wing and lowers the right wing. The pilot rolls by increasing the lift on one wing and decreasing it on the other. This changes the bank angle.[6] The ailerons are the primary control of bank. The rudder also has a secondary effect on bank.[7]

[링크 : https://en.wikipedia.org/wiki/Aircraft_principal_axes]

[링크 : https://velog.io/@sobokii/UE5-Roll-Pitch-Yaw]

 

주익의 에일러론이 둘 다 움직이면 어떻게 될까 궁금했는데,

일단 구조적으로 양쪽이 반대로 움직이게 되어있어서 안된다고 하고

된다고 하더라도.. 무게중심에 가까워서 엘리베이션과는 다르게 움직일 것 같단 의견

플랩을 내리면 에일러론을 둘다 내린 형상이 되니

둘 다 내리면 수직방향으로 AoA이 커진 채로 올라가고

둘 다 올리면 수직방향으로 AoA가 커진채로 내려가려나?

[링크 : https://www.clien.net/service/board/park/15063368]

 

두서없이 쓰다 보니 먼 소리인지... 잠을 자야하나?!

'모종의 음모 > motion simulator' 카테고리의 다른 글

forza horizon 수직동기화와 telemetry 정보  (0) 2025.01.01
github 에 작성중인 코드 푸시!  (0) 2024.12.28
HS-311 서보  (0) 2024.12.26
f1 2015 telemetry udp  (0) 2024.12.08
dirt rally 2.0 telemetry udp  (0) 2024.12.08
Posted by 구차니

서보 데이터 시트를 보는데

4.8V ~ 6.0V 입력가능하고

6.0V 일 경우 최대 800mA 를 소모한다. 생각외로.. 많이 먹네? 4.8W 라.. (역률 인지 먼지 이런건 모르니 패스)

아무튼 모터 두개를 동시에 풀로 돌린다고 가정하면

1.6A는 흘려주어야 한다는 건데.. 일반적인 보조배터리라면 5V 2A는 되니까

라즈베리 등을 작동 시키는데에만도 빠듯하다는 의미가 될 듯..

아무튼 60도에 0.15~0.19초

0.0025초/1도 3msec 라니 물리적으로는 상당히 빠른 편이라고 해줘야 하나?

 

 

[링크 : https://www.devicemart.co.kr/goods/view?no=11225]

'모종의 음모 > motion simulator' 카테고리의 다른 글

github 에 작성중인 코드 푸시!  (0) 2024.12.28
yaw roll pitch  (0) 2024.12.27
f1 2015 telemetry udp  (0) 2024.12.08
dirt rally 2.0 telemetry udp  (0) 2024.12.08
forza horizon 4 telemetry 수정  (0) 2024.12.07
Posted by 구차니

다시 프로그램 수정해서 받아보니 패킷의 길이가 시원하게 보여서 좋긴하네

nc는 패킷의 시작을 알 수 없어서 매번 아쉽다.

 

/YF로 나오는 녀석은 패킷의 거의 마지막 부분이었군

280 received, 343 sizeof(FORZA_DASH)

83 0A B0 42 28 0F 0C 42 BA 7F 8B 44 BA 7F 8B 44 
AB 05 3D C4 8C 0F 8B 40 C8 54 DA C3 46 BE 2F 40 
1B E5 B8 BF B2 5E CD 3C 4C 74 15 40 5A 9B 58 3F 
13 BE C8 BC 41 4D 08 3F E3 4A 08 3F 4D 98 0B BC 
49 B1 58 BF BB F3 D4 3F C8 41 A4 3F EA 88 DA 3F 
88 4C B0 3F 35 F8 B4 C1 FE 29 31 C1 D3 61 96 C1 
FA 6F DF C0 8A DD 30 C0 AE D2 30 C0 7A E2 30 C0 
4D D1 30 C0 00 00 00 00 00 00 00 80 00 00 00 00 
00 00 00 00 00 00 00 00 15 49 87 BB C1 3D D5 3D 
00 00 00 00 06 01 3B 45 00 00 00 00 00 00 80 41 
00 50 C3 48 00 50 C3 48 00 00 00 00 00 00 80 3F 
00 00 80 3F 96 3D 13 41 00 00 C8 42 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 BB 50 42 44 
E9 01 42 44 49 C5 54 44 9F EA 54 44 00 00 90 41 
00 00 90 41 00 00 90 41 00 00 90 41 00 00 80 40 
00 00 C6 42 40 AA A5 45 00 00 00 00 FF 2F 59 46 
00 80 3B 45 00 00 10 41 00 00 80 3F 00 00 00 00 
00 00 00 00 00 00 00 40 

 

280 바이트의 시작과 끝 매칭

$ nc -ul 20777 | hexdump -C
00150bd0  0f 3d a4 42 11 35 3c 42  1f 26 f0 44 1f 26 f0 44  |.=.B.5
00150be0  6a 66 35 c3 d3 e9 5b 40  5c bb 65 c4 d5 14 e5 40  |jf5...[@\.e....@|
00150bf0  31 da a3 40 9d d7 b3 bd  3d 12 a0 c0 2c 1f 31 3f  |1..@....=...,.1?|
00150c00  30 a1 52 ba bf d5 38 3f  59 cb 38 3f ef b2 a5 bc  |0.R...8?Y.8?....|
00150c10  ae 16 31 bf ca b0 41 40  1e 4d 4d 40 14 bb 72 40  |..1...A@.MM@..r@|
00150c20  13 8e 6b 40 d6 ed 1b 42  86 5f 09 43 04 a5 45 42  |..k@...B._.C..EB|
00150c30  02 81 3c 43 22 f3 e3 40  12 9d e5 40 f1 40 e4 40  |..
00150c40  34 af e5 40 00 00 00 00  f0 70 68 3d 00 00 00 00  |4..@.....ph=....|
00150c50  00 00 00 00 00 00 00 40  02 a4 0f be 13 8f 8d be  |.......@........|
00150c60  00 00 00 00 87 86 6d 45  00 00 00 00 00 00 80 41  |......mE.......A|
00150c70  00 50 c3 48 00 50 c3 48  00 00 00 00 00 00 80 3f  |.P.H.P.H.......?|
00150c80  00 00 80 3f 77 16 0f 41  00 00 c8 42 00 00 00 00  |...?w..A...B....|
00150c90  00 00 80 3f 98 68 2d 42  00 00 00 00 a2 1e 76 44  |...?.h-B......vD|
00150ca0  fc 37 76 44 37 e5 84 44  24 b4 84 44 00 00 90 41  |.7vD7..D$..D...A|
00150cb0  00 00 90 41 00 00 90 41  00 00 90 41 00 00 80 40  |...A...A...A...@|
00150cc0  00 00 c6 42 40 aa a5 45  00 00 00 00 ff 2f 59 46  |...B@..E..... /YF |
00150cd0  00 80 3b 45 00 00 10 41  00 00 80 3f 00 00 00 00  |..;E...A...?....|
00150ce0  00 00 00 00 00 00 00 40  97 45 a4 42 1c 46 3c 42  |.......@.E.B.F

'모종의 음모 > motion simulator' 카테고리의 다른 글

yaw roll pitch  (0) 2024.12.27
HS-311 서보  (0) 2024.12.26
dirt rally 2.0 telemetry udp  (0) 2024.12.08
forza horizon 4 telemetry 수정  (0) 2024.12.07
forza telemetry  (0) 2024.12.02
Posted by 구차니