Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ Missions adapt MMTC to their mission by accomplishing the following two steps:

## Quick Start

MMTC requires Red Hat Enterprise Linux (RHEL) 8 or 9 and Java 8. After cloning the repository and running `./gradlew build`, two MMTC installation options are available:
Build requirements:
- Red Hat Enterprise Linux (RHEL) 8 or 9 on an x86-64 host
- Java 17

Runtime requirements:
- Red Hat Enterprise Linux (RHEL) 8 or 9 on an x86-64 host
- Java 8 for all components except the web application, which requires Java 17

After cloning the repository and running `./gradlew build`, two MMTC installation options are available:

### Demo

Expand All @@ -45,7 +53,6 @@ For users who wish to experiment with MMTC’s behavior and functionality withou

See the "Quick Start Guide" section of the User Guide for complete instructions.


### Installation

To create a traditional clean installation of MMTC that is ready for configuration and adaptation:
Expand All @@ -59,6 +66,6 @@ For further information, please see the User Guide at `docs/User_Guide.adoc`, wh

## Copyright

© 2024 The Johns Hopkins University Applied Physics Laboratory LLC
© 2025 The Johns Hopkins University Applied Physics Laboratory LLC

This work was performed for the Jet Propulsion Laboratory, California Institute of Technology, sponsored by the United States Government under the Prime Contract 80NM0018D00004 between the Caltech and NASA under subcontract number 1658085.
112 changes: 111 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,33 @@ val createDistDir = tasks.register("createDistDir") {

doLast {
exec {
commandLine("bash", "create-dist.sh", project.version)
commandLine("bash", "create-dist.sh", project.version, "cli")
}
}

outputs.dir("build/mmtc-dist-tmp")
}

val createWebAppDistDir = tasks.register("createWebappDistDir") {
inputs.files("mmtc-core/bin/mmtc")
inputs.files("mmtc-core/build/libs/mmtc-core-" + project.version + "-app.jar")
inputs.files("mmtc-plugin-ampcs/build/libs/mmtc-plugin-ampcs-" + project.version + ".jar")
inputs.files("mmtc-webapp/build/libs/mmtc-webapp-" + project.version + ".jar")

dependsOn("mmtc-core:uberJar")
dependsOn("mmtc-plugin-ampcs:jar")
dependsOn(":userGuidePdf")
dependsOn("mmtc-webapp:jar")

doLast {
exec {
commandLine("bash", "create-dist.sh", project.version, "webapp")
}
}

outputs.dir("build/mmtc-webapp-dist-tmp")
}

