Skip to content

Commit

Permalink
Merge pull request #12194 from jfayot/feat_tracking_reference_frame
Browse files Browse the repository at this point in the history
Added Entity.trackingReferenceFrame
  • Loading branch information
ggetz authored Nov 15, 2024
2 parents 74663e9 + d9e3859 commit 09a0276
Show file tree
Hide file tree
Showing 11 changed files with 4,286 additions and 30 deletions.
4,010 changes: 4,010 additions & 0 deletions Apps/SampleData/tracking.czml

Large diffs are not rendered by default.

32 changes: 4 additions & 28 deletions Apps/Sandcastle/gallery/Callback Position Property.html
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
}

// Create the entity and bind its position to the callback position property
viewer.entities.add({
const entity = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
Expand All @@ -158,35 +158,11 @@
leadTime: 1,
trailTime: 0.1,
},
trackingReferenceFrame: Cesium.TrackingReferenceFrame.INERTIAL,
viewFrom: new Cesium.Cartesian3(-100, 0, 10),
});

const camera = viewer.camera;
const scene = viewer.scene;

const scratchPosition = new Cesium.Cartesian3();
const scratchOrientation = new Cesium.Quaternion();
const scratchTransform = new Cesium.Matrix4();
const offset = new Cesium.Cartesian3(-100, 0, 10);

// Update camera to follow entity's position and orientation
viewer.clock.onTick.addEventListener(function (clock) {
if (scene.mode === Cesium.Scene.MORPHING) {
return;
}
const time = clock.currentTime;
const entityPosition = position.getValue(time, scratchPosition);
const entityOrientation = orientation.getValue(time, scratchOrientation);
if (entityPosition === undefined || entityOrientation === undefined) {
return;
}
const transform = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
entityPosition,
entityOrientation,
Cesium.Cartesian3.ONE,
scratchTransform,
);
camera.lookAtTransform(transform, offset);
});
viewer.trackedEntity = entity;
//Sandcastle_End
};
if (typeof Cesium !== "undefined") {
Expand Down
110 changes: 110 additions & 0 deletions Apps/Sandcastle/gallery/Entity tracking.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<meta
name="description"
content="Apply different tracking reference frames to tracked entities."
/>
<meta name="cesium-sandcastle-labels" content="Beginner, Showcases" />
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script
type="text/javascript"
src="../../../Build/CesiumUnminified/Cesium.js"
nomodule
></script>
<script type="module" src="../load-cesium-es6.js"></script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
<script id="cesium_sandcastle_script">
window.startup = async function (Cesium) {
"use strict";
//Sandcastle_Begin
// This example illustrates the possible tracking reference frames
// apllied to two different entities: a near surface slow moving
// object and a satellite
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: Cesium.Terrain.fromWorldTerrain(),
shouldAnimate: true,
});

const startTime = Cesium.JulianDate.fromIso8601("2012-03-15T10:00:00Z");

const satelliteStopTime = Cesium.JulianDate.fromIso8601("2012-03-16T10:00:00Z");

const droneStopTime = Cesium.JulianDate.fromIso8601("2012-03-15T10:00:30Z");

const dataSource = await viewer.dataSources.add(
Cesium.CzmlDataSource.load("../../SampleData/tracking.czml"),
);

const satellite = dataSource.entities.getById("Satellite/ISS");
const drone = dataSource.entities.getById("CesiumDrone");

satellite.viewFrom = new Cesium.Cartesian3(-300, 20, 100);
drone.viewFrom = new Cesium.Cartesian3(-50, 0, 5);

Sandcastle.addDefaultToolbarButton("Satellites", function () {
viewer.clock.stopTime = satelliteStopTime;
viewer.clock.currentTime = startTime;
viewer.clock.multiplier = 30;
viewer.timeline.zoomTo(startTime, satelliteStopTime);
viewer.trackedEntity = satellite;
});

Sandcastle.addToolbarButton("Drone", function () {
viewer.clock.stopTime = droneStopTime;
viewer.clock.currentTime = startTime;
viewer.clock.multiplier = 1;
viewer.timeline.zoomTo(startTime, droneStopTime);
viewer.trackedEntity = drone;
});

Sandcastle.addToolbarMenu([
{
text: "Tracking reference frame: Auto-detect",
onselect: function () {
satellite.trackingReferenceFrame = Cesium.TrackingReferenceFrame.AUTODETECT;
drone.trackingReferenceFrame = Cesium.TrackingReferenceFrame.AUTODETECT;
},
},
{
text: "Tracking reference frame: Inertial",
onselect: function () {
satellite.trackingReferenceFrame = Cesium.TrackingReferenceFrame.INERTIAL;
drone.trackingReferenceFrame = Cesium.TrackingReferenceFrame.INERTIAL;
},
},
{
text: "Tracking reference frame: Velocity",
onselect: function () {
satellite.trackingReferenceFrame = Cesium.TrackingReferenceFrame.VELOCITY;
drone.trackingReferenceFrame = Cesium.TrackingReferenceFrame.VELOCITY;
},
},
]);
//Sandcastle_End
};
if (typeof Cesium !== "undefined") {
window.startupCalled = true;
window.startup(Cesium).catch((error) => {
"use strict";
console.error(error);
});
Sandcastle.finishedLoading();
}
</script>
</body>
</html>
Binary file added Apps/Sandcastle/gallery/Entity tracking.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions Apps/Sandcastle/gallery/Interpolation.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,21 @@
viewer.trackedEntity = entity;
});

