사례 연구 - HoloLens 공간 매핑 기능 확장

Microsoft HoloLens 첫 번째 앱을 만들 때는 디바이스에서 공간 매핑의 경계를 얼마나 멀리까지 푸시할 수 있는지 확인하고자 했습니다. Microsoft Studios의 소프트웨어 엔지니어인 Jeff Evertt는 홀로그램이 사용자의 실제 환경에 배치되는 방식을 보다 세밀하게 제어할 필요 없이 새로운 기술이 어떻게 개발되었는지 설명합니다.

참고

HoloLens 2 환경 인식 애플리케이션을 직관적으로 개발할 수 있도록 설계된 구조화되어 높은 수준의 환경 표현을 Mixed Reality 개발자에게 제공하는 새로운 Scene Understanding 런타임을 구현합니다.

비디오 보기

공간 매핑 외

HoloLens 첫 번째 게임 중 두 게임인 Fragments and Young Conker를작업하는 동안 실제 세계에서 홀로그램을 절차적으로 배치할 때 사용자 환경에 대한 더 높은 수준의 이해가 필요했습니다. 각 게임에는 고유한 특정 배치 요구 사항이 있습니다. 예를 들어 조각에서 바닥이나 테이블과 같은 다양한 표면을 구분하여 관련 위치에 단서를 배치하려고 했습니다. 또한 수명 크기의 홀로그램 문자가 놓일 수 있는 표면(예: 체면)을 식별할 수 있기를 원했습니다. Young Conker에서는 Conker와 동료가 플레이어의 실내에서 올려진 표면을 플랫폼으로 사용할 수 있기를 원했습니다.

이러한 게임을 위한 개발 파트너인 Asobo Studios는이 문제에 직면한 후 HoloLens 공간 매핑 기능을 확장하는 기술을 만들었습니다. 이를 사용하여 플레이어의 공간을 분석하고 벽, 테이블, 자식 및 바닥과 같은 표면을 식별할 수 있습니다. 또한 홀로그램 개체에 가장 적합한 배치를 결정하기 위해 제약 조건 집합에 대해 최적화할 수 있는 기능을 제공했습니다.

공간 이해 코드

Asobo의 원래 코드를 가져와서 이 기술을 캡슐화하는 라이브러리를 만들었습니다. Microsoft 및 Asobo는 이제 이 코드를 오픈 소스로 제공하고 MixedRealityToolkit에서 사용할 수 있도록 했습니다. 모든 소스 코드가 포함되어 있어 요구 사항에 맞게 사용자 지정하고 개선 사항을 커뮤니티와 공유할 수 있습니다. C++ 해결기용 코드는 UWP DLL로 래핑되고 MixedRealityToolkit 내에 포함된 드롭인 프리팹을 사용하여 Unity에 노출되었습니다.

Unity 샘플에는 벽에서 빈 공간을 찾고, 바닥의 큰 공간이나 최대값에 개체를 배치하고, 문자가 배치될 위치를 식별하고, 수많은 기타 공간 이해 쿼리를 식별할 수 있는 유용한 쿼리가 많이 포함되어 있습니다.

HoloLens 제공하는 공간 매핑 솔루션은 전체 문제 공간 영역의 요구 사항을 충족할 만큼 충분히 일반적이도록 설계되었지만 공간 이해 모듈은 두 가지 특정 게임의 요구를 지원하도록 빌드되었습니다. 따라서 해당 솔루션은 특정 프로세스 및 가정 집합을 중심으로 구성됩니다.

  • 고정 크기 플레이스페이스:사용자가 init 호출에서 최대 재생 영역 크기를 지정합니다.
  • 일회성 검색 프로세스:프로세스에는 사용자가 작업하는 개별 검색 단계가 필요하며, 플레이스페이스를 정의합니다. 쿼리 함수는 검색이 종료될 때까지 작동하지 않습니다.
  • 사용자 기반 플레이스페이스 "그리기": 검색 단계 중에 사용자는 재생 영역을 이동하고 둘러보며 포함해야 하는 영역을 효과적으로 그렸습니다. 생성된 메시는 이 단계에서 사용자 피드백을 제공하는 데 중요합니다.
  • 실내 홈 또는 사무실 설정:쿼리 함수는 직각으로 평면 표면과 벽 주위에 설계되었습니다. 소프트 제한 사항입니다. 그러나 검색 단계 중에 주 축과 보조 축을 따라 메시 공간을 최적화하기 위해 기본 축 분석이 완료됩니다.

실내 검색 프로세스

