8.15. Chandrayaan-2 lunar orbiter

The example here shows how to create a 3D terrain model with Chandrayaan-2 lunar orbiter data, using both the Orbiter High Resolution Camera (OHRC) and the Terrain Mapping Camera-2 (TMC-2).

This workflow uses the Community Sensor Model (Section 8.12). It needs ASP 3.6.0 or later (Section 2.1), ISIS 10.0.0_RC2 (or a later release-candidate or stable version), ALE 1.1.3 or later, and USGSCSM 2.0.2 or later. All are available as public conda packages (see below).

Chandrayaan-2 ISIS data should be downloaded as documented further down.

8.15.1. Environment setup

Fetch ISIS, ALE, USGSCSM, and rclone into a fresh conda environment:

conda create -n isis10rc2                     \
   -c usgs-astrogeology/label/RC              \
   -c conda-forge                             \
   isis=10.0.0_RC2 ale=1.1.3 usgscsm=2.0.2 rclone

Activate the environment:

conda activate isis10rc2
export ISISROOT=$CONDA_PREFIX

Set the location of the ISIS data area (to be downloaded next):

export ISISDATA=$HOME/projects/isisdata
export ALESPICEROOT=$ISISDATA

Install ASP, build 2026/5 or newer (Section 2.1), as some bugfixes for the Chandrayaan-2 cameras were incorporated at that time. Set its path as documented there.

See also the USGS ISIS TMC documentation.

8.15.2. ISIS kernels download

The mission kernels are fetched with downloadIsisData, which is shipped with ISIS:

downloadIsisData chandrayaan2 $ISISDATA

Note that the full chandrayaan2 directory is large (about 200 GB), of which essentially all is reconstructed attitude kernels (ck) covering the entire mission since 2019. For a single OHRC image only one or two ck files are needed. Fetching everything except ck takes only a few hundred MB:

downloadIsisData chandrayaan2 $ISISDATA --exclude="kernels/ck/**"

The command:

rclone --config $ISISROOT/etc/isis/rclone.conf \
  ls chandrayaan2:kernels/ck/

lists all available ck files. This can help pick the ones that span the acquisition time of the products to be processed.

The ck files matching the orbit dates of interest can then be fetched individually with rclone, such as:

rclone                                          \
  --config $ISISROOT/etc/isis/rclone.conf       \
  copy                                          \
  chandrayaan2:kernels/ck/                      \
  $ISISDATA/chandrayaan2/kernels/ck/            \
  --include="ch2_att_27Jul2020_04Sep2020_v1.bc" \
  --include="ch2_att_27Aug2020_04Oct2020_v1.bc" \
  --no-traverse -P

8.15.3. Fetching images

Images, orthoimages, and DEMs for the OHRC and TMC-2 cameras can be downloaded from ISRO.

Each download is a zip. After unzipping, locate the .img and .xml files and move them into a working directory. Keep the original ISRO filenames; a rename can break isisimport.

8.15.4. Orbiter High Resolution Camera

The OHRC instrument is a high-resolution camera with a 0.25 m ground sample distance (GSD). It can adjust its look angle and acquire stereo pairs (Section 8.1).

8.15.4.1. Input data

Download the OHRC stereo pair from ISRO as described in Section 8.15.3. We selected the region of interest to be between 20 and 21 degrees in longitude, and -70 to -67 degrees in latitude. The prefixes are:

ch2_ohr_nrp_20200827T0030107497_d_img_d18
ch2_ohr_nrp_20200827T0226453039_d_img_d18

We also got a TMC-2 orthoimage and corresponding DEM with the prefixes:

ch2_tmc_ndn_20231101T0125121377_d_oth_d18
ch2_tmc_ndn_20231101T0125121377_d_dtm_d18

These are at lower resolution but useful for context.

../_images/chandrayaan2_ohrc_tmc.png

Fig. 8.26 From left to right: The first and second OHRC images, and their approximate extent in the (many times larger) TMC-2 ortho image. Note that the illumination in the TMC-2 ortho image is very different.

8.15.4.2. Preprocessing

Each calibrated image dataset has .img and .xml files, with raw data and a PDS-4 label.

The isisimport command converts the raw image to a .cub file:

