C $Id: icss_transf_orb.f,v 1.2 1998/07/24 21:54:42 asc Exp $
CCCC
C
C  ICSS_TRANSF_ORB - converts any vectorized quantity from one
C	             coordinate system to another.
C 
C  PURPOSE:  Vectors in GCI, GSE, GEO, GSM, HSEa(inertial), HSEb(earth-oriented) or HS
C	     coordinates are accepted and transformed into the user's choice
C	     of GCI, GSE, GEO, GSM, HSEa, HSEb or HS coordinates. However, not
C            all permutations are implemented.
C
C  UNIT TYPE:  SUBROUTINE
C
C  INVOCATION METHOD:  CALL ICSS_TRANSF_ORB   (orb_src_sys, 
C                                              orb_target_sys,
C	                                       orb_pos, 
C                                              orb_pos_time, 
C                                              trans_orb_pos, 
C					       rotation_matrix,
C                                              trans_orb_stat)
C
C  ARGUMENT LIST:
C
C  NAME	             TYPE     USE     DESCRIPTION
C  ----              ----     ---     -----------
C  SRC_SYS           I*4      I       COORDINATE SYS OF ENTERED ORBIT VECTOR
C  TARGET_SYS        I*4      I       REQ. COORD. SYS OF ORBIT VECTOR
C  ORB_POS(3)        R*8      I       ORBIT VECTOR TO BE TRANSFORMED
C  ORB_POS_TIME(2)   I*4      I       TIME OF ORB. VECTOR, YEAR-DAY,MILLI OF DAY
C  TRANS_ORB_POS(3)  R*8      O       TRANSFORMED ORBIT VECTOR
C  ROTATION_MATRIX(9)R*8      O	      ROTATION MATRIX
C  TRANS_ORB_STAT    I*4      O       FLAG SHOWING STATUS OF TRANS. REQUEST
C
C  FILE/RECORD REFERENCES:  NONE
C
C  EXTERNAL VARIABLES:  NONE
C
C  EXTERNAL REFERENCES:
C    IC_GCI_TO_GEO          Returns the GCI to GEO transformation matrix
C    IC_GCI_TO_GSE	    Returns the GCI to GSE transformation matrix
C    IC_GCI_TO_GSM	    Returns the GCI to GSM transformation matrix
C    MXTRP8		    Routine that transposes matrices, but also
C                            inverts rotation matrices (the matrix that
C                            transforms a vector from one system to another)
C    IC_GSE_TO_GEO	    Returns the GSE to GEO transformation matrix
C    IC_GSE_TO_GSM	    Returns the GSE to GSM transformation matrix
C    IC_GSM_TO_GEO	    Returns the GSM to GEO transformation matrix
C    IC_GSE_TO_HSEB	    Returns the GSE to HSEb transformation matrix
C                             (need to shift origin also)
C    IC_HSEB_TO_HS	    Returns the HSEB to HS transformation matrix
C    MULMAT		    Routine that multiplies two matrices
C
C  ABNORMAL TERMINATION CONDITIONS, ERROR MESSAGES:

C
C  THE RETURN STATUS IS SET TO A NON-ZERO STATUS FROM A SUBORDINATE UNIT 
C  THAT RETURNS AN ERROR
C
C ASSUMPTIONS, CONSTRAINTS, RESTRICTIONS:  Only the following transformations
C are implemented, currently:
C GCI to GEO
C GCI to GSE
C GCI t0 GSM
C GSE to GCI
C GSE to GEO
C GSE to GSM
C GSE to HSEb
C GSM to GEO
C GSM to GSM
C GSM to GSE
C HSEb to HS
C
C
C  DEVELOPMENT HISTORY
C
C  AUTHOR	CHANGE ID	RELEASE	  DATE	    DESCRIPTION OF CHANGE
C  ------	---------	-------   ----	    ---------------------
C  J. LUBELCZYK                 B1R1      10/17/90  INITIAL PDL
C  J. Lubelczyk                 B1R1      12/10/90  CODING
C  J. LUBELCZYK ICCR #83, CCR #'S 130, 137 09/12/91 Return Transform matrix
C  J. LUBELCZYK                           09/19/91  Added error handling
C  J. Rizzello  ICCR #0761                11/26/91  Use local variables for
C                                                   upper case conversion
C  J. Rizzello  ICCR #0558                02/11/92  Return SS$_NORMAL to caller
C                                                    when successful
C  B. SAMUELSON SPOF PORT                 04/11/94  Change: required to port
C     (CSC)     (see notes)                          icss routines to SPOF
C
C  A. DAVIS     ACE SCIENCE CENTER        08/15/97  Added HS, HSE
C  S. HEMPLE    ACE SCIENCE CENTER        01/14/98  Added RTN and CORRECTED 
C                                                        HSEa, HSEb, and HS
C
C  NOTES:
C
C     1.  The changes recorded under ID SPOF-PORT are required to make the
C         ICSS coordinate conversion routines, originally developed under
C         VAX-VMS 5.4 run on the UNIX-based workstations of the SPOF.  (Sun
C         SPARCstations and DEC DECstations).  The changes are as follows:
C            a.  Delete references to ICSS_INC
C            b.  Define Message texts or files to correspond to the messages
C                ICSS_SUCCESSFUL, etc. which are embedded in the error handling.
C            c.  Remove references to the NAG routines F01CRF and F01CKF (matrix
C                transposition and matrix multiplication routines).
C     2.  In addition, to successfully run the software packages, copies of the
C         Solar/Lunar/Planetary (SLP) file and timing coefficients file (TCC)
C         must be ported onto the SPOF.
C     4.  This version uses numbers to indicate source an target coordinate
C         systems instead of characters to simplify conversion to different
C         platforms. The values are as follows:
C             GCI = 1
C             GSE = 2
C             GSM = 3
C             GEO = 4
C             HSEb = 5
C             HSEa = 6
C             HS  = 7
C             RTN = 8
C
CCCC
C
C  PDL:
C
C  Set TRANS_ORB_STAT to successful
C  if the source or target system are invalid then
C     SET error status
C     ABORT TO 990
C  endif
C  if the source system equals the target system then
C     TRANS_ORB_POS = ORB_POS
C     ABORT TO 990
C  endif
C
C  docase KEY ON ORBIT SOURCE SYSTEM
C  case 1 (SRC_SYS is equal to GCI)
C
C     docase SOURCE SYS IS GCI, GET CORRESPONDING ORBIT TARGET SYSTEM
C     case 1 (TARGET_SYS is equal to GEO)
C        call IC_GCI_TO_GEO to get the gci to geo TRANSFORM_MATRIX
C     case 2 (TARGET_SYS is equal to GSE)
C        call IC_GCI_TO_GSE to get the gci to gse TRANSFORM_MATRIX
C     case 3 (TARGET_SYS is equal to GSM)
C        call IC_GCI_TO_GSM to get the gci to gsm TRANSFORM_MATRIX
C     enddo
C
C  case 2 (SRC_SYS is equal to GSE)
C
C     docase SOURCE SYS IS GSE, GET CORRESPONDING ORBIT TARGET SYSTEM
C     case 1 (TARGET_SYS is equal to GCI)
C        call IC_GCI_TO_GSE to get the gci to gse TRANSFORM_MATRIX
C        call MXTRP8 routine to invert the TRANSFORM_MATRIX resulting
C         in the gse to gci TRANSFORM_MATRIX
C     case 2 (TARGET_SYS is equal to GEO)
C        call IC_GSE_TO_GEO to get the gse to geo TRANSFORM_MATRIX
C     case 3 (TARGET_SYS is equal to GSM)
C        call IC_GSE_TO_GSM to get the gse to gsm TRANSFORM_MATRIX
C     case 4 (TARGET_SYS is equal to HSEb)
C        call IC_GSE_TO_HSEb to get the GSE to HSEb TRANSFORM_MATRIX
C     enddo
C
C  case 3 (SRC_SYS is equal to GSM)
C
C     docase SOURCE SYS IS GSM, GET CORRESPONDING ORBIT TARGET SYSTEM
C     case 1 (TARGET_SYS is equal to GCI)
C        call IC_GCI_TO_GSM to get the gci to gsm TRANSFORM_MATRIX
C        call MXTRP8 routine to invert the TRANSFORM_MATRIX resulting
C         in the gsm to gci TRANSFORM_MATRIX
C     case 2 (TARGET_SYS is equal to GEO)
C        call IC_GSM_TO_GEO to get the gsm to geo TRANSFORM_MATRIX
C     case 3 (TARGET_SYS is equal to GSE)
C        call IC_GSE_TO_GSM to get the gse to gsm TRANSFORM_MATRIX
C        call MXTRP8 routine to invert the TRANSFORM_MATRIX resulting
C         in the gsm to gse TRANSFORM_MATRIX
C     enddo
C
C  case 4 (SRC_SYS is equal to GEO)
C     Not implemented
C
C  case 5 (SRC_SYS is equal to HSEb)
C     docase SOURCE SYS IS HSEb, GET CORRESPONDING ORBIT TARGET SYSTEM
C     case 1 (TARGET_SYS is equal to HS)
C        call IC_HSEb_TO_HS to get the HSEb to HS TRANSFORM_MATRIX
C     propose HSEb->GSE->GCI->Whatever (not implemented)
C     enddo
C
C  case 6 (SRC_SYS is equal to HS)
C        propose HS->HSEb->GSE->GCI->Whatever (not implemented)
C  enddo
C
C  if getting the transformation matrix was not successful abort to 990
C
C  call MULMAT routine to multiply the TRANSFORM_MATRIX and 
C   the given ORB_POS vector.  The result will be the TRANS_ORB_POS.
C
C  Return the transformation matrix in 9 element single dimension format
C
C990 CONTINUE
C
C  RETURN
C
CCCC
	subroutine ICSS_TRANSF_ORB   (src_sys,              ! INT*4  
     -                                target_sys,           ! INT*4
     -				      orb_pos,              ! REAL*8 (3)
     -				      orb_pos_time,         ! INT*4 (2)
     -				      trans_orb_pos,        ! REAL*8 (3)
     -				      rotation_matrix,      ! REAL*8 (9)
     -				      trans_orb_stat)       ! INT*4