공간 이해 모듈을 로드할 때 가장 먼저 해야 할 일은 공간을 스캔하는 것이므로 바닥, 최면, 벽 등의 사용 가능한 모든 표면이 식별되고 레이블이 지정됩니다. 검색 프로세스 중에는 방 주변을 둘러보고 검사에 포함해야 하는 영역을 "칠"합니다.

이 단계에서 볼 수 있는 메시는 사용자에게 검색 중인 방 부분을 알 수 있는 중요한 시각적 피드백 부분입니다. 공간 이해 모듈의 DLL은 내부적으로 플레이스페이스를 8cm 크기의 복셀 큐브 그리드로 저장합니다. 검사의 초기 부분에서는 기본 구성 요소 분석을 완료하여 방의 축을 확인합니다. 내부적으로 이러한 축에 맞춰진 복셀 공간을 저장합니다. 메시는 복셀 볼륨에서 isosurface를 추출하여 약 1초마다 생성됩니다.

흰색의 공간 매핑 메시 및 녹색으로 된 재생 영역 메시 이해

흰색의 공간 매핑 메시 및 녹색으로 된 재생 영역 메시 이해

포함된 SpatialUnderstanding.cs 파일은 검사 단계 프로세스를 관리합니다. 다음 함수를 호출합니다.

  • SpatialUnderstanding_Init:시작할 때 한 번 호출합니다.
  • GeneratePlayspace_InitScan:검사 단계를 시작해야 함을 나타냅니다.
  • GeneratePlayspace_UpdateScan_DynamicScan:각 프레임을 호출하여 검사 프로세스를 업데이트합니다. 카메라 위치와 방향이 전달되며 위에서 설명한 플레이스페이스 그리기 프로세스에 사용됩니다.
  • GeneratePlayspace_RequestFinish:재생 영역을 종료하기 위해 호출됩니다. 이렇게 하면 검색 단계 중에 영역 "그리기"를 사용하여 재생 영역을 정의하고 잠급 수 있습니다. 애플리케이션은 검색 단계 중에 통계를 쿼리할 수 있으며 사용자 피드백을 제공하기 위해 사용자 지정 메시를 쿼리할 수 있습니다.
  • Import_UnderstandingMesh:검사하는 동안 모듈에서 제공하고 이해 프리팹에 배치된 SpatialUnderstandingCustomMesh 동작은 프로세스에서 생성된 사용자 지정 메시를 주기적으로 쿼리합니다. 또한 이 작업은 검사가 완료된 후 한 번 더 수행됩니다.

SpatialUnderstanding 동작에 의해 구동되는 검색 흐름은 InitScan을호출한 다음, UpdateScan 각 프레임을 검사합니다. 통계 쿼리가 적절한 검사를 보고하면 사용자는 RequestFinish를 호출하여 검사 단계의 끝을 나타낼 수 있습니다. UpdateScan은 DLL이 처리를 완료했음을 나타내는 반환 값이 될 때까지 계속 호출됩니다.

쿼리

검색이 완료되면 인터페이스에서 세 가지 유형의 쿼리에 액세스할 수 있습니다.

  • 토폴로지 쿼리:스캔한 공간의 토폴로지 기반의 빠른 쿼리입니다.
  • 셰이프 쿼리:토폴로지 쿼리의 결과를 활용하여 정의한 사용자 지정 셰이프와 일치하는 가로 표면을 찾습니다.
  • 개체 배치 쿼리:개체에 대한 규칙 및 제약 조건 집합을 기반으로 가장 적합한 위치를 찾는 더 복잡한 쿼리입니다.

세 가지 기본 쿼리 외에도 태그가 지정된 표면 형식을 검색하는 데 사용할 수 있는 광선 캐스팅 인터페이스가 있으며 사용자 지정 watertight room mesh를 복사할 수 있습니다.

토폴로지 쿼리

DLL 내에서 토폴로지 관리자는 환경의 레이블 지정을 처리합니다. 위에서 설명한 것처럼 대부분의 데이터는 복셀 볼륨 내에 포함된 파셸 내에 저장됩니다. 또한 PlaySpaceInfos 구조체는 세계 맞춤(아래의 자세한 내용), 바닥 및 최대 높이를 포함하여 플레이스페이스에 대한 정보를 저장하는 데 사용됩니다.

추론은 바닥, 최면 및 벽 결정에 사용됩니다. 예를 들어 1m2보다 큰 가장 크고 가장 낮은 가로 표면은 바닥으로 간주됩니다. 검사 프로세스 중에 카메라 경로도 이 프로세스에 사용됩니다.

