@petrus.hyvonen @luc would you have some test file in Python showing creation of a class using PythonAttitudeProviderModifier ?
In a nutshell I want to perform yaw-steering using CelestialBodyPointed as an underlying provider (so as I can point Z axis towards another SC, while managing remaining degree of freedom to maximize sun illumination), but the current implementation does not allow it, because type of underlying provider for YawSteering is restricted to GroundPointing, while CelestialBodyPointed is not of that type (its type is AttitudeProvider)
I thus created a python class YawSteering2 overloading required functions using PythonAttitudeProviderModifier, but I get a run time error (invalid args on getAttitude), and I don’t know why.
Here is the code of the class:
class YawSteering2(PythonAttitudeProviderModifier):
    PLUS_Z = PVCoordinates(Vector3D.PLUS_K, Vector3D.ZERO, Vector3D.ZERO);
    
    def __init__(self, inertialFrame, groundPointingLaw, sun, phasingAxis):
        self.sun = sun        
        self.groundPointingLaw = groundPointingLaw
        self.inertialFrame = inertialFrame
        self.phasingNormal = PVCoordinates(Vector3D.crossProduct(Vector3D.PLUS_K, phasingAxis).normalize(),
                                               Vector3D.ZERO,
                                               Vector3D.ZERO);
        super(YawSteering2, self).__init__()
        
    def getUnderlyingAttitudeProvider(self)->AttitudeProvider :
        return self.groundPointingLaw
    
    def getAttitude(self, pVCoordinatesProvider, absoluteDate, frame) -> Attitude:
        base = self.getBaseState(pVCoordinatesProvider, absoluteDate, frame)
        sunDirection = PVCoordinates(pVCoordinatesProvider.getPVCoordinates(absoluteDate, frame),
                      self.sun.getPVCoordinates(absoluteDate, frame))
        sunNormal = PVCoordinates.crossProduct(self.PLUS_Z, base.getOrientation().applyTo(sunDirection))
        compensation = TimeStampedAngularCoordinates(absoluteDate, self.PLUS_Z, sunNormal.normalize(),
                                                  self.PLUS_Z, self.phasingNormal,
                                                  1.0e-9)
        return Attitude(frame, compensation.addOffset(base.getOrientation()))
     
    def getAttitude_FFF(self, fieldPVCoordinatesProvider, fieldAbsoluteDate, frame) -> FieldAttitude:
        field = fieldAbsoluteDate.getField()
        zero = FieldVector3D.getZero(field)
        plusZ = FieldPVCoordinates(FieldVector3D.getPlusK(field), zero, zero)
        
        base = self.getBaseState(fieldPVCoordinatesProvider, fieldAbsoluteDate, frame)
        
        sunDirection = FieldPVCoordinates(fieldPVCoordinatesProvider.getPVCoordinates(fieldAbsoluteDate, frame),
                      FieldPVCoordinates(self.sun.getPVCoordinates(fieldAbsoluteDate, frame)))
        
        sunNormal = plusZ.crossProduct(base.getOrientation().applyTo(sunDirection))
        
        compensation = TimeStampedFieldAngularCoordinates(fieldAbsoluteDate, plusZ, sunNormal.normalize(),
                                                  plusZ, FieldPVCoordinates(field,self.phasingNormal),
                                                  1.0e-9)
        
        return FieldAttitude(frame, compensation.addOffset(base.getOrientation()))
    
    def finalize(self):
        pass
and how it is used (later on it is integrated in an AttitudeSequence):
        # attitude provider pointing towards targetSc
        targetSc_pointing = CelestialBodyPointed(FramesFactory.getEME2000(), targetSc.prop,
                                    Vector3D.PLUS_K,# phasing dir in EME2000
                                    Vector3D.PLUS_K, # SC vector to be pointed
                                    Vector3D.PLUS_I) # phasing dir in SC frame
        
        # with yaw steering (not working currently using CelestialBodyPointed as underlying provider)
        sat_r_pointed_YS = YawSteering2(FramesFactory.getEME2000(), targetSc_pointing,
                                       CelestialBodyFactory.getSun(), Vector3D.PLUS_I)
the runtime error occurs during propagation (I’m using NumericalPropagator):
<super: <class 'JavaError'>, <JavaError object>>
    Java stacktrace:
java.lang.RuntimeException: AttributeError
	at org.orekit.attitudes.PythonAttitudeProviderModifier.getAttitude(Native Method)
	at org.orekit.attitudes.AttitudesSequence.getAttitude(AttitudesSequence.java:292)
	at
I checked it was properly working with the ‘normal’ YawSteering and using a GroundPointing-type underlying provider (such as BodyCenterPointing).