Exemple #1
0
void OnTerminate() {
	try {
		std::rethrow_exception(std::current_exception());
		systemLogStream.Event(std::string("Terminate called, shutting down services."));
	}
	catch (Exception& ex) {
		systemLogStream.Event(std::string("Terminate called, shutting down services.") + ex.what() + "\n" + ex.StackTraceStr());
	}
	catch (std::exception& ex) {
		systemLogStream.Event(std::string("Terminate called, shutting down services.") + ex.what());
	}
	logger.Flush();
	logger.OpenStream(nullptr);
	logFile.close();
	int ans = MessageBoxA(NULL, "Open logs?", "Unhandled exception", MB_YESNO);
	if (ans == IDYES) {
		system(logFilePath.string().c_str());
	}

	std::abort();
}
Exemple #2
0
void nvlog(char *data, int size) {
  nvlogger.Log((unsigned char *)data, size);
  nvlogger.Flush();
}
Exemple #3
0
void nvlog_flush() {
  nvlogger.Flush();
}
Exemple #4
0
int main(int argc, char* argv[]) {
	// Initialize logger
	logFile.open("engine_test.log");
	logFilePath = std::experimental::filesystem::current_path();
	logFilePath /= "engine_test.log";
	cout << "Log files can be found at:\n   ";
	cout << "   " << logFilePath << endl;

	if (logFile.is_open()) {
		logger.OpenStream(&logFile);
	}
	else {
		logger.OpenStream(&std::cout);
	}

	// Set exception terminate handler
	std::set_terminate(OnTerminate);


	// Create the window itself
	Window window;
	window.SetTitle("QC Simulator");
	window.SetSize({ 960, 640 });


	// Create GraphicsEngine
	systemLogStream.Event("Initializing Graphics Engine...");

	std::unique_ptr<IGxapiManager> gxapiMgr;
	std::unique_ptr<IGraphicsApi, ReportDeleter> gxapi;
	std::unique_ptr<GraphicsEngine> engine;
	std::unique_ptr<QCWorld> qcWorld;
	std::unique_ptr<InputHandler> inputHandler;
	std::unique_ptr<Input> joyInput;
	std::unique_ptr<Input> keyboardInput;

	try {
		// Create manager
		systemLogStream.Event("Creating GxApi Manager...");
		gxapiMgr.reset(new GxapiManager());
		auto adapters = gxapiMgr->EnumerateAdapters();
		std::string cardList;
		for (auto adapter : adapters) {
			cardList += "\n";
			cardList += adapter.name;
		}
		systemLogStream.Event("Available graphics cards:" + cardList);


		// Create graphics api
		int device = 0;
		if (argc == 3 && argv[1] == std::string("--device") && isdigit(argv[2][0])) {
			device = argv[2][0] - '0'; // works for single digits, good enough, lol
		}
		systemLogStream.Event("Creating GraphicsApi...");
		gxapi.reset(gxapiMgr->CreateGraphicsApi(adapters[device].adapterId));
		std::stringstream ss;
		ss << "Using graphics card: " << adapters[device].name;
		systemLogStream.Event(ss.str());


		// Create graphics engine
		systemLogStream.Event("Creating Graphics Engine...");

		GraphicsEngineDesc desc;
		desc.fullScreen = false;
		desc.graphicsApi = gxapi.get();
		desc.gxapiManager = gxapiMgr.get();
		desc.width = window.GetClientSize().x;
		desc.height = window.GetClientSize().y;
		desc.targetWindow = window.GetNativeHandle();
		desc.logger = &logger;

		engine.reset(new GraphicsEngine(desc));

		// Load graphics pipeline
		std::string pipelineFileName = SelectPipeline(gxapi.get());
		std::string exeDir = System::GetExecutableDir();
		std::ifstream pipelineFile(INL_PIPELINE_DIRECTORY "\\" + pipelineFileName);
		if (!pipelineFile.is_open()) {
			throw FileNotFoundException("Failed to open pipeline JSON.");
		}
		std::string pipelineDesc((std::istreambuf_iterator<char>(pipelineFile)), std::istreambuf_iterator<char>());
		engine->LoadPipeline(pipelineDesc);


		// Create mini world
		qcWorld.reset(new QCWorld(engine.get()));
		

		// Create input handling
		inputHandler = std::make_unique<InputHandler>(qcWorld.get());

		window.OnResize += Delegate<void(ResizeEvent)>{ &InputHandler::OnResize, inputHandler.get() };

		auto joysticks = Input::GetDeviceList(eInputSourceType::JOYSTICK);
		if (!joysticks.empty()) {
			joyInput = std::make_unique<Input>(joysticks.front().id);
			joyInput->SetQueueMode(eInputQueueMode::QUEUED);
			joyInput->OnJoystickMove += Delegate<void(JoystickMoveEvent)>{ &InputHandler::OnJoystickMove, inputHandler.get() };
		}
		auto keyboards = Input::GetDeviceList(eInputSourceType::KEYBOARD);
		if (!keyboards.empty()) {
			keyboardInput = std::make_unique<Input>(keyboards.front().id);
			keyboardInput->SetQueueMode(eInputQueueMode::QUEUED);
			keyboardInput->OnKeyboard += Delegate<void(KeyboardEvent)>{ &InputHandler::OnKey, inputHandler.get() };
		}

		window.OnResize += [&engine, &qcWorld](ResizeEvent evt) {
			engine->SetScreenSize(evt.clientSize.x, evt.clientSize.y);
			qcWorld->ScreenSizeChanged(evt.clientSize.x, evt.clientSize.y);
		};

		logger.Flush();
	}
	catch (Exception& ex) {
		errorMessage = std::string("Error creating GraphicsEngine: ") + ex.what() + "\n" + ex.StackTraceStr();
		systemLogStream.Event(errorMessage);
		logger.Flush();
	}
	catch (std::exception& ex) {
		errorMessage = std::string("Error creating GraphicsEngine: ") + ex.what();
		systemLogStream.Event(errorMessage);
		logger.Flush();
	}

	if (!qcWorld) {
		return 0;
	}


	// Main rendering loop
	Timer timer;
	timer.Start();
	double frameTime = 0.05, frameRateUpdate = 0;
	std::vector<double> frameTimeHistory;
	float avgFps = 0;

	auto CaptionHandler = [&window](Vec2i cursorPos) {
		Vec2i size = window.GetSize();
		RectI rc;
		rc.top = 5;
		rc.bottom = 50;
		rc.right = size.x - 5;
		rc.left = size.x - 50;
		if (rc.IsPointInside(cursorPos))
			return eWindowCaptionButton::CLOSE;
		rc.Move({ -50, 0 });
		if (rc.IsPointInside(cursorPos))
			return eWindowCaptionButton::MAXIMIZE;
		rc.Move({ -50, 0 });
		if (rc.IsPointInside(cursorPos))
			return eWindowCaptionButton::MINIMIZE;
		if (cursorPos.y < 55) {
			return eWindowCaptionButton::BAR;
		}
		return eWindowCaptionButton::NONE;
	};
	//window.SetBorderless(true);
	//window.SetCaptionButtonHandler(CaptionHandler);

	while (!window.IsClosed()) {
		inputHandler->SetFocused(window.IsFocused());
		window.CallEvents();
		if (joyInput) {
			joyInput->CallEvents();
		}
		if (keyboardInput) {
			keyboardInput->CallEvents();
		}

		try {
			// Update world
			qcWorld->UpdateWorld(frameTime);
			qcWorld->RenderWorld(frameTime);

			// Calculate elapsed time for frame.
			frameTime = timer.Elapsed();
			timer.Reset();

			// Calculate average framerate
			frameRateUpdate += frameTime;
			if (frameRateUpdate > 0.5) {
				frameRateUpdate = 0;

				double avgFrameTime = 0.0;
				for (auto v : frameTimeHistory) {
					avgFrameTime += v;
				}
				avgFrameTime /= frameTimeHistory.size();
				avgFps = 1 / avgFrameTime;

				frameTimeHistory.clear();
			}
			frameTimeHistory.push_back(frameTime);

			// Set info text as window title
			unsigned width, height;
			engine->GetScreenSize(width, height);
			std::string title = "Graphics Engine Test | " + std::to_string(width) + "x" + std::to_string(height) + " | FPS=" + std::to_string((int)avgFps);
			window.SetTitle(title);
		}
		catch (Exception& ex) {
			std::stringstream trace;
			trace << "Graphics engine error:" << ex.what() << "\n";
			ex.PrintStackTrace(trace);
			systemLogStream.Event(trace.str());
			PostQuitMessage(0);
		}
		catch (std::exception& ex) {
			systemLogStream.Event(std::string("Graphics engine error: ") + ex.what());
			logger.Flush();
			PostQuitMessage(0);
		}
	}

	cout << "Shutting down." << endl;
	return 0;
}
Exemple #5
0
int main(int argc,char* argv[])
{
   //Set the precision of the data output to the terminal
   std::cout.precision(10);

   //A command line handling object
   CommandLine* cl=NULL;
   //Create a logger to output the data to terminal
   Logger log;

   //A stringstream object to store output information in
   std::stringstream strout;

   //Specim navigation filename
   std::string strSpecimNavFile="";
   //Output filename to write results to
   std::string strOutputFile="";
   //Level-1 data file name to read data properties from
   std::string strLevel1File="";
   //Post-processed nav file name 
   std::string strPostProcNavFile="";
   //Pointer to a NavigationInterpolator
   NavigationInterpolator* interpolator=NULL;
   //Pointer to a boresight onject
   Boresight* boresight=NULL;
   //Pointer to a lever arm object
   Leverarm* leverarm=NULL;
   //String to hold interpolation choice
   std::string strinterpmethod="";
   //Value to hold user specified time to use as first scan line time
   //double usersynctime=-1;

   //Scan offset time
   double scantimeoffset=0;
   //Position-Attitude time offset
   double posattoffset=0;
   //Smoothing filter kernel size
   unsigned int smoothkernelsize=0;

   //Shall we write out the navigation quality flags
   bool WRITE_QUALITY=false;
   std::string strOutputFlagFile;

   //String to contain info for output hdr file
   std::string info="";

   //Get exe name without the path
   std::string niceexename=std::string(argv[0]);
   niceexename=niceexename.substr(niceexename.find_last_of("/\\")+1);

   //Output a "nice" header
   Logger::FormattedInformation(niceexename,VERSION,DESCRIPTION);

   try
   {
      //----------------------------------------------------------------------------
      //Create the command line object
      //----------------------------------------------------------------------------
      cl=new CommandLine(argv,argc);

      //----------------------------------------------------------------------------
      //Check if anything went wrong (most likely an exception will have been thrown but lets be safe)
      //----------------------------------------------------------------------------
      if(cl->IsGood()==false)
      {
         throw "An error has occurred with the command line\n"; //throw exception that an error has occurred
      }    

      //----------------------------------------------------------------------
      // Get some information about the system running the program and log it
      //----------------------------------------------------------------------
      ComputerInfo cinfo;
      Logger::Log(cinfo.GetOutput());

      //----------------------------------------------------------------------------
      //check the command line options given against the list of available options in the software
      //----------------------------------------------------------------------------
      std::string badoptions;
      int retval=cl->CheckAvailableOptions(availableopts,number_of_possible_options,&badoptions); 
      if(retval<0)
      {
         //Options are on commnd line that are not available in this software
         strout<<"There are "<<(-retval)<<" unrecognised options on command line: "<<badoptions<<std::endl;
         throw CommandLine::CommandLineException(strout.str());
      }

      Logger::Log("Command line used to run: "+cl->ReturnCLAsString());

      //----------------------------------------------------------------------------
      // Go through each possible option in turn and set up the required data / response
      //----------------------------------------------------------------------------
      if(cl->OnCommandLine("-help"))
      {
         log.Add(cl->ProgramUsage(number_of_possible_options,availableopts,optsdescription));
         log.Flush();
         throw "";
      }
   
      //-------------------------------------------------------------------
      // Is the Specim .nav file on the command line (IT MUST BE PRESENT)
      //-------------------------------------------------------------------
      if((cl->OnCommandLine("-nav"))&&(!cl->OnCommandLine("-nonav")))
      {
         //Check that an argument follows the nav option - and get it if it exists
         if(cl->GetArg("-nav").compare(optiononly)!=0)
         {
            strSpecimNavFile=cl->GetArg("-nav");
            log.Add("Will use Specim Navigation file: "+strSpecimNavFile);
         }
         else
            throw CommandLine::CommandLineException("Argument -nav must immediately precede the Specim .nav filename.\n");
      }
      else if((!cl->OnCommandLine("-nav"))&&(cl->OnCommandLine("-nonav")))
      {
         //Throw an exception
         //throw CommandLine::CommandLineException("Argument -nav [Specim navigation file] must be present on the command line.\n");  
         if(cl->GetArg("-nonav").compare(optiononly)!=0)
         {
            throw CommandLine::CommandLineException("Option -nonav does not take any arguments.\n");
         }
         else
            strSpecimNavFile="NULL";
      }
      else
      {
         //Throw an exception
         throw CommandLine::CommandLineException("Argument -nav [Specim navigation file] or -nonav must be present on the command line.\n");  
      }

      //-------------------------------------------------------------------
      // Is the output filename on the command line (IT MUST BE PRESENT)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-output"))
      {
         //Check that an argument follows the output option - and get it if it exists
         if(cl->GetArg("-output").compare(optiononly)!=0)
         {
            strOutputFile=cl->GetArg("-output");
            log.Add("Will write to output BIL file: "+strOutputFile);
         }
         else
            throw CommandLine::CommandLineException("Argument -output must immediately precede the output filename.\n");
      }
      else
      {
         //Throw an exception
         throw CommandLine::CommandLineException("Argument -output [the file to write to] must be present on the command line.\n");  
      }

      //-------------------------------------------------------------------
      // Is the level 1 filename on the command line (IT MUST BE PRESENT)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-lev1"))
      {
         //Check that an argument follows the lev1 option - and get it if it exists
         if(cl->GetArg("-lev1").compare(optiononly)!=0)
         {
            strLevel1File=cl->GetArg("-lev1");
            log.Add("Will read the sensor data properties from the level-1 file: "+strLevel1File);
         }
         else
            throw CommandLine::CommandLineException("Argument -lev1 must immediately precede the level-1 filename.\n");
      }
      else
      {
         //Throw an exception
         throw CommandLine::CommandLineException("Argument -lev1 [the level-1 hyperspectral file] must be present on the command line.\n");  
      }

      //-------------------------------------------------------------------
      // Is the lever arm on the command line (IT MUST BE PRESENT)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-leverarm"))
      {
         //Check that 3 arguments follow the leverarm option
         if(cl->NumArgsOfOpt("-leverarm") != 3 )
            throw CommandLine::CommandLineException("Error: There should be 3 arguments following the -leverarm option.\n");
         
         //Get the 3 arguments into the leverarm parameters
         double lax=StringToDouble(cl->GetArg("-leverarm",0));
         double lay=StringToDouble(cl->GetArg("-leverarm",1));
         double laz=StringToDouble(cl->GetArg("-leverarm",2));

         log.Add("Will apply lever arm corrections of (X,Y,Z): "+ToString(lax)+" "+ToString(lay)+" "+ToString(laz));
         leverarm=new Leverarm(lax,lay,laz);

      }
      else
      {
         throw CommandLine::CommandLineException("Argument -leverarm [the sensor lever arm values] must be present on the command line.\n");  
      }

      //-------------------------------------------------------------------
      // Is the boresight on the command line (IT MUST BE PRESENT)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-boresight"))
      {
         //Check that 3 arguments follow the boresight option
         if(cl->NumArgsOfOpt("-boresight") != 3 )
            throw CommandLine::CommandLineException("Error: There should be 3 arguments following the -boresight option.\n");
         
         //Get the 3 arguments into the boresight parameters
         double p=StringToDouble(cl->GetArg("-boresight",0));
         double r=StringToDouble(cl->GetArg("-boresight",1));
         double h=StringToDouble(cl->GetArg("-boresight",2));
         log.Add("Will apply boresight corrections of (R,P,H): "+ToString(r)+" "+ToString(p)+" "+ToString(h));
         boresight=new Boresight(r,p,h);
      }
      else
      {
         throw CommandLine::CommandLineException("Argument -boresight [the sensor boresight values] must be present on the command line.\n");  
      }

      //-------------------------------------------------------------------
      // Is the post-processed nav file on the command line (ITS OPTIONAL)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-procnav"))
      {
         //Check that an argument follows the procnav option - and get it if it exists
         if(cl->GetArg("-procnav").compare(optiononly)!=0)
         {
            strPostProcNavFile=cl->GetArg("-procnav");
            log.Add("Will read navigation data from SBET/SOL file: "+strPostProcNavFile);
            info=info+";Navigation from post-processed SBET/SOL file. \n";
         }
         else
            throw CommandLine::CommandLineException("Argument -procnav must immediately precede the SBET/SOL filename.\n");
      }
      else
      {            
         log.Add("No SBET/SOL file has been given, therefore will read real-time navigation data from Specim .nav file: "+strSpecimNavFile);         
         info=info+";Navigation from real-time Specim .nav file. \n";
      }

      //-------------------------------------------------------------------
      // Is the ScanTime Offset on the command line (ITS OPTIONAL)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-scantimeoffset"))
      {
         //Check that an argument follows the scantimeoffset option - and get it if it exists
         if(cl->GetArg("-scantimeoffset").compare(optiononly)!=0)
         {
            std::string cl_tmp=cl->GetArg("-scantimeoffset");
            scantimeoffset=StringToDouble(cl_tmp.c_str());
            if(errno==ERANGE)
            {
               throw "An error has occurred in the conversion of scan time offset in CommandLine of main().";
            }
            log.Add("Will apply a user-specified scan offset of: "+cl_tmp);
         }
         else
            throw CommandLine::CommandLineException("Argument -scantimeoffset must immediately precede the scan time offset value.");
      }
      else
      {
         log.Add("No user-supplied scan time offset to be applied.");
      }
      
      //-------------------------------------------------------------------
      // Is smoothing requested on the command line (ITS OPTIONAL)
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-smooth"))
      {
         //Check that an argument follows the smooth option - and get it if it exists
         if(cl->GetArg("-smooth").compare(optiononly)!=0)
         {
            std::string cl_tmp=cl->GetArg("-smooth");
            smoothkernelsize=StringToUINT(cl_tmp);
            if(errno==ERANGE)
            {
               throw "An error has occurred in the conversion of smooth kernel size in CommandLine of main().";
            }
            if(smoothkernelsize%2==0)
               throw "Smoothing kernel size must be an odd number.";
               
            log.Add("Will apply a smoothing of kernel size: "+cl_tmp);
         }
         else
            throw CommandLine::CommandLineException("Argument -smooth must immediately precede the smoothing kernel size.");
      }
      else
      {
         log.Add("No smoothing of navigation data to be applied.");
      }

      //-------------------------------------------------------------------
      // What method of interpolation is to be used
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-interp"))
      {
         //Check that an argument follows the interp option - and get it if it exists
         if(cl->GetArg("-interp").compare(optiononly)!=0)
         {
            std::string cl_tmp=cl->GetArg("-interp");
            strinterpmethod=cl_tmp;

            log.Add("Will use the interpolation method: "+cl_tmp);
         }
         else
            throw CommandLine::CommandLineException("Argument -interp must immediately precede the interpolation method keyword.");
      }
      else
      {
         strinterpmethod="Linear";
         log.Add("No interpolation method of navigation data supplied, will use Linear.");
      }

      //-------------------------------------------------------------------
      // Add a Position-Attitude time offset 
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-posattoff"))
      {
         //Check that an argument follows the posattoff option - and get it if it exists
         if(cl->GetArg("-posattoff").compare(optiononly)!=0)
         {
            std::string cl_tmp=cl->GetArg("-posattoff");
            posattoffset=StringToDouble(cl_tmp.c_str());
            if(errno==ERANGE)
            {
               throw "An error has occurred in the conversion of position attitude time offset in CommandLine of main().";
            }
            log.Add("Will use the given position attitude offset: "+cl_tmp);
         }
         else
            throw CommandLine::CommandLineException("Argument -posattoff must immediately precede the position/attitude shift value.");
      }
      else
      {
         posattoffset=0; 
         log.Add("Will not use a position-attitude offset.");
      }


      //-------------------------------------------------------------------
      // Output the quality flags
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-qualityfile"))
      {
         //Check that an argument follows the qualityfile option - and get it if it exists
         if(cl->GetArg("-qualityfile").compare(optiononly)!=0)
         {
            strOutputFlagFile=cl->GetArg("-qualityfile");
            log.Add("Will write quality flags to: "+strOutputFlagFile);
         }
         else
            throw CommandLine::CommandLineException("Argument -qualityfile must immediately precede the output quality flag filename.\n");

         //Set the bool to true
         WRITE_QUALITY=true;
      }
      else
      {
         WRITE_QUALITY=false;
      }

      //-------------------------------------------------------------------
      // Force processing of aplnav
      //-------------------------------------------------------------------
      if(cl->OnCommandLine("-force"))
      {
         if(cl->GetArg("-force").compare(optiononly)!=0)
         {
            throw CommandLine::CommandLineException("Option -force does not take any arguments.\n");
         }
         else
            GLOBAL_FORCE=true;
      }
      else
      {
         GLOBAL_FORCE=false;
      }

      //-------------------------------------------------------------------
      // ENTER NEW COMMAND LINE OPTIONS HERE
      //-------------------------------------------------------------------

   }
   catch(CommandLine::CommandLineException e)
   {
      Logger::Error(std::string(e.what())+"\n"+e.info);
      delete cl;
      exit(1);
   }
   catch(std::string e)
   {
      Logger::Error(e);
      delete cl;
      exit(1);
   }
   catch(const char* e)
   {
      Logger::Error(e);
      delete cl;
      exit(1);
   }
   catch(BinaryReader::BRexception e)
   {
      Logger::Error(std::string(e.what())+"\n"+e.info);
      delete cl;
      exit(1); //exit the program
   }
   catch(std::exception &e)
   {
      Logger::Error(e.what());
      delete cl;
      exit(1);
   }

   //Flush the log
   log.Flush();
   //Output a blank line
   Logger::Log("");

   //Add some information to the header files
   info=info+";Command line used to process data: "+cl->ReturnCLAsString()+"\n";
   info=info+";boresight (P,R,H) = "+ToString(boresight->Pitch())+" "+ToString(boresight->Roll())+" "+ToString(boresight->Heading())+"\n";
   info=info+";leverarm (X,Y,Z) = "+ToString(leverarm->X())+" "+ToString(leverarm->Y())+" "+ToString(leverarm->Z())+"\n";


   try
   { 
      //-------------------------------------------------------------------
      // In this section we deal with getting per scan times
      //-------------------------------------------------------------------

      //Set up navigation syncer to get per scan line times
      NavigationSyncer syncer(strSpecimNavFile,strLevel1File);

      //Add the y start value to the output header file.
      info=info+"y start = "+ToString(syncer.GetCropTimeOffset())+"\n";

      //Get the perscan line times
      log.Add("Finding per-scan times...");
      log.Flush();
      syncer.FindScanTimes();

      //Correct the times for GPS leapseconds if from SBET/SOL file
      //This is because the times from the Specim nav file are in GPS time
      //and SBET/SOL times are in UTC. So this adds leapseconds onto the times 
      //which have been derived from the Specim data, making them relevant
      //for querying the data from the SBET/SOL file.
      //Ignore (for the moment) if from Specim Nav file - adds time on
      //to that data before writing out (see below)
      if(strPostProcNavFile!="")
         syncer.ApplyLeapSeconds();

      //Apply a user-defined time offset to the scans
      if(scantimeoffset!=0)
      {
         log.Add("\nApplying user defined timing offset...");
         log.Flush();
         syncer.ApplyTimeShift(scantimeoffset);
         info=info+";User defined scan timing offset added onto data: "+ToString(scantimeoffset)+"\n";
      }

      //-------------------------------------------------------------------
      // In this section we deal with getting per scan navigation data
      //-------------------------------------------------------------------

      //Set up an interpolator to interpolate the navigation to the scan lines
      log.Add("Creating Navigation Interpolation object...");
      log.Flush();
      if(strPostProcNavFile!="")
         interpolator=new NavigationInterpolator(strPostProcNavFile,strLevel1File);
      else
         interpolator=new NavigationInterpolator(strSpecimNavFile,strLevel1File);         

      //Assign the scan times to the interpolator - these are just 
      //pointing to the data so dont delete the syncer
      log.Add("\nSetting times to interpolation object...");
      log.Flush();
      double* scantimes=NULL;
      scantimes=syncer.PtrToTimes();
      interpolator->SetTimes(scantimes);

      //Smooth the nav data
      if(smoothkernelsize!=0)
      {
         log.Add("Smoothing the data using a triangular low-pass filter...");
         log.Flush();
         info=info+";Smoothed input navigation data using a triangular low-pass filter with kernel size: "+ToString(smoothkernelsize)+"\n";
         interpolator->SmoothNavData(Triangle,smoothkernelsize);
      }

      //Interpolate the data to the scan times
      log.Add("\nInterpolating navigation data to scan times...");
      log.Flush();
      if(strinterpmethod.compare("Linear")==0)
      {
         interpolator->Interpolate(Linear);
         if(posattoffset!=0)
            interpolator->PosAttShift(Linear,posattoffset);
      }
      else if(strinterpmethod.compare("Spline")==0)
      {
         interpolator->Interpolate(CubicSpline);
         if(posattoffset!=0)
            interpolator->PosAttShift(Linear,posattoffset);
      }
      else
         throw "Unknown interpolation method. Expected 'Linear' or 'Spline'";

      //Apply the lever arm offsets to the interpolated position data
      log.Add("Adding leverarm correction...");
      log.Flush();
      interpolator->ApplyLeverarm(leverarm);    

      //Apply the boresight offsets to the interpolated attitude data
      log.Add("Adding boresight correction...");
      log.Flush();
      interpolator->ApplyBoresight(boresight);

      //If the times are from the Specim nav file then they must be converted
      //from GPS time to UTC by adding on the leap seconds.
      if(strPostProcNavFile=="")
         syncer.ApplyLeapSeconds();
      scantimes=syncer.PtrToTimes();
      interpolator->SetTimes(scantimes);

      //Check the plausibilty of the interpolated data
      interpolator->CheckPlausibility();

      //Write out the data
      log.Add("\nWriting data out...");
      log.Flush();
      interpolator->Writer(strOutputFile,info);

      //Write out the quality flags
      if(WRITE_QUALITY==true)
      {
         interpolator->WriteFlags(strOutputFlagFile);
      }

      //delete the interpolator
      delete interpolator;

   }
   catch(std::string e)
   {
      Logger::Error(e);
      exit(1);
   }
   catch(const char* e)
   {
      Logger::Error(e);
      exit(1);
   }
   catch(BinaryReader::BRexception e)
   {
      Logger::Error(std::string(e.what())+"\n"+e.info);
      exit(1); 
   }
   catch(BILWriter::BILexception e)
   {
      Logger::Error(std::string(e.what())+"\n"+e.info);
      exit(1); 
   }
   catch(std::exception &e)
   {
      Logger::Error(e.what());
      exit(1);
   }

   Logger::Log("Navigation processing completed. \n \n");

   //Delete the command line object
   if(cl!=NULL)
      delete cl;
   if(boresight!=NULL)
      delete boresight;
   if(leverarm!=NULL)
      delete leverarm;
}