Làm thế nào để loại bỏ jitter khỏi đầu vào chuyển động?


9

Tôi đang viết một mod Minecraft hỗ trợ đầu vào từ Razer Hydra . Đó là một cặp bộ điều khiển chuyển động (một cho mỗi tay) cung cấp thông tin vị trí và xoay cực kỳ chính xác.

Với mục đích của câu hỏi này, việc xoay bộ điều khiển bên phải trên trục Y khiến nhân vật của người chơi nhìn sang trái hoặc phải (ngáp) và xoay trên trục X khiến người chơi nhìn lên và xuống (cao độ).

Đầu vào từ bộ điều khiển được ánh xạ trực tiếp đến tiêu đề của nhân vật. Nếu bộ điều khiển được xoay 30 độ trái, nhân vật sẽ quay 30 độ sang trái.

Vấn đề là đầu vào "jitter". Nếu tôi cố giữ bộ điều khiển một cách hoàn hảo, tiêu đề của nhân vật sẽ di chuyển thất thường trong một hình nón rất nhỏ (có thể là 1 độ).

Điều này có lẽ là do bàn tay run rẩy của tôi, vì dữ liệu của bộ điều khiển dường như chính xác.

Tôi đã thử lọc đầu vào bằng cách lấy trung bình dữ liệu từ các khung X cuối cùng, nhưng điều này làm cho đầu vào có vẻ như bơ.

Câu hỏi của tôi là: Làm thế nào tôi có thể lọc dữ liệu xoay để loại bỏ jitter mà không mất độ chính xác?


bạn đã xem xét bỏ qua những thay đổi rất nhỏ trong phong trào?
Phi

1
Razer Hyrdra này rất thú vị ... lần đầu tiên tôi nghe về nó, điều thú vị hơn nữa là viết một bản mod Minecraft để bổ sung cho nó ... Giả định của tôi là: Giống như một hình ảnh pixel, để "giảm nhiễu" bạn cần để làm mờ hình ảnh ... Về cơ bản, bạn có thể sống với hình ảnh pixel hoặc sống với hình ảnh mờ ... Tôi cảm thấy như đây là cùng một hiệu trưởng, bạn cần chọn cái nào bạn thích, trò chơi run rẩy hoặc kém chính xác hơn ... ... Đó chỉ là những gì tôi nghĩ ...
Luke San Antonio Bialecki 15/03/13

1
Bạn có thể làm tốt nhất của cả hai. Luôn lưu trữ 50 khung nói cuối cùng. Nhưng trung bình chỉ hơn một vài khung hình, tùy thuộc vào lượng chuyển động đầu vào. Đối với các chuyển động lớn, chỉ dựa vào nói 5 khung hình cuối cùng và đối với các chuyển động nhỏ (nếu không bị xáo trộn) thì dựa vào 30 khung hình cuối cùng.
danijar

@sharethis Đó là một ý tưởng thú vị. Tôi cuối cùng có thể thực hiện một cái gì đó như thế. Jitter không phải là vấn đề một khi đầu vào vượt qua một ngưỡng nhất định, vì vậy tôi chỉ có thể lấy trung bình các đầu vào nhỏ để loại bỏ jitter, và không trung bình bất cứ thứ gì cho đầu vào lớn.
Táo

Câu trả lời:


8

Vấn đề độ trễ phản hồi này là tình huống xảy ra với hầu như tất cả các bộ điều khiển chuyển động, cho dù là thứ gì đó như Hydra, Wii Remote, Kinect hay PlayStation Move.

Vấn đề là đây:

Khi một luồng đầu vào đang đến, bạn đang đưa ra quyết định trên cơ sở từng khung hình về việc có tin tưởng dữ liệu đầu vào hay không; liệu các xu hướng bạn đang thấy bây giờ có tiếp tục trong dữ liệu bạn nhận được hàng chục mili giây kể từ bây giờ không. Ví dụ: nếu có sự thay đổi đột ngột sang bên phải khung này, bạn không biết liệu đó có phải là một chút dữ liệu đầu vào thực sự hay không (và vì vậy bạn nên hành động theo nó) hoặc liệu nó chỉ là jitter (và vì vậy bạn nên bỏ qua nó). Cho dù bạn chọn gì, nếu sau đó bạn phát hiện ra rằng bạn đã sai, bạn đã cho phép jitter đầu vào biến nó thành trò chơi của bạn (trong trường hợp đầu tiên) hoặc giới thiệu độ trễ trong trò chơi của bạn (trong trường hợp sau).