val mmtcEl8Rpm = tasks.register<Rpm>("mmtcEl8Rpm") {
dependsOn(tasks.build)

Expand Down Expand Up @@ -141,6 +161,73 @@ tasks.getByName("mmtcEl9Rpm") {
dependsOn(tasks.getByName("cleanMmtcEl9Rpm"))
}

val mmtcWebAppEl8Rpm = tasks.register<Rpm>("mmtcWebAppEl8Rpm") {
dependsOn(tasks.build)

packageName = "mmtc-webapp"
distribution = "el8"
release = "1.$distribution"
archStr = "x86_64"
os = org.redline_rpm.header.Os.LINUX

preInstall(file(projectDir.toPath().resolve("rpm-scripts/pre-install.sh")))
postInstall(file(projectDir.toPath().resolve("rpm-scripts/post-install.sh")))

user(this, "mmtc")
permissionGroup(this, "mmtc")

//make the RPM relocatable using prefix(). however, also set the default location using into();
//otherwise, if you install without specifying a custom "--prefix", it gets installed in /usr
//(at least that's what happened in my local testing).
prefix("/opt/local/mmtc")
into("/opt/local/mmtc")

//copy the distribution folder, preserving permissions since they're already correct.
//NOTE: this doesn't seem to set *directory* permissions, so we use post-install.sh for that.
from(projectDir.toPath().resolve("build/mmtc-webapp-dist-tmp"))

//NOTE: create-dist.sh updates bin/mmtc to point to the correct (newly installed) jar file,
//so we no longer create a symlink at lib/mmtc.jar
}

val mmtcWebAppEl9Rpm = tasks.register<Rpm>("mmtcWebAppEl9Rpm") {
dependsOn(tasks.build)

packageName = "mmtc-webapp"
distribution = "el9"
release = "1.$distribution"
archStr = "x86_64"
os = org.redline_rpm.header.Os.LINUX

preInstall(file(projectDir.toPath().resolve("rpm-scripts/pre-install.sh")))
postInstall(file(projectDir.toPath().resolve("rpm-scripts/post-install.sh")))

user(this, "mmtc")
permissionGroup(this, "mmtc")

//make the RPM relocatable using prefix(). however, also set the default location using into();
//otherwise, if you install without specifying a custom "--prefix", it gets installed in /usr
//(at least that's what happened in my local testing).
prefix("/opt/local/mmtc")
into("/opt/local/mmtc")

//copy the distribution folder, preserving permissions since they're already correct.
//NOTE: this doesn't seem to set *directory* permissions, so we use post-install.sh for that.
from(projectDir.toPath().resolve("build/mmtc-webapp-dist-tmp"))

//NOTE: create-dist.sh updates bin/mmtc to point to the correct (newly installed) jar file,
//so we no longer create a symlink at lib/mmtc.jar
}

// fix for Rpm task setting incorrect digests in RPM metadata
tasks.getByName("mmtcWebAppEl8Rpm") {
dependsOn(tasks.getByName("cleanMmtcWebAppEl8Rpm"))
}

tasks.getByName("mmtcWebAppEl9Rpm") {
dependsOn(tasks.getByName("cleanMmtcWebAppEl9Rpm"))
}

distributions {
main {
distributionBaseName.set(project.name)
Expand All @@ -150,6 +237,15 @@ distributions {
}
}

distributions {
create("mmtcWebApp") {
distributionBaseName.set("mmtc-webapp")
contents {
from("build/mmtc-webapp-dist-tmp")
}
}
}

tasks.distZip {
dependsOn(createDistDir)
}
Expand All @@ -164,6 +260,20 @@ tasks.installDist {
dependsOn(createDistDir)
}

tasks.getByName<Zip>("mmtcWebAppDistZip") {
dependsOn(createWebAppDistDir)
}

tasks.getByName<Tar>("mmtcWebAppDistTar") {
dependsOn(createWebAppDistDir)
compression = Compression.GZIP
archiveExtension.set("tar.gz")
}

tasks.getByName("installMmtcWebAppDist") {
dependsOn(createWebAppDistDir)
}

val demoZip = tasks.register("demoZip") {
dependsOn(tasks.build)
dependsOn(createDistDir)
Expand Down
24 changes: 22 additions & 2 deletions create-dist.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#!/bin/bash

# only arg provided to this script must be project version string
# two args provided to this script:
# - project version string
# - "cli" or "webapp"

set -e

DIST_DIR=build/mmtc-dist-tmp
if [ "${2}" = "webapp" ]; then
DIST_DIR=build/mmtc-webapp-dist-tmp
else
DIST_DIR=build/mmtc-dist-tmp
fi

if [[ -d $DIST_DIR ]]; then
rm -r $DIST_DIR
Expand Down Expand Up @@ -53,3 +59,17 @@ touch $DIST_DIR/log/.keep

mkdir $DIST_DIR/output/
touch $DIST_DIR/output/.keep

if [ "${2}" = "webapp" ]; then
cp mmtc-webapp/bin/mmtc-webapp $DIST_DIR/bin

if [[ "$OSTYPE" == "darwin"* ]]; then
# BSD sed
sed -i '' "s|@VERSION@|${1}|" $DIST_DIR/bin/mmtc-webapp
else
# assume Linux (and GNU sed)
sed -i "s/@VERSION@/${1}/" $DIST_DIR/bin/mmtc-webapp
fi

cp mmtc-webapp/build/libs/mmtc-webapp-$1.jar $DIST_DIR/lib/
fi
7 changes: 6 additions & 1 deletion mmtc-core/bin/mmtc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ fi

echo

if [[ -z "${MMTC_JAR+x}" ]]
then
export MMTC_JAR=mmtc-core-@[email protected]
fi

exec ${JAVA_HOME}/bin/java \
-jar \
-Djava.library.path=${MMTC_HOME}/lib/naif/JNISpice/lib \
-Dlog4j2.configurationFile=${MMTC_HOME}/conf/log4j2.xml \
${MMTC_HOME}/lib/mmtc-core-@[email protected] "$@"
${MMTC_HOME}/lib/${MMTC_JAR} "$@"
4 changes: 4 additions & 0 deletions mmtc-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ dependencies {
"configuration" to "precompiledClasses"
)))

// provides javax.xml.bind classes
implementation("jakarta.xml.bind:jakarta.xml.bind-api:4.0.2")
implementation("com.sun.xml.bind:jaxb-impl:4.0.2")

implementation("commons-beanutils:commons-beanutils:1.11.0")
implementation("org.apache.commons:commons-configuration2:2.12.0")
implementation("com.google.guava:guava:33.4.8-jre")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class MmtcCli {
public static final Marker USER_NOTICE = MarkerManager.getMarker("USER_NOTICE");
Expand Down Expand Up @@ -115,7 +116,7 @@ public static void main(String[] args) {
}
case ROLLBACK: {
try {
new TimeCorrelationRollback(appInvoc.args).rollback();
new TimeCorrelationRollback(appInvoc.args).rollback(Optional.empty());
} catch (Exception e) {
logger.fatal("Rollback failed.", e);
System.exit(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package edu.jhuapl.sd.sig.mmtc.app;

import edu.jhuapl.sd.sig.mmtc.cfg.TimeCorrelationAppConfig;
import edu.jhuapl.sd.sig.mmtc.cfg.TimeCorrelationRunConfig;
import edu.jhuapl.sd.sig.mmtc.correlation.TimeCorrelationContext;
import edu.jhuapl.sd.sig.mmtc.products.model.SclkKernel;
import edu.jhuapl.sd.sig.mmtc.products.model.TextProductException;
Expand Down Expand Up @@ -77,6 +77,7 @@ private double computeTdtPredictionErrorMs() throws MmtcException {
double estimatedEtUsingPriorCorrelation = CSPICE.sct2e(ctx.config.getNaifSpacecraftId(), actualEncSclk);
double estimatedTdtUsingPriorCorrelation = CSPICE.unitim(estimatedEtUsingPriorCorrelation, "ET", "TDT");
return (estimatedTdtUsingPriorCorrelation - actualTdt) * TimeConvert.MSEC_PER_SECOND;
// experimental == estimated - actual/accepted
} catch (SpiceErrorException ex) {
throw new MmtcException("Unable to compute TDT error: " + ex.getMessage(), ex);
}
Expand Down Expand Up @@ -115,7 +116,7 @@ private void retrieveAndComputeGncParams() throws MmtcException, TimeConvertExce
logger.info("Retrieving GNC parameter values and calculating related metrics");

// create local refs for brevity throughout the rest of this method
final TimeCorrelationAppConfig config = ctx.config;
final TimeCorrelationRunConfig config = ctx.config;
final TelemetrySource tlmSource = ctx.telemetrySource;
// final FrameSample targetSample = ctx.correlation.target.get().getTargetSample();
final TimeCorrelationTarget tcTarget = ctx.correlation.target.get();
Expand Down Expand Up @@ -252,7 +253,7 @@ private double computeTdtSErrorMs(TelemetrySource.GncParms gncParms, Double curr
* @throws MmtcException if the state vector could not be computed
*/
private double[] computeTargetState(String target, String observer) throws TimeConvertException, MmtcException {
final TimeCorrelationAppConfig config = ctx.config;
final TimeCorrelationRunConfig config = ctx.config;
final FrameSample targetSample = ctx.correlation.target.get().getTargetSample();

final String corr = "NONE"; // Aberration correction
Expand Down
Loading