isisimport \
  from = ch2_ohr_nrp_20200827T0030107497_d_img_d18.xml \
  to   = ch2_ohr_nrp_20200827T0030107497_d_img_d18.cub

(and same for the second image). The PDS4 template is auto-detected in ISIS 10.

For simplicity, the output cub files are renamed to ohrc/img1.cub and ohrc/img2.cub.

ISIS 10 is required for correct OHRC line exposure handling. Older versions wrote a LineExposureDuration value 1000 times too large into the cub label (the ISRO PDS4 label tags the field as unit="ms" but the value is in microseconds), which then propagated into the CSM camera and broke its time-vs-line mapping. Cubs and CSM JSONs created with older ISIS should be rebuilt.

The isisimport command only works with raw images and not with ortho images.

The SPICE kernels are attached with spiceinit:

spiceinit from = ohrc/img1.cub

This expects the SPICE kernels for Chandrayaan-2 to exist locally under $ISISDATA/chandrayaan2/ (see the download instructions above). For more information on ISIS data, see Section 2.3.1 and the links from there.

Next, CSM cameras are created with isd_generate from the ALE package, following the linescan recipe in Section 8.12.2.1:

export ALESPICEROOT=$ISISDATA
isd_generate -k ohrc/img1.cub ohrc/img1.cub
isd_generate -k ohrc/img2.cub ohrc/img2.cub

It is expected that the environment is activated with conda activate, with ISISROOT set to $CONDA_PREFIX, and $ISISDATA and $ALESPICEROOT set, as described in the environment setup section above (not just the environment’s bin directory added to the path). Chandrayaan-2 uses the SpiceQL mission database, and skipping conda activate can make isd_generate crash instead of printing a clear error, as SpiceQL then cannot find its configuration under $CONDA_PREFIX.

Check each produced CSM camera file with cam_test (Section 16.9), against itself and against the .cub camera, before proceeding.

The images can be inspected with stereo_gui (Section 16.71), as:

stereo_gui ohrc/img1.cub ohrc/img2.cub

The resulting cub files are very large, on the order of 12,000 x 101,075 pixels. For exploratory work, these can be cropped, with the ISIS crop command, such as:

crop                            \
  from     = ohrc/img1.cub      \
  to       = ohrc/img1_crop.cub \
  sample   = 1                  \
  line     = 1                  \
  nsamples = 12000              \
  nlines   = 50000

It is very important to ensure that the upper-left pixel (1, 1) is part of the crop region, as otherwise the resulting images will be inconsistent with the CSM camera models.

8.15.4.3. Bundle adjustment

We found that these images have notable pointing error, so bundle adjustment (Section 16.5) is needed:

bundle_adjust                           \
  ohrc/img1_crop.cub ohrc/img2_crop.cub \
  ohrc/img1.json ohrc/img2.json         \
  --ip-per-image 30000                  \
  -o ba/run

This stereo pair has a convergence angle of about 25 degrees (Section 16.5.11.4).

../_images/chandrayaan2_ohrc_interest_points.png

Fig. 8.27 The left and right cropped OHRC images, and the interest point matches between them (as shown by stereo_gui, Section 16.71.9).

8.15.4.4. Stereo

Just as for TMC (Section 8.15.5), it is suggested to run stereo with mapprojected images (Section 6.1.7) for most reliable results.

Here we do a preliminary parallel_stereo (Section 16.51) run on the crops from above without mapprojected images:

parallel_stereo                     \
  --alignment-method affineepipolar \
  --stereo-algorithm asp_mgm        \
  --clean-match-files-prefix ba/run \
  --nodes-list nodes.txt            \
  ohrc/img1_crop.cub                \
  ohrc/img2_crop.cub                \
  ba/run-img1.adjusted_state.json   \
  ba/run-img2.adjusted_state.json   \
  stereo/run

See Section 8.19 for running on multiple nodes.

A DEM, orthoimage, and triangulation error image are made with point2dem (Section 16.56), as:

point2dem           \
  --tr 1.0          \
  --errorimage      \
  stereo/run-PC.tif \
  --orthoimage      \
  stereo/run-L.tif
../_images/chandrayaan2_ohrc_dem_ortho_err.png