Không có giải pháp tốt cho việc này. Một giải pháp "chính xác" để xác định xem đầu vào là thực hay jitter yêu cầu biết luồng đầu vào sẽ làm gì trong tương lai, cũng như những gì nó đã làm trong quá khứ. Chúng ta không thể làm điều đó trong các trò chơi, vì những lý do rõ ràng. Vì vậy, không có cách nào để lọc dữ liệu xoay để loại bỏ jitter mà không làm mất độ chính xác, trong bối cảnh trò chơi đang hoạt động với dữ liệu đầu vào trong thời gian thực.

Tôi đã thấy một nhà sản xuất lớn khuyên các nhà phát triển giải quyết vấn đề này bằng cách cho người chơi giữ nút trong khi xoay điều khiển, để trò chơi có thể tắt mã chống giật tại thời điểm đó, vì vậy nó không bị lag. (Tôi không khuyến nghị điều này, nhưng đó là một cách tiếp cận).

Tôi đã thấy một vài thư viện phần mềm trung gian đầu vào chuyển động giải quyết vấn đề này bằng cách đưa ra độ trễ nhân tạo trong đầu vào - có bộ đệm một phần tư giây mà dữ liệu đầu vào đi vào và trò chơi của bạn chỉ nghe về đầu vào một phần tư sau, để thư viện có thể giải quyết vấn đề jitter cho bạn, bằng cách biết những gì xảy ra cả trước và sau "hiện tại" theo quan điểm của trò chơi. Điều đó làm việc rất tốt, ngoài việc giới thiệu một phần tư độ trễ cho tất cả mọi thứ. Nhưng đó là một cách để giải quyết vấn đề và nó có thể thực hiện một công việc tuyệt vời là thể hiện chính xác một chuyển động với jitter được loại bỏ, với chi phí là độ trễ liên tục.

Nhưng không đi đến cực điểm đó, vẫn còn một số điều chúng ta có thể làm để đưa ra hành vi được cải thiện rất nhiều, mặc dù chúng ta biết rằng sẽ luôn có những "tình huống xấu nhất" hành xử theo kiểu không lý tưởng.

Cái nhìn sâu sắc cốt lõi là chúng tôi chỉ thực sự quan tâm đến jitter khi bộ điều khiển chủ yếu đứng yên và chúng tôi chỉ thực sự quan tâm đến độ trễ khi bộ điều khiển đang được di chuyển. Vì vậy, chiến lược của chúng tôi là cố gắng xử lý mọi thứ để chúng tôi có độ trễ khi bộ điều khiển đứng yên và có jitter khi bộ điều khiển chuyển động.

Đây là hai cách có thể để làm điều đó:

Một cách tiếp cận phổ biến là hệ thống "khóa / mở khóa", trong đó bạn theo dõi hướng của thiết bị và nếu nó không thay đổi trong một thời gian ngắn (nửa giây hoặc lâu hơn), bạn sẽ 'khóa' hướng đó, không mất hành động dựa trên hướng được báo cáo của thiết bị cho đến khi thiết bị khác đủ để 'mở khóa' lại. Điều này hoàn toàn có thể squitter jitter dựa trên định hướng, mà không đưa ra độ trễ khi định hướng đang tích cực thay đổi. Có thể có một gợi ý về độ trễ trước khi mã quyết định nó cần chuyển sang chế độ "mở khóa", nhưng sẽ tốt hơn rất nhiều so với độ trễ ở mọi nơi.

Một cách tiếp cận khác là lấy trung bình dữ liệu đầu vào từ các khung. Điểm quan trọng ở đây là chỉ lấy trung bình dữ liệu đầu vào từ các khung trong đó dữ liệu đầu vào giống nhau một cách mơ hồ - Điều này có nghĩa là các jitter nhỏ sẽ bị làm mờ và làm mềm, nhưng các thay đổi lớn hơn không bị mờ, vì dữ liệu của chúng không bị mờ đủ tương tự với dữ liệu từ các khung trước đó.

Có nhiều cách khác để có được một hiệu ứng tương tự là tốt. Cái nhìn sâu sắc cốt lõi là bạn không thể có cả jitter và non-lag trong trò chơi thời gian thực của mình cùng một lúc, bởi vì để làm được điều đó sẽ đòi hỏi kiến ​​thức về tương lai. Vì vậy, bạn cần chọn thời điểm thiên vị hành vi kiểm soát của mình đối với việc chấp nhận jitter và khi nào thiên vị nó theo hướng chấp nhận độ trễ, để làm cho trải nghiệm tổng thể trở nên không tệ nhất có thể.