토폴로지 관리자가 노출하는 쿼리의 하위 집합은 DLL을 통해 노출됩니다. 노출된 토폴로지 쿼리는 다음과 같습니다.

  • QueryTopology_FindPositionsOnWalls
  • QueryTopology_FindLargePositionsOnWalls
  • QueryTopology_FindLargestWall
  • QueryTopology_FindPositionsOnFloor
  • QueryTopology_FindLargestPositionsOnFloor
  • QueryTopology_FindPositionsSittable

각 쿼리에는 쿼리 유형에 한정된 매개 변수 집합이 있습니다. 다음 예제에서 사용자는 원하는 볼륨의 최소 높이 & 너비, 바닥 위의 최소 배치 높이 및 볼륨 앞의 최소 여유 공간을 지정합니다. 모든 측정값은 미터 단위입니다.

EXTERN_C __declspec(dllexport) int QueryTopology_FindPositionsOnWalls(
          _In_ float minHeightOfWallSpace,
          _In_ float minWidthOfWallSpace,
          _In_ float minHeightAboveFloor,
          _In_ float minFacingClearance,
          _In_ int locationCount,
          _Inout_ Dll_Interface::TopologyResult* locationData)

이러한 각 쿼리는 TopologyResult 구조체의 미리 할당된 배열을 취합니다. locationCount 매개 변수는 전달된 배열의 길이를 지정합니다. 반환 값은 반환된 위치의 수를 보고합니다. 이 숫자는 전달된 locationCount 매개 변수보다 크지 않습니다.

TopologyResult에는 반환된 볼륨의 중심 위치, 방향(예: 보통) 및 찾은 공간의 크기가 포함됩니다.

struct TopologyResult
     {
          DirectX::XMFLOAT3 position;
          DirectX::XMFLOAT3 normal;
          float width;
          float length;
     };

Unity 샘플에서 이러한 각 쿼리는 가상 UI 패널의 단추에 연결됩니다. 샘플에서는 이러한 각 쿼리에 대한 매개 변수를 적절한 값으로 하드 코딩합니다. 자세한 예제는 샘플 코드의 SpaceVisualizer.cs를 참조하세요.

셰이프 쿼리

DLL 내에서 도형 분석기(ShapeAnalyzer_W)는 토폴로지 분석기를 사용하여 사용자가 정의한 사용자 지정 셰이프와 일치합니다. Unity 샘플에는 쿼리 메뉴의 셰이프 탭에 미리 정의된 도형 집합이 있습니다.

셰이프 분석은 가로 표면에서만 작동합니다. 예를 들어, 평상시 표면과 평면 상단의 후면에 의해 정의되는 경우를 예로 들어 보겠습니다. 셰이프 쿼리는 두 표면이 정렬되고 연결된 특정 크기, 높이 및 가로 세로 범위의 두 표면을 찾습니다. API 용어를 사용하는 경우, couch 시트와 이면의 위쪽은 셰이프 구성 요소이며 맞춤 요구 사항은 셰이프 구성 요소 제약 조건입니다.

Unity 샘플(ShapeDefinition.cs)에서 "sittable" 개체에 대해 정의된 예제 쿼리는 다음과 같습니다.

shapeComponents = new List<ShapeComponent>()
     {
          new ShapeComponent(
               new List<ShapeComponentConstraint>()
               {
                    ShapeComponentConstraint.Create_SurfaceHeight_Between(0.2f, 0.6f),
                    ShapeComponentConstraint.Create_SurfaceCount_Min(1),
                    ShapeComponentConstraint.Create_SurfaceArea_Min(0.035f),
               }),
     };
     AddShape("Sittable", shapeComponents);

각 셰이프 쿼리는 구성 요소 간의 의존도를 나열하는 일련의 구성 요소 제약 조건 및 셰이프 제약 조건 집합이 있는 셰이프 구성 요소 집합에 의해 정의됩니다. 이 예제에서는 단일 구성 요소 정의에 세 개의 제약 조건을 포함하고 구성 요소 간에 셰이프 제약 조건이 없습니다(구성 요소가 하나만 있기 때문에).

반면, couch 셰이프에는 두 개의 셰이프 구성 요소와 4개의 셰이프 제약 조건이 있습니다. 구성 요소는 사용자의 구성 요소 목록에서 인덱스로 식별 됩니다 (이 예제에서는 0 및 1).

shapeConstraints = new List<ShapeConstraint>()
        {
              ShapeConstraint.Create_RectanglesSameLength(0, 1, 0.6f),
              ShapeConstraint.Create_RectanglesParallel(0, 1),
              ShapeConstraint.Create_RectanglesAligned(0, 1, 0.3f),
              ShapeConstraint.Create_AtBackOf(1, 0),
        };