C
	implicit        NONE
C
C*  Calling Parameters
C
	integer*4	SRC_SYS	            !coord sys of entered orbit vector
	integer*4       TARGET_SYS          !req coord sys of orbit vector
	real*8		ORB_POS(3)          !orbit vector to be transformed
	real*8		TRANS_ORB_POS(3)    !transformed orbit vector
	integer*4	ORB_POS_TIME(2)     !time of orb vector, year-day, milli
	real*8		ROTATION_MATRIX(9)  !Rotation matrix
	integer*4	TRANS_ORB_STAT      !status of transfer request
        integer*4       STATUS
C
C*  Other Variables
C
        real*8          TEMP_MATRIX(3,3) !temporary result matrix
        real*8          TEMP_MATRIX2(3,3)!temporary result matrix 2
        real*8          DUMMY(3,3)
        real*8          trans_pos_vec(3)
	real*8		TRANSFORM_MATRIX(3,3) !Transformation Matrix, Name is
C					!generic to allow a single matrix
C      					!multiplication statement
        integer*4       INTDUMMY /0/
C
C*  Includes
C
C
C*  Begin executable code
C
        STATUS = 0
	TRANS_ORB_STAT = 0 
C
C* Check for invalid source or target coordinate systems
C

C        write(*,*) SRC_SYS,TARGET_SYS, ORB_POS(1),ORB_POS(2),ORB_POS(3)
C        write(*,*) ORB_POS_TIME(1),ORB_POS_TIME(2)

        TRANS_ORB_STAT = 0
        if ((SRC_SYS .lt. 1) .or. (SRC_SYS .gt. 8)) then
           TRANS_ORB_STAT = 1
           goto 990
        else if ((TARGET_SYS .lt. 1) .or. (TARGET_SYS .gt. 8)) then
           TRANS_ORB_STAT = 1
           goto 990
        endif
C
C*  Validate source system and target system
C
	if  (SRC_SYS .eq. TARGET_SYS) then
	   TRANS_ORB_POS(1) = ORB_POS(1)
	   TRANS_ORB_POS(2) = ORB_POS(2)
	   TRANS_ORB_POS(3) = ORB_POS(3)
	   goto 990
	endif
