Google is committed to advancing racial equity for Black communities. See how.

InstantPlacementPoint

public class InstantPlacementPoint

Trackable Instant Placement point returned by hitTestInstantPlacement(float, float, float).

If ARCore has an accurate 3D pose for the InstantPlacementPoint returned by hitTestInstantPlacement(float, float, float) it will start with tracking method FULL_TRACKING. Otherwise, it will start with tracking method SCREENSPACE_WITH_APPROXIMATE_DISTANCE, and will transition to FULL_TRACKING once ARCore has an accurate 3D pose. Once the tracking method is FULL_TRACKING it will not revert to SCREENSPACE_WITH_APPROXIMATE_DISTANCE.

When the tracking method changes from SCREENSPACE_WITH_APPROXIMATE_DISTANCE in one frame to FULL_TRACKING in the next frame, the pose will jump from its initial location based on the provided approximate distance to a new location at an accurate distance.

This instantaneous change in pose will change the apparent scale of any objects that are anchored to the InstantPlacementPoint. That is, an object will suddenly appear larger or smaller than it was in the previous frame.

To avoid the visual jump due to the sudden change in apparent object scale, use the following procedure:

 1. Keep track of the pose and tracking method of the InstantPlacementPoint in
    each frame.
 2. Wait for the tracking method to change to FULL_TRACKING.
 3. Use the pose from the previous frame and the pose in the current frame to determine the
    object's distance to the device in both frames.
 4. Calculate the apparent change in scale due to the change in distance from the camera.
 5. Adjust the scale of the object to counteract the perceived change in scale, so that visually
    the object does not appear to change in size.
 6. Optionally, smoothly adjust the scale of the object back to its original value over several
    frames.
 

The following snippet shows how to use Instant Placement to place one object. The wrapper below shows how to use steps 1 through 5 to avoid the visual jump.

class ArPlacementActivity {
   private Session session = null;
   private placementIsDone = false;
   public void createSession() {
     session = new Session(this);
     Config config = new Config(session);
     config.setInstantPlacementMode(InstantPlacementMode.LOCAL_Y_UP);
     session.configure(config);
   }
   public void onDrawFrame(GL10 gl) {
     Frame frame = session.update();
     // Place an object on tap.
     if (!placementIsDone && didUserTap()) {
       // Use estimated distance from the user's device to the real world, based
       // on how we expect the app to be used by users.
       float approximateDistanceMeters = 1.0f;
       List results =
          frame.hitTestInstantPlacement(tapX, tapY, approximateDistanceMeters);
       if (!results.isEmpty()) {
         InstantPlacementPoint point = (InstantPlacementPoint) hit.getTrackable();
         anchor = point.createAnchor(point.getPose());
         placementIsDone = true;
         disableInstantPlacement();
       }
     }
   }
   private void disableInstantPlacement() {
     // When the placement is done, you can disable Instant Placement to save computing.
     Config config = new Config(session);
     config.setInstantPlacementMode(InstantPlacementMode.DISABLED);
     session.configure(config);
   }
 }
 

This wrapper of InstantPlacementPoint can be used to offset the apparent scale shift that occurs when the tracking method changes from SCREENSPACE_WITH_APPROXIMATE_DISTANCE to FULL_TRACKING. For AR experiences where a sudden apparent scale change is acceptable, no wrapper is required.