Sandcastle.addToolbarMenu([
{
text: "Tracking reference frame: East-North-Up",
onselect: function () {
entity.trackingReferenceFrame = Cesium.TrackingReferenceFrame.EAST_NORTH_UP;
},
},
{
text: "Tracking reference frame: Inertial",
onselect: function () {
entity.trackingReferenceFrame = Cesium.TrackingReferenceFrame.INERTIAL;
},
},
]);

//Add a combo box for selecting each interpolation mode.
Sandcastle.addToolbarMenu(
[
Expand Down
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

#### @cesium/engine

##### Additions :tada:

- Added `Entity.trackingReferenceFrame` property to allow tracking entities in their own inertial reference frame. [#12194](https://github.com/CesiumGS/cesium/pull/12194)

##### Fixes :wrench:

- Fix label rendering bug in WebGL1 contexts. [#12301](https://github.com/CesiumGS/cesium/pull/12301)
Expand Down
40 changes: 40 additions & 0 deletions packages/engine/Source/Core/TrackingReferenceFrame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Constants for identifying well-known tracking reference frames.
*
* @enum {number}
*/
const TrackingReferenceFrame = {
/**
* Auto-detect algorithm. The reference frame used to track the Entity will
* be automatically selected based on its trajectory: near-surface slow moving
* objects will be tracked in the entity's local east-north-up reference
* frame, while faster objects like satellites will use VVLH (Vehicle Velocity,
* Local Horizontal).
*
* @type {number}
* @constant
*/
AUTODETECT: 0,

/**
* The entity's inertial reference frame. If entity has no defined orientation
* property, a {@link VelocityOrientationProperty} is used instead, thus
* falling back to <code>TrackingReferenceFrame.VELOCITY</code>.
* When selected, the auto-detect algorithm is overridden.
*
* @type {number}
* @constant
*/
INERTIAL: 1,

/**
* The entity's inertial reference frame with orientation fixed to its
* {@link VelocityOrientationProperty}, ignoring its own orientation.
* When selected, the auto-detect algorithm is overridden.
*
* @type {number}
* @constant
*/
VELOCITY: 2,
};
export default Object.freeze(TrackingReferenceFrame);
16 changes: 15 additions & 1 deletion packages/engine/Source/DataSources/Entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CesiumMath from "../Core/Math.js";
import Matrix3 from "../Core/Matrix3.js";
import Matrix4 from "../Core/Matrix4.js";
import Quaternion from "../Core/Quaternion.js";
import TrackingReferenceFrame from "../Core/TrackingReferenceFrame.js";
import Transforms from "../Core/Transforms.js";
import GroundPolylinePrimitive from "../Scene/GroundPolylinePrimitive.js";
import GroundPrimitive from "../Scene/GroundPrimitive.js";
Expand Down Expand Up @@ -73,8 +74,9 @@ function createPropertyTypeDescriptor(name, Type) {
* @property {string} [name] A human readable name to display to users. It does not have to be unique.
* @property {TimeIntervalCollection} [availability] The availability, if any, associated with this object.
* @property {boolean} [show] A boolean value indicating if the entity and its children are displayed.
* @property {TrackingReferenceFrame} [trackingReferenceFrame=TrackingReferenceFrame.AUTODETECT] The reference frame used when this entity is being tracked. <br/> If <code>undefined</code>, reference frame is determined based on entity velocity: near-surface slow moving entities are tracked using the local east-north-up reference frame, whereas fast moving entities such as satellites are tracked using VVLH (Vehicle Velocity, Local Horizontal).
* @property {Property | string} [description] A string Property specifying an HTML description for this entity.
* @property {PositionProperty | Cartesian3 | CallbackProperty} [position] A Property specifying the entity position.
* @property {PositionProperty | Cartesian3 | CallbackPositionProperty} [position] A Property specifying the entity position.
* @property {Property | Quaternion} [orientation=Transforms.eastNorthUpToFixedFrame(position)] A Property specifying the entity orientation in respect to Earth-fixed-Earth-centered (ECEF). If undefined, east-north-up at entity position is used.
* @property {Property | Cartesian3} [viewFrom] A suggested initial offset for viewing this object.
* @property {Entity} [parent] A parent entity to associate with this entity.
Expand Down Expand Up @@ -122,6 +124,10 @@ function Entity(options) {
this._definitionChanged = new Event();
this._name = options.name;
this._show = defaultValue(options.show, true);
this._trackingReferenceFrame = defaultValue(
options.trackingReferenceFrame,
TrackingReferenceFrame.AUTODETECT,
);
this._parent = undefined;
this._propertyNames = [
"billboard",
Expand Down Expand Up @@ -296,6 +302,14 @@ Object.defineProperties(Entity.prototype, {
this._definitionChanged.raiseEvent(this, "show", value, !value);
},
},
/**
* Gets or sets the entity's tracking reference frame.
* @demo {@link https://sandcastle.cesium.com/index.html?src=Entity tracking.html|Cesium Sandcastle Entity tracking Demo}
*
* @memberof Entity.prototype
* @type {TrackingReferenceFrame}
*/
trackingReferenceFrame: createRawPropertyDescriptor("trackingReferenceFrame"),
/**
* Gets whether this entity is being displayed, taking into account
* the visibility of any ancestor entities.
Expand Down
51 changes: 50 additions & 1 deletion packages/engine/Source/DataSources/EntityView.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import JulianDate from "../Core/JulianDate.js";
import CesiumMath from "../Core/Math.js";
import Matrix3 from "../Core/Matrix3.js";
import Matrix4 from "../Core/Matrix4.js";
import Quaternion from "../Core/Quaternion.js";
import TrackingReferenceFrame from "../Core/TrackingReferenceFrame.js";
import Transforms from "../Core/Transforms.js";
import SceneMode from "../Scene/SceneMode.js";
import VelocityVectorProperty from "./VelocityVectorProperty.js";

const updateTransformMatrix3Scratch1 = new Matrix3();
const updateTransformMatrix3Scratch2 = new Matrix3();
Expand All @@ -21,6 +24,9 @@ const updateTransformCartesian3Scratch3 = new Cartesian3();
const updateTransformCartesian3Scratch4 = new Cartesian3();
const updateTransformCartesian3Scratch5 = new Cartesian3();
const updateTransformCartesian3Scratch6 = new Cartesian3();
const updateTransformOrientationScratch = new Quaternion();
const velocityScratch = new Cartesian3();
const rotationScratch = new Matrix3();
const deltaTime = new JulianDate();
const northUpAxisFactor = 1.25; // times ellipsoid's maximum radius

Expand All @@ -30,6 +36,9 @@ function updateTransform(
updateLookAt,
saveCamera,
positionProperty,
velocityProperty,
orientationProperty,
trackingReferenceFrame,
time,
ellipsoid,
) {
Expand Down Expand Up @@ -228,7 +237,39 @@ function updateTransform(
}

const transform = updateTransformMatrix4Scratch;
if (hasBasis) {

let orientation;
if (defined(orientationProperty)) {
orientation = orientationProperty.getValue(
time,
updateTransformOrientationScratch,
);
}

const velocity = velocityProperty.getValue(time, velocityScratch);

if (
trackingReferenceFrame === TrackingReferenceFrame.INERTIAL &&
defined(orientation)
) {
Matrix4.fromTranslationQuaternionRotationScale(
cartesian,
orientation,
Cartesian3.ONE,
transform,
);
} else if (
trackingReferenceFrame === TrackingReferenceFrame.VELOCITY &&
defined(velocity)
) {
const rotation = Transforms.rotationMatrixFromPositionVelocity(
cartesian,
velocity,
ellipsoid,
rotationScratch,
);
Matrix4.fromRotationTranslation(rotation, cartesian, transform);
} else if (hasBasis) {
transform[0] = xBasis.x;
transform[1] = xBasis.y;
transform[2] = xBasis.z;
Expand Down Expand Up @@ -316,6 +357,8 @@ function EntityView(entity, scene, ellipsoid) {
this._lastCartesian = new Cartesian3();
this._defaultOffset3D = undefined;

this._velocityProperty = new VelocityVectorProperty(entity.position, true);

this._offset3D = new Cartesian3();
}

Expand Down Expand Up @@ -362,10 +405,13 @@ EntityView.prototype.update = function (time, boundingSphere) {
}

const entity = this.entity;
const trackingReferenceFrame = entity.trackingReferenceFrame;
const positionProperty = entity.position;
if (!defined(positionProperty)) {
return;
}
const velocityProperty = this._velocityProperty;
const orientationProperty = entity.orientation;
const objectChanged = entity !== this._lastEntity;
const sceneModeChanged = sceneMode !== this._mode;

Expand Down Expand Up @@ -419,6 +465,9 @@ EntityView.prototype.update = function (time, boundingSphere) {
updateLookAt,
saveCamera,
positionProperty,
velocityProperty,
orientationProperty,
trackingReferenceFrame,
time,
ellipsoid,
);
Expand Down
Loading

0 comments on commit 09a0276

Please sign in to comment.