Tutorial zur Konvertierung des Geräte-Arbeitsbereichs
Dieses Tutorial istGrundlegendes KraftfeedbackEs handelt sich um eine Weiterentwicklung des Tutorials, bei der die Eigenschaften und Methoden der Raumtransformationen verwendet werden, um Inverse3 Hier wird erläutert, wie Sie die Position, Drehung und Skalierung eines Objekts anpassen können.
Einleitung
Nachdem Sie die Grundsätzliche Kraft-Feedback-Szene eingerichtet haben, werden Sie möglicherweise feststellen, dass sich das Kraft-Feedback nicht wie erwartet ändert, wenn Sieden „Haptic Origin“ oder den „Haptic Controller“ verschieben, vergrößern, verkleinern oder drehen. Das Feedback bezieht sich weiterhin auf eine unsichtbare Kugel vor dem Gerät und wird von diesen Transformationen nicht beeinflusst.

Diese Diskrepanz entsteht, weil bei der Berechnung der Kräfte die tatsächlichen, nicht transformierten Koordinaten des Cursors des Geräts verwendet werden. Um dies zu beheben, werdendievon der Komponente„Inverse3 Controller“ bereitgestelltenthreadsicheren, zwischengespeicherten Transformationsmatrizengenutzt, damit die Transformation im Weltraum auf die Berechnung des haptischen Feedbacks angewendet werden kann.
Einrichtung der Szene
Beginnen Sie mit der Szene aus dem Tutorial zur grundlegenden Kraft-Feedback-Funktionund stellen Sie sicher, dass die Einstellung für die dominante Handdes „Inverse3 -Controllers“ mit Ihrem Gerät übereinstimmt. Drehen Sieden „Haptic Controller“ so, dass das Logo von „ Haply “ zur Kamera zeigt, und passen Sie gegebenenfalls die Skalierung von „Haptic Origin“ an, um den Bewegungsbereich des Cursors zu vergrößern oder dessen Position anzupassen.


Änderungen am Skript für die Kraft-Feedback-Funktion
Aus dem Tutorial zu den Grundlagen der Kraft-Feedback-Technik SphereForceFeedback.cs Kopieren Sie das Skript undOnDeviceStateChanged Bitte nehmen Sie im Callback die folgenden Änderungen vor.
device.CursorLocalPositionをdevice.CursorPositionersetzt.device.CursorLocalVelocityをdevice.CursorVelocityersetzt.device.CursorSetLocalForce(force)をdevice.CursorSetForce(force)ersetzt.
private void OnDeviceStateChanged(object sender, Inverse3EventArgs args)
{
var inverse3 = args.DeviceController;
var force = ForceCalculation(inverse3.CursorPosition, inverse3.CursorVelocity,
_cursorRadius, _ballPosition, _ballRadius);
inverse3.SetCursorForce(force);
}
Das Spielerlebnis
Inverse3 Wechseln Sie mit gedrücktem Mauszeiger in den Wiedergabemodus. Berühren Sie wie im vorherigen Beispiel die Kugel. Sie sollten nun ein präzises haptisches Feedback spüren, das die auf„Haptic Origin“ und „Haptic Controller“ angewendeten Transformationen widerspiegelt.

Quelldatei
Die vollständige Szene dieses Beispiels sowie die zugehörigen Dateien können aus den „Tutorials“-Beispielen im Unity-Paketmanager importiert werden.
Diese Beispielszene enthält zusätzliche Skripte, mit denen sich der Haptic Controller und der Haptic Origin zur Laufzeit anpassen lassen.
SphereForceFeedback.cs
/*
* Copyright 2024 Haply Robotics Inc. All rights reserved.
*/
using Haply.Inverse.DeviceControllers;
using Haply.Inverse.DeviceData;
using UnityEngine;
namespace Haply.Samples.Tutorials._3_DeviceSpaceTransform
{
public class SphereForceFeedback : MonoBehaviour
{
// must assign in inspector
public Inverse3Controller inverse3;
[Range(0, 800)]
// Stiffness of the force feedback.
public float stiffness = 300f;
[Range(0, 3)]
public float damping = 1f;
private Vector3 _ballPosition;
private float _ballRadius;
private float _cursorRadius;
/// <summary>
/// Stores the cursor and sphere transform data for access by the haptic thread.
/// </summary>
private void SaveSceneData()
{
var t = transform;
_ballPosition = t.position;
_ballRadius = t.lossyScale.x / 2f;
_cursorRadius = inverse3.Cursor.Radius;
}
/// <summary>
/// Saves the initial scene data cache.
/// </summary>
private void Awake()
{
inverse3 ??= FindFirstObjectByType<Inverse3Controller>();
inverse3.Ready.AddListener((device, args) => SaveSceneData());
}
/// <summary>
/// Subscribes to the DeviceStateChanged event.
/// </summary>
private void OnEnable()
{
inverse3.DeviceStateChanged += OnDeviceStateChanged;
}
/// <summary>
/// Unsubscribes from the DeviceStateChanged event.
/// </summary>
private void OnDisable()
{
inverse3.DeviceStateChanged -= OnDeviceStateChanged;
inverse3.Release();
}
/// <summary>
/// Calculates the force based on the cursor's position and another sphere position.
/// </summary>
/// <param name="cursorPosition">The position of the cursor.</param>
/// <param name="cursorVelocity">The velocity of the cursor.</param>
/// <param name="cursorRadius">The radius of the cursor.</param>
/// <param name="otherPosition">The position of the other sphere (e.g., ball).</param>
/// <param name="otherRadius">The radius of the other sphere.</param>
/// <returns>The calculated force vector.</returns>
private Vector3 ForceCalculation(Vector3 cursorPosition, Vector3 cursorVelocity, float cursorRadius,
Vector3 otherPosition, float otherRadius)
{
var force = Vector3.zero;
var distanceVector = cursorPosition - otherPosition;
var distance = distanceVector.magnitude;
var penetration = otherRadius + cursorRadius - distance;
if (penetration > 0)
{
// Normalize the distance vector to get the direction of the force
var normal = distanceVector.normalized;
// Calculate the force based on penetration
force = normal * penetration * stiffness;
// Apply damping based on the cursor velocity
force -= cursorVelocity * damping;
}
return force;
}
/// <summary>
/// Event handler that calculates and send the force to the device when the cursor's position changes.
/// </summary>
/// <param name="sender">The Inverse3 data object.</param>
/// <param name="args">The event arguments containing the device data.</param>
private void OnDeviceStateChanged(object sender, Inverse3EventArgs args)
{
var inverse3 = args.DeviceController;
// Calculate the ball force. Using 'device.Position' instead of 'device.LocalPosition'
// ensures the force calculation considers the device's offset and rotation in world space.
var force = ForceCalculation(inverse3.CursorPosition, inverse3.CursorVelocity,
_cursorRadius, _ballPosition, _ballRadius);
// Apply the calculated force to the cursor. Using 'device.CursorSetForce' instead of
// 'device.CursorSetLocalForce' ensures that the force vector is correctly converted
// from world space to the device's local space.
inverse3.SetCursorForce(force);
}
}
}