래퍼 함수는 사용자 지정 셰이프 정의를 쉽게 만들기 위해 Unity 모듈에서 제공 됩니다. 구성 요소 및 모양 제약 조건의 전체 목록은 ShapeComponentConstraintShapeConstraint 구조 내의 SpatialUnderstandingDll 에서 찾을 수 있습니다.

파란색 사각형은가 중 셰이프 쿼리의 결과를 강조 표시 합니다.

파란색 사각형은가 중 셰이프 쿼리의 결과를 강조 표시 합니다.

개체 배치 해 찾기

개체 배치 쿼리를 사용 하 여 실제 방에 있는 이상적인 위치를 식별 하 여 개체를 배치할 수 있습니다. 개체 규칙 및 제약 조건이 지정 된 경우 해 찾기가 최적 위치를 찾습니다. 또한 Solver_RemoveObject 또는 Solver_RemoveAllObjects 호출을 통해 개체가 제거 될 때까지 개체 쿼리를 유지 하 여 제한 된 다중 개체 배치를 허용 합니다.

개체 배치 쿼리는 매개 변수가 있는 배치 유형, 규칙 목록 및 제약 조건 목록의 세 부분으로 구성 됩니다. 쿼리를 실행 하려면 다음 API를 사용 합니다.

public static int Solver_PlaceObject(
                [In] string objectName,
                [In] IntPtr placementDefinition,	// ObjectPlacementDefinition
                [In] int placementRuleCount,
                [In] IntPtr placementRules,     	// ObjectPlacementRule
                [In] int constraintCount,
                [In] IntPtr placementConstraints,	// ObjectPlacementConstraint
                [Out] IntPtr placementResult)

이 함수는 개체 이름, 배치 정의 및 규칙 및 제약 조건 목록을 사용 합니다. C # 래퍼는 규칙 및 제약 조건 생성을 용이 하 게 하는 생성 도우미 함수를 제공 합니다. 배치 정의에는 쿼리 유형 즉, 다음 중 하나를 포함 합니다.

public enum PlacementType
                {
                    Place_OnFloor,
                    Place_OnWall,
                    Place_OnCeiling,
                    Place_OnShape,
                    Place_OnEdge,
                    Place_OnFloorAndCeiling,
                    Place_RandomInAir,
                    Place_InMidAir,
                    Place_UnderFurnitureEdge,
                };

각 배치 형식에는 해당 형식에 고유한 매개 변수 집합이 있습니다. Objectplacementdefinition 구조에는 이러한 정의를 만들기 위한 정적 도우미 함수 집합이 포함 되어 있습니다. 예를 들어 개체를 바닥에 배치할 위치를 찾으려면 다음 함수를 사용할 수 있습니다.

public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims)

배치 유형 외에도 규칙 및 제약 조건 집합을 제공할 수 있습니다. 규칙을 위반할 수 없습니다. 그러면 형식 및 규칙을 충족 하는 가능한 배치 위치가 제약 조건 집합에 대해 최적화 되어 최적의 배치 위치를 선택할 수 있습니다. 제공 된 정적 생성 함수를 통해 각 규칙 및 제약 조건을 만들 수 있습니다. 아래에는 규칙 및 제약 조건 생성 함수 예제가 나와 있습니다.

public static ObjectPlacementRule Create_AwayFromPosition(
                    Vector3 position, float minDistance)
               public static ObjectPlacementConstraint Create_NearPoint(
                    Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)

아래의 개체 배치 쿼리는 이전에 배치 된 다른 개체와 대화방의 가운데 근처에서 절반 측정기 큐브를 표면의 가장자리에 배치 하는 위치를 찾고 있습니다.

List<ObjectPlacementRule> rules = 
          new List<ObjectPlacementRule>() {
               ObjectPlacementRule.Create_AwayFromOtherObjects(1.0f),
          };

     List<ObjectPlacementConstraint> constraints = 
          new List<ObjectPlacementConstraint> {
               ObjectPlacementConstraint.Create_NearCenter(),
          };

     Solver_PlaceObject(
          “MyCustomObject”,
          new ObjectPlacementDefinition.Create_OnEdge(
          new Vector3(0.25f, 0.25f, 0.25f), 
          new Vector3(0.25f, 0.25f, 0.25f)),
          rules.Count,
          UnderstandingDLL.PinObject(rules.ToArray()),
          constraints.Count,
          UnderstandingDLL.PinObject(constraints.ToArray()),
          UnderstandingDLL.GetStaticObjectPlacementResultPtr());