Fig. 8.28 From left to right: Produced OHRC DEM (range of heights is 304 to 650 meters), orthoimage, and triangulation error image (blue = 0 m, red = 0.5 m). There is notable jitter, whose magnitude is on the order of image GSD (0.25 m), which is rather high, but which could be corrected (Section 16.38). Some unmodeled lens distortion also seems evident, which could be solved for (Section 12.2.2).

8.15.4.5. Alignment to LOLA

We aligned the produced OHRC DEM to LOLA (Section 19.11), which is the usual global reference coordinate system for the Moon.

The OHRC DEM turned out to be shifted relative to LOLA by about 4 km along the satellite track, which resulted in failure to align with pc_align (Section 16.53).

Manual alignment was first performed (Section 16.53.12). The inputs were the OHRC DEM and a LOLA point cloud, after gridding both with a 10 m grid size and the same projection with point2dem, and manually picking a few visually similar features. That brought the cloud notably closer, and the output transform from that alignment was used for aligning the full clouds as:

pc_align                                  \
  --max-displacement 250                  \
  --initial-transform init-transform.txt  \
  --csv-format 2:lon,3:lat,4:radius_km    \
  --save-inv-transformed-reference-points \
  stereo/run-DEM.tif lola/lola.csv        \
  -o stereo/run-align
../_images/chandrayaan2_ohrc_lola.png

Fig. 8.29 The difference between the aligned OHRC DEM and LOLA point cloud. Blue = -5 m, red = 5 m. Given that the DEM, in principle, should have a vertical uncertainty of under 1 m, this could be better, but at least we are in the ballpark.

A terrain model created with the lower-resolution TMC-2 images would likely be easier to align to LOLA, as it would have a much bigger extent.

8.15.5. Terrain Mapping Camera-2

The TMC-2 instrument is a 3-line pushbroom camera, with separate forward (fwd), downward-pointing (nadir), and backward (aft) detectors. The fwd detector looks ~25 degrees ahead of nadir and the aft detector looks ~25 degrees behind, a setup which is well-suited to stereo with any of these image pairs. The ground sample distance is about 5 meters at 100 km altitude.

All three detectors record simultaneously, so a substantial ground swath is imaged by all of them.

8.15.5.1. Input data

Download the TMC-2 forward, nadir, and aft stereo triplet from ISRO as described in Section 8.15.3. The three acquisitions cover a shared ground swath on the same orbit pass:

ch2_tmc_ncf_20231101T0125121344_d_img_d18
ch2_tmc_ncn_20231101T0125121377_d_img_d18
ch2_tmc_nca_20231101T0125121377_d_img_d18

We use only the fwd/aft pair below for the largest stereo convergence angle.

The corresponding pre-existing DTM (ch2_tmc_ndn_20231101T0125121377, mentioned earlier) covers the same orbit pass. These images include the footprint of the OHRC images from earlier but extend well beyond them.

8.15.5.2. Preprocessing

We use only the CSM camera models (Section 8.12), as it appears that the non-nadir TMC ISIS camera models in the .cub files are still problematic (as of 5/2026). The fix is to skip spiceinit entirely and run isd_generate directly.

ALE 1.1.3 (without spiceinit-attached kernels) needs a metakernel file under $ALESPICEROOT to locate SPICE kernels, but the USGS Chandrayaan-2 ISIS data area (as of 5/2026) does not ship one. The workaround is to create a small metakernel locally at:

$ISISDATA/chandrayaan2/kernels/mk/ch2_v01.tm

listing the kernel files. The values in PATH_VALUES should be absolute due to limitations in ALE, and should be correct for the local file system. See the NAIF Metakernel reference for the file format and compare with existing .tm files for other missions.

With the metakernel in place, the workflow is as follows:

export ALESPICEROOT=$ISISDATA

isisimport \
  from = ch2_tmc_ncf_20231101T0125121344_d_img_d18.xml \
  to   = ch2_tmc_ncf_20231101T0125121344_d_img_d18.cub

and same for the other ones.

For simplicity, the output cub files are renamed to tmc/fwd.cub and tmc/aft.cub. Then run:

isd_generate tmc/fwd.cub
isd_generate tmc/aft.cub

We skipped the -k option (read kernels from a cub) here given the current issue with spiceinit mentioned earlier.