Tôi chỉ đăng một câu trả lời, bạn có thể vui lòng cho ý kiến ​​của bạn về giải pháp của tôi?
Táo

2

Tôi phát triển phần mềm chuyển đổi đầu vào chuyển động thành đầu vào chuột nhạy và chính xác, cũng như duy trì một trang web cố gắng giúp các nhà phát triển tự thực hiện các giải pháp tốt như nhau. Tôi thường khuyên bạn nên chống lại ngưỡng di chuyển, mặc dù điều này phụ thuộc vào mức độ đáp ứng và độ chính xác của người chơi muốn, tôi rất vui vì điều đó phù hợp với bạn trong tình huống của bạn. Nhưng ở đây tôi sẽ đưa ra một giải pháp khác:

Tôi sử dụng một cái gì đó gọi là Soft Tiered Smoothing . Ý tưởng là chúng ta chuyển hướng đầu vào thông qua các thuật toán làm mịn khác nhau tùy thuộc vào cường độ hiện tại của vận tốc con quay (trong thực tế, một trong những thuật toán làm mịn đó chỉ là "không làm mịn"). Đó là phần "tầng". Phần "mềm" là chúng ta thực sự có thể phân chia đầu vào trơn tru giữa các thuật toán làm mịn khác nhau tùy thuộc vào cách so sánh với 2 ngưỡng.

Nó bảo vệ sự dịch chuyển một cách chính xác và không thêm bất kỳ độ trễ nào cho các chuyển động nhanh.

Trong thực tế, bạn có hai ngưỡng. Khi cường độ của tốc độ đầu vào nhỏ hơn ngưỡng dưới, chúng tôi đang sử dụng thuật toán làm mịn đơn giản (trung bình trên nhiều khung hình). Khi nó lớn hơn ngưỡng khác, chúng tôi không sử dụng thuật toán làm mịn nào cả. Nhưng trong trường hợp này, chúng ta vẫn chuyển các số không cho thuật toán làm mịn ngưỡng thấp hơn.

Khi vận tốc đầu vào nằm giữa hai ngưỡng, chúng ta chia đầu vào giữa hai thuật toán tương ứng.

Đây là một đoạn trích từ bài viết trên:

GetSoftTieredSmoothedInput(Vec2 input, float threshold1, float threshold2) {
    // this will be length(input) for vectors
    float inputMagnitude = Abs(input);

    float directWeight = (inputMagnitude - threshold1) / (threshold2 - threshold1);
    directWeight = clamp(directWeight, 0, 1);

    return GetDirectInput(input * directWeight) +
        GetSmoothedInput(input * (1.0 - directWeight));
}

GetDirectInput chỉ trả về những gì được cung cấp cho nó, nhưng nó cho thấy rằng một thuật toán làm mịn khác có thể được sử dụng ở đây. GetSmoothedInput có vận tốc và trả về tốc độ được làm mịn.

Với Soft Smoothed Smoothing, không có làm mịn được áp dụng cho các chuyển động rõ ràng có chủ ý (trên ngưỡng lớn hơn), có làm mịn được áp dụng để che đi một lượng nhỏ jitter, điều này cũng sẽ ảnh hưởng đến các chuyển động rất nhỏ, nhưng khi bạn đạt được ngưỡng của mình thì không đúng lắm đáng chú ý. Và có một sự chuyển tiếp rất suôn sẻ giữa hai người (không có điều đó, jitter thực sự có thể được khuếch đại).

Mặc dù các câu trả lời khác đều đúng khi nói rằng rất khó để nhận ra jitter ngay lập tức nhận được đầu vào, nhưng cũng đúng là jitter hầu như luôn luôn có vận tốc rất thấp và độ trễ đầu vào đi kèm làm trơn tru ít được chú ý hơn đối với các đầu vào tốc độ thấp .

Như bài viết đã đề cập, điều này được sử dụng ở một vài nơi trong công cụ nguồn mở JoyShockMapper của tôi , một trình ánh xạ đầu vào biến đầu vào con quay hồi chuyển thành đầu vào chuột. Ngay cả đối với những người sử dụng các công cụ ánh xạ khác như Steam hoặc reWASD, một số sử dụng JoyShockMapper cùng một lúc chỉ để điều khiển con quay hồi chuyển của nó.