성공 하면 배치 위치, 차원 및 방향을 포함 하는 Objectplacementresult 구조가 반환 됩니다. 또한 배치가 배치 된 개체의 내부 목록에 추가 됩니다. 이후 배치 쿼리에서는이 개체를 고려 합니다. Unity 샘플의 Levelsolver 찾기 .cs 파일에는 더 많은 예제 쿼리가 포함 되어 있습니다.

파란색 상자는

파란색 상자는 "카메라 위치에서 멀리" 규칙을 사용 하 여 바닥 쿼리의 세 위치에서 발생 한 결과를 보여 줍니다.

팁:

  • 수준 또는 응용 프로그램 시나리오에 필요한 여러 개체의 배치 위치를 해결 하는 경우 먼저 필수적인 개체와 대량 개체를 해결 하 여 공간을 찾을 수 있는 확률을 최대화 합니다.
  • 배치 순서는 중요 합니다. 개체 배치를 찾을 수 없는 경우 제한 된 구성으로 시도 합니다. 여러 방 구성에서 기능을 지원 하려면 대체 (fallback) 구성 집합이 있어야 합니다.

광선 캐스팅

세 가지 기본 쿼리 외에도, 광선 캐스팅 인터페이스를 사용 하 여 태그가 지정 된 서피스 형식을 검색 하 고, 방을 검색 하 고 완료 한 후에 사용자 지정 watertight playspace 메시를 복사할 수 있습니다. 레이블은 바닥, 천장 및 벽 같은 표면에 대해 내부적으로 생성 됩니다. PlayspaceRaycast 함수는 광선이 알려진 표면과 충돌 하는 경우를 반환 하 고, 해당 하는 경우에는 RaycastResult형식으로 해당 화면에 대 한 정보를 반환 합니다.

struct RaycastResult
     {
          enum SurfaceTypes
          {
               Invalid,	// No intersection
               Other,
               Floor,
               FloorLike,         // Not part of the floor topology, 
                                  //     but close to the floor and looks like the floor
               Platform,          // Horizontal platform between the ground and 
                                  //     the ceiling
               Ceiling,
               WallExternal,
               WallLike,          // Not part of the external wall surface, 
                                  //     but vertical surface that looks like a 
                                  //	wall structure
               };
               SurfaceTypes SurfaceType;
               float SurfaceArea;	// Zero if unknown 
                                        //	(i.e. if not part of the topology analysis)
               DirectX::XMFLOAT3 IntersectPoint;
               DirectX::XMFLOAT3 IntersectNormal;
     };

내부적으로 raycast는 playspace의 계산 된 8cm 제곱 voxel 표현에 대해 계산 됩니다. 각 voxel에는 처리 된 토폴로지 데이터 (surfels 라고도 함)를 포함 하는 surface 요소 집합이 포함 되어 있습니다. 교차 된 voxel 셀에 포함 된 surfels는 토폴로지 정보를 조회 하는 데 사용 되는 가장 일치 하는 항목과 비교 됩니다. 이 토폴로지 데이터에는 교차 된 표면의 노출 영역 뿐만 아니라 SurfaceTypes 열거형 형식으로 반환 되는 레이블 지정이 포함 됩니다.

Unity 샘플에서 커서는 각 프레임을 비춥니다. 첫째, Unity의 colliders에 대해 둘째, 모듈의 세계 표현 이해 마지막으로 UI 요소를 기준으로 합니다. 이 응용 프로그램에서 UI는 우선 순위, 이해 결과 및 마지막으로 Unity의 colliders를 가져옵니다. SurfaceType 은 커서 옆에 텍스트로 보고 됩니다.

바닥과의 교차점을 보고 하는 raycast 결과

바닥과의 교차점을 보고 하는 raycast 결과

코드 가져오기

오픈 소스 코드는 MixedRealityToolkit에서 사용할 수 있습니다. 프로젝트에서 코드를 사용 하는 경우 HoloLens 개발자 포럼 에서 알려주세요. 작업을 확인할 때까지 기다릴 수 없습니다!

작성자 정보

Jeff Evertt, Microsoft의 소프트웨어 엔지니어링 리드 Jeff Evertt 는 인큐베이션부터 경험 개발까지 이전 며칠 이후 HoloLens 작업 한 소프트웨어 엔지니어링 리드입니다. HoloLens 하기 전에는 다양 한 플랫폼과 게임에서 Xbox Kinect와 게임 업계에서 작업 했습니다. Jeff는 경고음이 들리고 현란한 광원을 사용 하는 로봇, 그래픽 및 사물에 대 한 열정적인입니다. 그는 새로운 작업을 배우고 소프트웨어, 하드웨어, 특히 두 부분이 교차 하는 공간에서 작업 하는 것을 활용할.

참고 항목