class WrappedInstantPlacement {
   public InstantPlacementPoint point;
   public TrackingMethod previousTrackingMethod;
   public float previousDistanceToCamera;
   public float scaleFactor = 1.0f;
   public WrappedInstantPlacement(
       InstantPlacementPoint point,
       TrackingMethod previousTrackingMethod,
       float previousDistanceToCamera) {
     this.point = point;
     this.previousTrackingMethod = previousTrackingMethod;
     this.previousDistanceToCamera = previousDistanceToCamera;
   }
 }
 ArrayList wrappedPoints =
     new ArrayList();
 public void onDrawFrame(GL10 gl) {
   Frame frame = session.update();
   // Place an object on tap.
   if (didUserTap()) {
     // Use estimated distance from the user's device to the real world, based
     // on how we expect the app to be used by users.
     float approximateDistanceMeters = 2.0f;
     // Returns a single result if the hit test was successful.
     List results = frame.hitTestInstantPlacement(tapX, tapY,
         approximateDistanceMeters);
      for (HitResult hit : results) {
           InstantPlacementPoint point = (InstantPlacementPoint) hit.getTrackable();
           wrappedPoints.add(
               new WrappedInstantPlacement(point, point.getTrackingMethod(),
                                           distance(camera.getPose(), point.getPose())));
      }
   }
   for (WrappedInstantPlacement wrappedPoint : wrappedPoints) {
     InstantPlacementPoint point = wrappedPoint.point;
     if (point.getTrackingState() == TrackingState.STOPPED) {
       wrappedPoints.remove(wrappedPoint);
       continue;
     }
     if (point.getTrackingState() == TrackingState.PAUSED) {
       continue;
     }
     if (point.getTrackingMethod() == TrackingMethod.SCREENSPACE_WITH_APPROXIMATE_DISTANCE) {
        // Continue to use estimated depth and pose. Record distance to camera for use in
        // the next frame if the transition to full tracking happens.
        wrappedPoint.previousDistanceToCamera =
            distance(point.getPose(), camera.getPose());
     } else if (point.getTrackingMethod() == TrackingMethod.FULL_TRACKING) {
        if (wrappedPoint.previousPoseType ==
            TrackingMethod.SCREENSPACE_WITH_APPROXIMATE_DISTANCE) {
         // Transition from estimated pose to real pose. Adjust object scale to
         // counter-act apparent change is size due to pose jump.
         wrappedPoint.scaleFactor = distance(point.getPose(), camera.getPose()) /
             wrappedPoint.previousDistanceToCamera);
         // TODO: Apply the scale factor to the model.
         // ...
         previousPoseType = TrackingMethod.FULL_TRACKING;
       }
    }
 

Nested Classes

enum InstantPlacementPoint.TrackingMethod Tracking methods for InstantPlacementPoint

Public Methods

Anchor
createAnchor(Pose pose)
Creates an anchor at the given pose in the world coordinate space that is attached to this trackable.
boolean
equals(Object obj)
Indicates whether some other object is a Trackable referencing the same logical trackable as this one.
Collection<Anchor>
getAnchors()
Gets the Anchors attached to this trackable.
Pose
getPose()
Gets the pose of the Instant Placement point.
InstantPlacementPoint.TrackingMethod
TrackingState
getTrackingState()
Gets this trackable's TrackingState.
int
hashCode()
Returns a hash code value for the object.

Inherited Methods

Public Methods

public Anchor createAnchor (Pose pose)

Creates an anchor at the given pose in the world coordinate space that is attached to this trackable. The type of trackable will determine the semantics of attachment and how the anchor's pose will be updated to maintain this relationship. Note that the relative offset between the pose of multiple anchors attached to a trackable may adjust slightly over time as ARCore updates its model of the world.

Parameters
pose

public boolean equals (Object obj)

Indicates whether some other object is a Trackable referencing the same logical trackable as this one.

Parameters
obj the reference object with which to compare.
Returns
  • true if this object is the same as the obj argument; false otherwise.

public Collection<Anchor> getAnchors ()

Gets the Anchors attached to this trackable.

public Pose getPose ()

Gets the pose of the Instant Placement point. Use getTrackingMethod() to determine whether depth and scale are accurate or are based on the estimated depth provided to hitTestInstantPlacement(float, float, float).

If the tracking method is SCREENSPACE_WITH_APPROXIMATE_DISTANCE, the pose will be based on the approximate distance provided to hitTestInstantPlacement(float, float, float).

When the tracking method changes from SCREENSPACE_WITH_APPROXIMATE_DISTANCE to FULL_TRACKING, there will be a noticeable pose jump as the depth changes, from one that's estimated based on the approximate distance provided to hitTestInstantPlacement(float, float, float) to the actual distance as determined by ARCore.

Consequently, the on-screen size, or apparent scale, of any object anchored to the pose will appear to change abruptly. To prevent a visible pop in 3D asset size when the tracking method changes, the scale of the object can be adjusted to counteract the apparent scale change when the tracking method changes. See the InstantPlacementPoint class-level documentation for an example.

public InstantPlacementPoint.TrackingMethod getTrackingMethod ()

public TrackingState getTrackingState ()

Gets this trackable's TrackingState.

public int hashCode ()

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.

Returns
  • a hash code value for this object.
See Also