File size: 6,527 Bytes
4c75661
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// drive.hpp ์˜ ์ถฉ๋Œยทํ›„์ง„ ํšŒ๊ท€ ์‹œํ—˜ โ€” tests/test_drive_cpp.py ๊ฐ€ ์ปดํŒŒ์ผํ•ด ๋Œ๋ฆฐ๋‹ค.
#include "drive.hpp"
#include <cmath>
#include <cstdio>
using namespace vkgs;
int main(int, char** argv) {
    ObstacleGrid og; og.load(argv[1]); Drivable road;
    int fails = 0;
    // 1) ์ถœ๋ฐœ ์ž์„ธ๊ฐ€ ๊ธฐ๋‘ฅ์— ๊ฑธ์นจ: ๊ทธ ์ž๋ฆฌ์—์„œ ์•ž์œผ๋กœ(๋น ์ ธ๋‚˜๊ฐ€๋Š” ๋ฐฉํ–ฅ) ๊ฐ€๋ฉด ๋ง‰ํžˆ์ง€ ์•Š๊ณ , ๋ฒฝ(x=10)์—์„œ๋Š” ๋ฉˆ์ถ˜๋‹ค
    Vehicle car; car.x = 0; car.y = 0.5f; car.yaw = 0;
    ContactInfo cur = vehicle_contact(car, og, road, false);
    std::printf("start contact %d\n", cur.total());
    // ์ „์ œ: ์ •๋ง๋กœ ๊ธฐ๋‘ฅ์— ๊ฑธ์นœ ์ฑ„ ์ถœ๋ฐœํ•ด์•ผ '๋น ์ ธ๋‚˜๊ฐ€๊ธฐ' ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์‹œํ—˜๋œ๋‹ค
    if (cur.total() <= 0) { std::puts("FAIL start pose does not overlap the pillar"); ++fails; }
    VehicleControl go; go.throttle = 1;
    float maxx = 0; int blocked = 0;
    for (int i = 0; i < 2000; ++i) {
        Vehicle prev = car; car.step(go, 0.01f);
        ContactInfo hit = vehicle_contact(car, og, road, false);
        if (hit.total() > cur.total()) { car = prev; car.v = 0; ++blocked; } else cur = hit;
        maxx = std::max(maxx, car.x + car.geom.front);
    }
    std::printf("front reached x=%.2f (wall at 10.0), blocked steps %d\n", maxx, blocked);
    // ํ—ˆ์šฉ์น˜: obst_tol 0.1 + ์ƒ˜ํ”Œ ๊ฐ„๊ฒฉ 0.1
    if (maxx > 10.25f || maxx < 9.8f) { std::puts("FAIL wall"); ++fails; }
    // 2) ํ›„์ง„: ์ •์ง€ ์ƒํƒœ์—์„œ ๋ธŒ๋ ˆ์ดํฌ 5์ดˆ โ†’ -3 m/s ๊ทผ์ฒ˜, ์ˆ˜ m ์ด๋™
    Vehicle r; VehicleControl back; back.brake = 1;
    for (int i = 0; i < 500; ++i) r.step(back, 0.01f);
    std::printf("reverse v=%.2f x=%.2f\n", r.v, r.x);
    if (r.v > -2.9f || r.x > -5.0f) { std::puts("FAIL reverse"); ++fails; }
    // 3) ํ›„์ง„ ์ค‘ ์œ„ ํ‚ค = ๋ธŒ๋ ˆ์ดํฌ โ†’ 0 ์—์„œ ๋ฉˆ์ท„๋‹ค๊ฐ€ ์ „์ง„
    VehicleControl fwd; fwd.throttle = 1; int k = 0;
    while (r.v < 0 && k < 300) { r.step(fwd, 0.01f); ++k; }
    std::printf("stopped after %.2f s, v=%.2f\n", k * 0.01f, r.v);
    if (k > 100) { std::puts("FAIL brake-from-reverse"); ++fails; }
    // 4) ๊ธฐ๋ณธ ์น˜์ˆ˜ = Zoe
    VehicleGeom g; std::printf("zoe geom rear %.2f front %.2f center %.2f\n", g.rear, g.front, g.center());
    // drive.hpp ์˜ ๊ธฐ๋ณธ๊ฐ’ (Renault Zoe: ์ถ•๊ฑฐ 2.588 m, ๋’ค ์˜ค๋ฒ„ํ–‰ 0.65, ๊ธธ์ด 4.08 โ†’ ์•ž 3.43, ํญ 1.74)
    if (std::fabs(g.wheelbase - 2.588f) > 1e-4f || std::fabs(g.rear + 0.65f) > 1e-4f ||
        std::fabs(g.front - 3.43f) > 1e-4f || std::fabs(g.half_width - 0.87f) > 1e-4f ||
        std::fabs(g.center() - 0.5f * (g.front + g.rear)) > 1e-5f) {
        std::puts("FAIL zoe geom");
        ++fails;
    }
    // 5) ๋‹ค๋ฅธ ์ฐจ๋Ÿ‰(์žฅ๋ฉด ๊ฐ์ฒด ๋ฐ”๋‹ฅ ์‚ฌ๊ฐํ˜•): ์•ž ์ฐจ์— ๋ง‰ํžˆ๊ณ , 90ยฐ ๋Œ์•„๊ฐ„ ์ฐจ๋Š” ํญ ์ชฝ์—์„œ ๋ง‰ํžˆ๊ณ , ์˜† ์ฐจ์„  ์ฐจ๋Š” ์ง€๋‚˜๊ฐ„๋‹ค
    auto drive_into = [&](const std::vector<Footprint>& others) {
        Vehicle c; ObstacleGrid none; Drivable nr;
        ContactInfo cc = vehicle_contact(c, none, nr, false, 0.15f, 0.1f, &others);
        float mx = 0;
        for (int i = 0; i < 1500; ++i) {
            Vehicle prev = c; c.step(go, 0.01f);
            ContactInfo h = vehicle_contact(c, none, nr, false, 0.15f, 0.1f, &others);
            if (h.total() > cc.total()) { c = prev; c.v = 0; if (h.kind != Contact::Vehicle) return -1.0f; } else cc = h;
            mx = std::max(mx, c.x + c.geom.front);
        }
        return mx;
    };
    float f1 = drive_into({Footprint{12, 0, 0, 2.0f, 1.0f}});           // ๋’ค๋ x = 10
    float f2 = drive_into({Footprint{12, 0, 1.5707963f, 2.0f, 1.0f}});  // ์˜†์œผ๋กœ ์„  ์ฐจ: ๊ฐ€๊นŒ์šด ๋ฉด x = 11
    float f3 = drive_into({Footprint{12, 3.0f, 0, 2.0f, 1.0f}});        // ์˜† ์ฐจ์„  (y = 3)
    std::printf("vehicle ahead stop %.2f (10), sideways %.2f (11), next lane %.2f (free)\n", f1, f2, f3);
    if (f1 > 10.25f || f1 < 9.8f) { std::puts("FAIL vehicle ahead"); ++fails; }
    if (f2 > 11.25f || f2 < 10.8f) { std::puts("FAIL vehicle sideways"); ++fails; }
    if (f3 < 30.0f) { std::puts("FAIL next lane blocked"); ++fails; }
    // 6) ๋น„์Šค๋“ฌํžˆ(17ยฐ) ๋ฒฝ์— ๋ฐ•์•„ ๋ง‰ํžŒ ๋’ค ํ›„์ง„์œผ๋กœ ๋น ์ ธ๋‚˜์˜จ๋‹ค โ€” ์  ์ˆ˜๋งŒ ๋น„๊ตํ•˜๋ฉด ํ›„์ง„ ์Šคํ…๋งˆ๋‹ค +1 ๋กœ ๋ง‰ํ˜€ ๊ฐ‡ํ˜”๋‹ค (2026-10-09)
    {
        Vehicle c; c.x = 3.0f; c.y = 4.0f; c.yaw = 0.3f;
        ContactInfo cc = vehicle_contact(c, og, road, false);
        auto step_blocked = [&](const VehicleControl& ctl) {
            Vehicle prev = c; c.step(ctl, 0.01f);
            ContactInfo h = vehicle_contact(c, og, road, false);
            float dir = c.v > 0 ? 1.0f : c.v < 0 ? -1.0f : 0.0f;
            if (h.depth(2) > cc.depth(2) && !escaping(c, dir, cc.depth(2), og, road, false, 0.15f, 0.1f, 2)) {
                c = prev; c.v = 0; return true;
            }
            cc = h; return false;
        };
        int blocked = 0;
        for (int i = 0; i < 600; ++i) blocked += step_blocked(go);
        float x_hit = c.x;
        VehicleControl back; back.brake = 1;
        for (int i = 0; i < 300; ++i) step_blocked(back);
        std::printf("angled wall: stopped x=%.2f (blocked %d, contact %d), after 3 s reverse x=%.2f\n", x_hit, blocked, cc.total(), c.x);
        if (blocked == 0 || x_hit + c.geom.front * std::cos(0.3f) > 10.4f) { std::puts("FAIL angled wall not blocking"); ++fails; }
        if (c.x > x_hit - 1.0f) { std::puts("FAIL stuck after angled hit (reverse)"); ++fails; }
    }
    // 7) ์™ธํ†จ์ด ํ•œ ์นธ์ด ์ฐจ์ฒด ์™ผ์ชฝ ๊ฐ€์žฅ์ž๋ฆฌ๋งŒ ์Šค์นœ๋‹ค (์ƒ˜ํ”Œ 2์  = graze): ๋ง‰ํžˆ์ง€ ์•Š๊ณ  ์ง€๋‚˜๊ฐ„๋‹ค. graze 0 ์ด๋ฉด ๋ง‰ํžŒ๋‹ค
    for (int gz : {2, 0}) {
        Vehicle c; c.x = -16.0f; c.y = 4.28f; c.yaw = 0;  // ์™ผ์ชฝ ๋ ์ƒ˜ํ”Œ y = 4.28 + 0.77 = 5.05 (์นธ 5.0~5.2), ๊ทธ ์•ˆ์ชฝ ์ค„ 4.95 ๋Š” ๋ฐ–
        ContactInfo cc = vehicle_contact(c, og, road, false);
        int blocked = 0;
        for (int i = 0; i < 400; ++i) {
            Vehicle prev = c; c.step(go, 0.01f);
            ContactInfo h = vehicle_contact(c, og, road, false);
            float dir = c.v > 0 ? 1.0f : -1.0f;
            if (h.depth(gz) > cc.depth(gz) && !escaping(c, dir, cc.depth(gz), og, road, false, 0.15f, 0.1f, gz)) {
                c = prev; c.v = 0; ++blocked;
            } else cc = h;
        }
        std::printf("graze %d: lone cell beside the car, x=%.2f blocked %d\n", gz, c.x, blocked);
        if (gz == 2 && (blocked || c.x < -5.0f)) { std::puts("FAIL grazing a lone cell blocks the car"); ++fails; }
        if (gz == 0 && !blocked) { std::puts("FAIL test setup: the lone cell does not touch the car"); ++fails; }
    }
    return fails;
}