C
C*  Get the appropriate transformation matrix
C
	if (SRC_SYS .eq. 1) then
	   if (TARGET_SYS .eq. 4) then
	      call IC_GCI_TO_GEO (ORB_POS_TIME, TRANSFORM_MATRIX,  
     1                            DUMMY, INTDUMMY)
	   else if (TARGET_SYS .eq. 2) then
	      call IC_GCI_TO_GSE (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	   else if (TARGET_SYS .eq. 3) then
	      call IC_GCI_TO_GSM (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	   else if (TARGET_SYS .eq. 5) then
	      call IC_GCI_TO_GSE (ORB_POS_TIME, 
     1                 TEMP_MATRIX, DUMMY, INTDUMMY, STATUS)
	      call IC_GSE_TO_HSEB (ORB_POS_TIME, 
     1             TEMP_MATRIX2, DUMMY, INTDUMMY, STATUS,
     2                                    trans_pos_vec)
              call MULMAT (TEMP_MATRIX2,TEMP_MATRIX,3,3,3,
     1                                      TRANSFORM_MATRIX)
	   else if (TARGET_SYS .eq. 7) then
	      call IC_GCI_TO_GSE (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	      call IC_GSE_TO_HSEB (ORB_POS_TIME, 
     1                 TEMP_MATRIX, DUMMY, INTDUMMY, STATUS,
     2                                    trans_pos_vec)
              call MULMAT (TEMP_MATRIX,TRANSFORM_MATRIX,3,3,3,
     1                                      TEMP_MATRIX2)
	      call IC_HSEB_TO_HSEA (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
              call MULMAT (TRANSFORM_MATRIX,TEMP_MATRIX2,3,3,3,
     1                                      TEMP_MATRIX)
	      call IC_HSEA_TO_HS (ORB_POS_TIME, 
     1                 TEMP_MATRIX2, DUMMY, INTDUMMY, STATUS)
              call MULMAT (TEMP_MATRIX2,TEMP_MATRIX,3,3,3,
     1                                      TRANSFORM_MATRIX)
           else ! Unimplemented target
	      STATUS = 1
	   endif
	else if (SRC_SYS .eq. 2) then
	   if (TARGET_SYS .eq. 1) then
	      call IC_GCI_TO_GSE (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)

	      call MXTRP8 (TRANSFORM_MATRIX, TEMP_MATRIX, 3, 3)	
              TRANSFORM_MATRIX(1,1) = TEMP_MATRIX(1,1)
              TRANSFORM_MATRIX(2,1) = TEMP_MATRIX(2,1)
              TRANSFORM_MATRIX(3,1) = TEMP_MATRIX(3,1)
              TRANSFORM_MATRIX(1,2) = TEMP_MATRIX(1,2)
              TRANSFORM_MATRIX(2,2) = TEMP_MATRIX(2,2)
              TRANSFORM_MATRIX(3,2) = TEMP_MATRIX(3,2)
              TRANSFORM_MATRIX(1,3) = TEMP_MATRIX(1,3)
              TRANSFORM_MATRIX(2,3) = TEMP_MATRIX(2,3)
              TRANSFORM_MATRIX(3,3) = TEMP_MATRIX(3,3)
           else if (TARGET_SYS .eq. 4) then
	      call IC_GSE_TO_GEO (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	   else  if (TARGET_SYS .eq. 3) then
	      call IC_GSE_TO_GSM (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	   else  if (TARGET_SYS .eq. 5) then
	      call IC_GSE_TO_HSEb (ORB_POS_TIME, 
     1         TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS,
     2                                           trans_pos_vec)
           else ! Unimplemented target
	      STATUS = 1
	   endif
	else if (SRC_SYS .eq. 3) then
	   if (TARGET_SYS .eq. 1) then
	      call IC_GCI_TO_GSM (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	      call MXTRP8 (TRANSFORM_MATRIX, TEMP_MATRIX, 3, 3)
              TRANSFORM_MATRIX(1,1) = TEMP_MATRIX(1,1)
              TRANSFORM_MATRIX(2,1) = TEMP_MATRIX(2,1)
              TRANSFORM_MATRIX(3,1) = TEMP_MATRIX(3,1)
              TRANSFORM_MATRIX(1,2) = TEMP_MATRIX(1,2)
              TRANSFORM_MATRIX(2,2) = TEMP_MATRIX(2,2)
              TRANSFORM_MATRIX(3,2) = TEMP_MATRIX(3,2)
              TRANSFORM_MATRIX(1,3) = TEMP_MATRIX(1,3)
              TRANSFORM_MATRIX(2,3) = TEMP_MATRIX(2,3)
              TRANSFORM_MATRIX(3,3) = TEMP_MATRIX(3,3)
	   else if (TARGET_SYS .eq. 4) then
	      call IC_GSM_TO_GEO (ORB_POS_TIME, 
     1                  TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	   else if (TARGET_SYS .eq. 2) then
	      call IC_GSE_TO_GSM (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	      call MXTRP8 (TRANSFORM_MATRIX, TEMP_MATRIX, 3, 3)
              TRANSFORM_MATRIX(1,1) = TEMP_MATRIX(1,1)
              TRANSFORM_MATRIX(2,1) = TEMP_MATRIX(2,1)
              TRANSFORM_MATRIX(3,1) = TEMP_MATRIX(3,1)
              TRANSFORM_MATRIX(1,2) = TEMP_MATRIX(1,2)
              TRANSFORM_MATRIX(2,2) = TEMP_MATRIX(2,2)
              TRANSFORM_MATRIX(3,2) = TEMP_MATRIX(3,2)
              TRANSFORM_MATRIX(1,3) = TEMP_MATRIX(1,3)
              TRANSFORM_MATRIX(2,3) = TEMP_MATRIX(2,3)
              TRANSFORM_MATRIX(3,3) = TEMP_MATRIX(3,3)
           else ! Unimplemented target
	      STATUS = 1
	   endif
	else if (SRC_SYS .eq. 4) then
C          Unimplemented	
           STATUS = 1
	else if (SRC_SYS .eq. 5) then
	   if (TARGET_SYS .eq. 6) then
	      call IC_HSEB_TO_HSEA (ORB_POS_TIME, 
     1                 TRANSFORM_MATRIX, DUMMY, INTDUMMY, STATUS)
	   else if (TARGET_SYS .eq. 7) then
	      call IC_HSEB_TO_HSEA (ORB_POS_TIME, 
     1                 TEMP_MATRIX, DUMMY, INTDUMMY, STATUS)
	      call IC_HSEA_TO_HS (ORB_POS_TIME, 
     1                 TEMP_MATRIX2, DUMMY, INTDUMMY, STATUS)
              call MULMAT (TEMP_MATRIX2,TEMP_MATRIX,3,3,3,
     1                                      TRANSFORM_MATRIX)
           else ! Unimplemented target
	      STATUS = 1
	   endif
	endif
C
C*  Check status of the transformation matrix
C
	if (STATUS .ne. 0) goto 990
C
C*  call MULMAT ROUTINE TO MULTIPLY THE TRANSFORMATION MATRIX BY
C*   THE GIVEN ORBIT VECTOR.  THE RESULT WILL BE THE TARGET ORBIT POSITION.
C
	call MULMAT (TRANSFORM_MATRIX, ORB_POS, 3, 3, 1, TRANS_ORB_POS)
C
C*  Return the transformation matrix
C
	ROTATION_MATRIX(1) = TRANSFORM_MATRIX(1,1)
	ROTATION_MATRIX(2) = TRANSFORM_MATRIX(2,1)
	ROTATION_MATRIX(3) = TRANSFORM_MATRIX(3,1)
	ROTATION_MATRIX(4) = TRANSFORM_MATRIX(1,2)
	ROTATION_MATRIX(5) = TRANSFORM_MATRIX(2,2)
	ROTATION_MATRIX(6) = TRANSFORM_MATRIX(3,2)
	ROTATION_MATRIX(7) = TRANSFORM_MATRIX(1,3)
	ROTATION_MATRIX(8) = TRANSFORM_MATRIX(2,3)
	ROTATION_MATRIX(9) = TRANSFORM_MATRIX(3,3)
C
990     if (STATUS .ne. 0) 
     .               TRANS_ORB_STAT = STATUS

	RETURN
C
	END






