jPapaBench: Mission Service with Periodic Tasks and Internal Receivers

This article introduce a real-time mission service implementation (AutopilotService) that contains a serials of periodic tasks and an internal receiver for, respectively, autopilot control and radio communication. Fig.1 shows the static declaration of AutopilotService in RTDroid application manifest, and its sub-constructs. Fig.2 lists its corresponding implementation.

<service android:name="papabench.android.AutopilotService">
  <rtdroid:priority scheduler="FIFO" priority="90"/>
  <rtdroid:scopeSizes total="50M" persistent="40M" release="10M"/>
  <!-- Autopilot Tasks -->
  <rtdroid:periodic-task instance-id="Navigation">
    <rtdroid:periodic>
  <period ms="250" ns="0"/>
  </rtdroid:periodic>
  <rtdroid:priority scheduler="FIFO" priority="32"/>
  <rtdroid:subScopeSize release="3M" />
  </rtdroid:periodic-task>

  <rtdroid:periodic-task instance-id="AltitudeControl">
  <rtdroid:periodic>
    <period ms="250" ns="0"/>
  </rtdroid:periodic>
  <rtdroid:priority scheduler="FIFO" priority="31"/>
  <rtdroid:subScopeSize release="3M" />
  </rtdroid:periodic-task>
  ...
  <rtdroid:periodic-task instance-id="SimulatorIRTask">
    <rtdroid:periodic>
      <period ms="50" ns="0"/>
    </rtdroid:periodic>
    <rtdroid:priority scheduler="FIFO" priority="27"/>
    <rtdroid:subScopeSize release="3M" />
  </rtdroid:periodic-task>

  <!-- Sub receiver for Flight Simulation -->
  <receiver android:name="SimulatorFlightModelTask">
    <rtdroid:priority scheduler="FIFO" priority="26"/>
    <intent-filter rtdroid:realtime="true" rtdroid:concurrentCount="2"
            rtdroid:role="subscriber">
      <action android:name="SimulatorFlightModelTask"/>
    </intent-filter>
    <rtdroid:subScopeSize release="3M" />
  </receiver>

  <intent-filter rtdroid:realtime="true" rtdroid:concurrentCount="2"
            rtdroid:role="observer">
    <action android:name="AutopilotStatusRcvr"/>
  </intent-filter>
</service>
Fig.1 Autopilot Service Declaration
public class AutopilotService extends RealtimeService{
    private AutopilotModule autopilotModule;
    private FlightModel flightModel;
    private PJPeriodicTask[] autopilotTasks;
    private static final int AUTOPILOT_TASKS_COUNT = 7;
    private PJPeriodicTask[] simulatorTasks;
    private static final int SIMULATOR_TASKS_COUNT = 3;
    
    public final RealtimeReceiver simServoRcvr = new RealtimeReceiver() {
        RadioCommands radioCommands = new RadioCommandsImpl();
        @Override
        public void onReceive(Context context, Intent intent) {
            RealtimeIntent rtIntent = (RealtimeIntent)intent;
            if( rtIntent.getInts()[4] == 1){
                radioCommands.setPitch(rtIntent.getInts()[0]);
                radioCommands.setRoll(rtIntent.getInts()[1]);
                radioCommands.setThrottle(rtIntent.getInts()[2]);
                radioCommands.setGain1(rtIntent.getInts()[3]);
                flightModel.processCommands(radioCommands);
            }
        }
    };
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("AutoPilotService onStartCommand");
        final RealtimeService service = this;
        executeInPersistent(new Runnable() {
            @Override
            public void run() {
                autopilotModule = PapaBenchPJFactory.createAutopilotModule();
                autopilotModule.setService(service);
                flightModel = PapaBenchPJFactory.createSimulator();
                //set flight plan
                autopilotModule.getNavigator()
                    .setFlightPlan(new RoundTripFlightPlan());
                autopilotModule.init();
                flightModel.init();
                createAutopilotTasks();
                createSimulatorTasks();
            }
        });
        registerComponents();
        return 0;
    }

    private void registerComponents() {
        registerRealtimeReceiver("SimulatorFlightModelTask", simServoRcvr);
        for (int i = 0; i < simulatorTasks.length; i++) {
        registerPeriodicTask(simulatorTasks[i].getTaskName(), simulatorTasks[i]);
        }
        for (int i = 0; i < autopilotTasks.length; i++) {
        registerPeriodicTask(autopilotTasks[i].getTaskName(), autopilotTasks[i]);
        }
    }

    private void createAutopilotTasks() {
        autopilotTasks = new PJPeriodicTask[AUTOPILOT_TASKS_COUNT];
        autopilotTasks[0] = new PJPeriodicTask(
         new AltitudeControlTaskHandler(autopilotModule),
         PapaBenchAutopilotConf.AltitudeControlTaskConf.NAME);
        autopilotTasks[1] = new PJPeriodicTask(
         new ClimbControlTaskHandler(autopilotModule),
         PapaBenchAutopilotConf.ClimbControlTaskConf.NAME);
        autopilotTasks[2] = new PJPeriodicTask(
         new LinkFBWSendTaskHandler(autopilotModule),
         PapaBenchAutopilotConf.LinkFBWSendTaskConf.NAME);
        autopilotTasks[3] = new PJPeriodicTask(
         new NavigationTaskHandler(autopilotModule),
         PapaBenchAutopilotConf.NavigationTaskConf.NAME);
        autopilotTasks[4] = new PJPeriodicTask(
         new RadioControlTaskHandler(autopilotModule),
         PapaBenchAutopilotConf.RadioControlTaskConf.NAME);
        autopilotTasks[5] = new PJPeriodicTask(
          new ReportingTaskHandler(autopilotModule),
          PapaBenchAutopilotConf.ReportingTaskConf.NAME);
        // StabilizationTask allocates messages which are sent to FBW unit
        autopilotTasks[6] = new PJPeriodicTask(
          new StabilizationTaskHandler(autopilotModule, this),
          PapaBenchAutopilotConf.StabilizationTaskConf.NAME);
    }

    public void createSimulatorTasks() {
        simulatorTasks = new PJPeriodicTask[SIMULATOR_TASKS_COUNT];
        simulatorTasks[0] = new PJPeriodicTask(
          new SimulatorFlightModelTaskHandler(flightModel, autopilotModule, null),
          PapaBenchSimulatorConf.SimulatorFlightModelTaskConf.NAME);
        simulatorTasks[1] = new PJPeriodicTask(
          new SimulatorGPSTaskHandler(flightModel, autopilotModule),
          PapaBenchSimulatorConf.SimulatorGPSTaskConf.NAME);
        simulatorTasks[2] = new PJPeriodicTask(
          new SimulatorIRTaskHandler(flightModel, autopilotModule),
          PapaBenchSimulatorConf.SimulatorIRTaskConf.NAME);
    }
}
Fig.2 Autopilot Service