As of ASP 3.7.0 (June 2026), with the custom-built ISIS 10.0.0, ALE 1.2.0, and USGSCSM 2.0.2 shipped with it (Section 2.2), this is resolved. spiceinit can be run on the TMC cubes and isd_generate invoked with the -k option, as done for OHRC above (Section 8.12). The alternative workflow is then:

spiceinit from = tmc/fwd.cub
spiceinit from = tmc/aft.cub

isd_generate -k tmc/fwd.cub tmc/fwd.cub
isd_generate -k tmc/aft.cub tmc/aft.cub

For the non-nadir fwd channel, the resulting CSM camera agrees with the ISIS camera to about 0.0001 pixels, and is equivalent to the metakernel-based ISD above. Either workflow can be used.

Check each JSON with cam_test (Section 16.9).

8.15.5.3. Bundle adjustment

Bundle-adjust (Section 16.5) the fwd/aft pair with the JSONs as cameras:

bundle_adjust                           \
  tmc/fwd.cub tmc/aft.cub               \
  tmc/fwd.json tmc/aft.json             \
  --num-iterations 100 --num-passes 2   \
  --camera-weight 0 --tri-weight 0.1    \
  --remove-outliers-params "75 3 50 50" \
  --ip-per-image 100000                 \
  --max-pairwise-matches 50000          \
  -o ba/run

It is suggested to inspect the produced report files (Section 16.5.11).

8.15.5.4. Stereo

Stereo with mapprojected images (Section 6.1.7) is strongly suggested for TMC. Using raw images with alignment-method affineepipolar or local_epipolar (Section 17.1.2) is not recommended given the extreme image aspect ratio (the images are about \(4000 \times 180000\) pixels) and the large change in perspective between the images.

The reference DEM for mapprojection can be a prior TMC DTM provided by ISRO (ch2_tmc_ndn_*_d_dtm_d18), a LOLA gridded DEM (Section 11.10.2), or a DEM gridded from LOLA samples with point2dem (Section 16.56.2.7). Fill in holes (Section 16.20.2.9) and blur (dem_mosaic --dem-blur-sigma 5, Section 16.20.2.6) such a DEM. Call it ref.tif.

We employ a south polar stereographic projection given the location of the site.

proj="+proj=stere +lat_0=-90 +lon_0=0 +k=1 +x_0=0 +y_0=0 +R=1737400 +units=m +no_defs"

Mapproject each cub at the native ~5 m/pixel resolution:

mapproject --tr 5 --t_srs "$proj" \
  ref.tif                         \
  tmc/fwd.cub                     \
  ba/run-fwd.adjusted_state.json  \
  tmc/fwd.map.tif

mapproject --tr 5 --t_srs "$proj" \
  ref.tif                         \
  tmc/aft.cub                     \
  ba/run-aft.adjusted_state.json  \
  tmc/aft.map.tif

Run stereo with --alignment-method none on the mapprojected pair, the bundle-adjusted JSON state files, and the reference DEM as the last argument:

parallel_stereo                   \
  --alignment-method none         \
  --stereo-algorithm asp_mgm      \
  --subpixel-mode 9               \
  --nodes-list nodes.txt          \
  tmc/fwd.map.tif tmc/aft.map.tif \
  ba/run-fwd.adjusted_state.json  \
  ba/run-aft.adjusted_state.json  \
  stereo/run                      \
  ref.tif

See Section 8.19 for running on multiple nodes.

Produce a DEM at 20 m / pixel (4x input image resolution, Section 16.56.4) with point2dem (Section 16.56). The --errorimage flag writes the triangulation error image (Section 16.56.2.2). This useful for inspecting along-track jitter (Section 16.38).

point2dem --tr 20 --t_srs "$proj"  \
  --errorimage --orthoimage       \
  stereo/run-L.tif stereo/run-PC.tif
../_images/chandrayaan2_tmc_dem_err.png

Fig. 8.30 Left: portion of the colorized hillshaded DEM produced with mapprojected TMC images. Color range -1130 to 2400 m. Right: triangulation error image, range 0 to 5 m (the ground sample distance).

The same recipe applies to fwd/nadir and nadir/aft once a triplet bundle adjustment has produced run-nadir.adjusted_state.json.

For preliminary investigations, run stereo with images mapprojected onto a small cropped version of the reference DEM.