Câu trả lời này giả định đầu vào được đưa ra với vận tốc góc (thường thấy với các bộ điều khiển có điều khiển chuyển động), không phải là định hướng tuyệt đối (nghe có vẻ như Razer Hydra đang mang lại cho bạn). Với định hướng tuyệt đối, tôi hy vọng bạn có thể sử dụng sự khác biệt giữa hướng hiện tại và hướng được báo cáo trước đó để có vận tốc, nhưng tôi không biết chắc chắn liệu nó có hoạt động tốt như với các bộ điều khiển tự báo cáo vận tốc góc không .

Một giải pháp làm mịn phổ biến khi bạn xử lý một vị trí / định hướng tuyệt đối thay vì vận tốc là nội suy theo hướng mục tiêu của bạn theo thời gian - điều này được mô tả rất chi tiết trong bài viết này của Gamasutra. Điều này cũng có thể hoạt động với Soft Smoothed Smoothing. Bạn sẽ tính toán cường độ vận tốc bằng cách sử dụng chênh lệch giữa đầu vào này và đầu vào được báo cáo trước đó. Bạn sẽ áp dụng sự khác biệt về hướng giữa khung này và khung cuối cùng nhân với giá trị "directeight" của bạn như được tính trong đoạn trích ở trên. Bước cuối cùng là thêm đầu vào được làm mịn, nhưng do cách làm mịn định hướng nội suy hoạt động, bạn chỉ cần áp dụng thay đổi hướng nội suy như bình thường - hoàn toàn không cần phải xem xét "directeight". Chỉ cần đặt hướng mục tiêu của bạn (đây là hướng bạn đang nội suy với việc làm mịn được mô tả trong bài viết Gamasutra đó) theo bất kỳ hướng nào bạn nhận được từ thiết bị và nội suy hướng của bạn theo hướng đó như được mô tả trong bài viết đó.


1

Cảm thấy kỳ lạ khi trả lời câu hỏi của riêng tôi, nhưng tôi nghĩ rằng tôi đã tìm thấy giải pháp của mình.

//Pseudo-Java

update()
{
    //deltaYaw is the change in yaw of the controller since last update
    //yawBuffer is initialized to zero, and only modified here
    //coneAngle is the stabilizing cone

    deltaYaw = getData().yaw;

    yawBuffer += deltaYaw;
    if (abs(yawBuffer) >= coneAngle)
    {
        player.yaw += (abs(yawBuffer)-coneAngle) * sign(yawBuffer);
        yawBuffer = coneAngle * sign(yawBuffer);
    }
}

Thay vì trực tiếp sửa đổi tiêu đề của người chơi, tôi chỉ cần "đẩy" một hình nón của một góc đã cho (trong trường hợp của tôi là 2,5 độ). Tôi đã tạo một bản demo HTML5 nhỏ của kỹ thuật này.

Khi bạn bắt đầu đẩy hình nón, độ trễ bằng không và độ chính xác đầy đủ. Tuy nhiên, nếu bạn đẩy hình nón sang trái, và sau đó muốn nhắm phải, bạn phải di chuyển qua toàn bộ góc của hình nón để thấy hiệu ứng.

Vì vậy, nó giải quyết các vấn đề chậm trễ tạm thời và làm mịn khủng khiếp, nhưng giới thiệu vấn đề mới của ngưỡng chuyển động. Tuy nhiên, nếu hình nón ổn định được điều chỉnh chính xác, ngưỡng không thể nhận thấy.


Đây có vẻ là một cách hợp lý để làm điều đó. Đã từng có máy quay (đắt tiền) ổn định hình ảnh của họ bằng cách sử dụng phương pháp này; nó mang lại cho bạn độ chính xác khi bạn tiếp tục chuyển động theo một hướng, nhưng có độ trễ khi bạn đổi hướng. Nếu điều đó làm việc tốt cho trò chơi của bạn, thì hoàn toàn đi cho nó. Bạn sẽ không tìm thấy một giải pháp duy nhất phù hợp nhất cho mọi trò chơi; nó luôn luôn là một sự đánh đổi trong đó bạn cần cân nhắc các mặt trái của từng cách tiếp cận với các nhu cầu cụ thể của trò chơi cụ thể mà bạn đang thực hiện. :)
Trevor Powell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.