ARKit: A Noobs Guide - Part II

Part II: Detecting Planes 🛫

The Basics

In the previous part, we went through the basics of ARKit, and some of its most basic classes that help with building AR experiences. In this part, we’ll look at more exciting stuff like detecting flat surfaces in your scene. Around you. Or anywhere really.

Let’s get right into it.

The Exciting Stuff: Plane Detection

Let’s quickly go over the basics of building an AR experience:

Create an ARWorldTrackingConfiguration object

Create an ARSession

Bind the ARSession to a ARSCNView

Run the ARSession with the configuration object

ARKit has the ability to detect planar surfaces, not necessarily horizontal plane surfaces, but it is what we are able to detect at this point. Support for vertical surfaces, I believe, will be added in the future. Oh, the glorious future.

Code

To enable plane detection, we simply set a property indicating the type of plane the session will detect, when the configuration object is created:

The planeDetection property on ARWorldTrackingConfiguration is an enum with one value ARPlaneDetectionHorizontal at the time of writing.

And by default, plane detection is turned off.

Now you expect to see horizontal surfaces around you in the session. But, you don’t. Let’s see why.

Show them planes

If plane detection is enabled on the configuration object, and the session is run, ARKit analyses feature points and detects horizontal planar surfaces in the scene, adds ARPlaneAnchor objects to the session.

Let’s look into what the logic actually is like.

An ARSession is able to track ARAnchor’s position and orientation in 3D space. When plane detection is enabled, ARPlaneAnchor (which is a subclass of ARAnchor) objects get added to the session whenever a flat surface is detected.

This information is available to the session, but this is not visible to the user unless we make it. The ARPlaneAnchor objects contain some useful properties like alignment, center, and extent which can be used to add a visual plane to the scene.

Every time an ARPlaneAnchor is added, the session notifies your ARSessionDelegate, ARSCNViewDelegate or ARSKViewDelegate. Let’s do this with SceneKit, since we’re familiar already with ARSCNView.

Most often, the View Controller that is handling your ARSCNView, would be your ARSCNViewDelegate, and you can implement methods on it that will be called by the session when it needs information.
As for our case, at any point during the session, whenever an ARAnchor is added to the session, the session adds an empty SCNNode at the anchor position and notifies the delegate with this method:

With that, you should have planes being detected and displayed in the scene around you.

I prefer to abstract the plane logic to its own class. You can take a look at my Plane implementation here.

That’s not all folks. We still have one thing left:

When planes are detected in the scene, ARKit constantly analyses the feature points for better results, and thereby the same plane that was detected could have a better result, by result I mean the boundaries and the position could be more accurate. To handle this and update the UI accordingly, we need a reference to the planes that we add to our session:

var planes = [ARPlaneAnchor: SCNNode]()

I use a dictionary to keep a reference of the planes when they’re added to the session, so I can refer back to the plane that needs updating using its anchor.

When boundaries for existing planes are updated as you get better input from the camera, the following delegate method is called:

And with that you should have an understanding of how planes are detected and updated in an ARSession.

Moving on

You should pretty much be able to write an AR app that detects flat surfaces around you. But what good is it if you can't put stuff in 3D you say? We'll see how to do exactly that in the next part. Feel free to leave any feedback you have.