1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-12-04 07:38:08 +00:00

Added file_long_code_generator

For now this reads chips from an ASCII text file, which is not very
efficient.
This commit is contained in:
Cillian O'Driscoll
2016-05-23 21:54:22 +01:00
parent 672e281361
commit 17578dee30
7 changed files with 439 additions and 1 deletions

View File

@@ -34,6 +34,7 @@ set(GNSS_SPLIBS_SOURCES
gps_pcode.cc
gps_pcode_generator.cc
spirent_prs_code_generator.cc
file_long_code_generator.cc
)

View File

@@ -0,0 +1,132 @@
/*!
* \file file_long_code_generator.cc
* \brief Defines a code generator conforming to the long_code_interface that
* reads the chips from a file.
* \author Cillian O'Driscoll, 2016. cillian.odriscoll(at)gmail.com
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "file_long_code_generator.h"
#include <algorithm>
#include <glog/logging.h>
#include <iostream>
FileLongCodeGenerator::FileLongCodeGenerator( int sv, std::istream &is )
{
set_prn( sv );
initialise( is );
}
bool FileLongCodeGenerator::get_chips( uint64_t first_chip_index, unsigned int num_chips,
std::vector< short >& dest )
{
if( first_chip_index < d_first_chip_index ||
first_chip_index > d_first_chip_index + d_num_chips ||
first_chip_index + num_chips < d_first_chip_index )
{
LOG(INFO) << "Attempted to access chips outside of range. [" << first_chip_index
<< ", " << first_chip_index+num_chips << "] not in [" << d_first_chip_index
<< ", " << d_first_chip_index+d_num_chips << "]";
return false;
}
uint64_t first_chip_to_return = std::max( d_first_chip_index,
first_chip_index ) - d_first_chip_index;
uint64_t last_chip_to_return = std::min( first_chip_index + num_chips,
d_first_chip_index + d_num_chips ) - d_first_chip_index;
uint64_t num_chips_to_return = last_chip_to_return - first_chip_to_return
+ 1;
dest.resize( num_chips_to_return );
LOG(INFO) << "Getting chips: " << first_chip_to_return
<< " to " << last_chip_to_return;
std::copy( d_the_chips.begin() + first_chip_to_return,
d_the_chips.begin() + last_chip_to_return + 1,
dest.begin() );
return true;
}
void FileLongCodeGenerator::set_prn( int sv )
{
d_sv = sv;
}
uint64_t FileLongCodeGenerator::get_code_length( void ) const
{
return d_code_length;
}
void FileLongCodeGenerator::initialise( std::istream &is )
{
// go to the beginning of the stream:
is.seekg(0);
// The file format is:
// FIRST_CHIP_INDEX
// CODE_LENGTH
// CHIP_0
// CHIP_1
// ...
// CHIP_N-1
// [Blank line]
// Handy algorithm for counting lines
uint64_t numLines =
std::count(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>(), '\n');
if( numLines <= 3 )
{
LOG(ERROR) << "Invalid file format: expected at least 3 lines";
}
d_num_chips = numLines - 3; // First two lines and last blank line
d_the_chips.resize( d_num_chips );
is.seekg(0);
is >> d_first_chip_index;
is >> d_code_length;
uint64_t ii = 0;
while( is >> d_the_chips[ii++] ){};
if( ii < d_num_chips )
{
LOG(ERROR) << "Expected " << d_num_chips << " chips, only read "
<< ii;
}
}

View File

@@ -0,0 +1,67 @@
/*!
* \file file_long_code_generator.h
* \brief Defines a code generator conforming to the long_code_interface that
* reads the chips from a file.
* \author Cillian O'Driscoll, 2016. cillian.odriscoll(at)gmail.com
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_FILE_LONG_CODE_GENERATOR_H_
#define GNSS_SDR_FILE_LONG_CODE_GENERATOR_H_
#include "long_code_interface.h"
#include <istream>
class FileLongCodeGenerator : public LongCodeInterface
{
public:
FileLongCodeGenerator( int sv, std::istream &is );
bool get_chips( uint64_t first_chip_index,
unsigned int num_chips,
std::vector< short >& dest );
void set_prn( int sv );
uint64_t get_code_length( void ) const;
private:
int d_sv;
uint64_t d_first_chip_index;
uint64_t d_num_chips;
uint64_t d_code_length;
std::vector< short > d_the_chips;
void initialise( std::istream &is );
};
#endif // GNSS_SDR_PCODE_GENERATOR_H_

View File

@@ -35,6 +35,7 @@
#include "Galileo_E1.h"
#include "configuration_interface.h"
#include "spirent_prs_code_generator.h"
#include "file_long_code_generator.h"
using google::LogMessage;
@@ -112,6 +113,31 @@ GalileoE1PrsDeTracking::GalileoE1PrsDeTracking(
LOG(ERROR) << "Unable to create a SpirentPrsCodeGenerator";
}
}
else if( not code_type.compare("File") )
{
std::string code_file_name = configuration->property( role + ".prs_code_file", std::string(""));
if( code_file_name == "" )
{
LOG(ERROR) << "prs_code_file configuration property missing";
}
std::ifstream prs_code_file( code_file_name );
if( not prs_code_file.is_open() )
{
LOG(ERROR) << "Unable to open prs_code_file: " << code_file_name;
}
code_gen = boost::shared_ptr< LongCodeInterface>(
new FileLongCodeGenerator( 1, prs_code_file )
);
if( code_gen == 0 )
{
LOG(ERROR) << "Unable to create a FileLongCodeGenerator";
}
}
else
{
LOG(ERROR) << code_type << " unknown PRS code type";

View File

@@ -35,6 +35,7 @@
#include "Galileo_E1.h"
#include "configuration_interface.h"
#include "spirent_prs_code_generator.h"
#include "file_long_code_generator.h"
using google::LogMessage;
@@ -112,6 +113,31 @@ GalileoE1PrsVemlTracking::GalileoE1PrsVemlTracking(
LOG(ERROR) << "Unable to create a SpirentPrsCodeGenerator";
}
}
else if( not code_type.compare("File") )
{
std::string code_file_name = configuration->property( role + ".prs_code_file", std::string(""));
if( code_file_name == "" )
{
LOG(ERROR) << "prs_code_file configuration property missing";
}
std::ifstream prs_code_file( code_file_name );
if( not prs_code_file.is_open() )
{
LOG(ERROR) << "Unable to open prs_code_file: " << code_file_name;
}
code_gen = boost::shared_ptr< LongCodeInterface>(
new FileLongCodeGenerator( 1, prs_code_file )
);
if( code_gen == 0 )
{
LOG(ERROR) << "Unable to create a FileLongCodeGenerator";
}
}
else
{
LOG(ERROR) << code_type << " unknown PRS code type";

View File

@@ -252,7 +252,6 @@ add_executable(gnss_block_test
${CMAKE_CURRENT_SOURCE_DIR}/flowgraph/pass_through_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/gnss_block/file_output_filter_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/pcode_generation_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/spirent_prs_code_generation_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/gnss_block/gnss_block_factory_test.cc
)
if(NOT ${ENABLE_PACKAGING})
@@ -376,6 +375,8 @@ add_executable(arithmetic_test
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/code_resampler_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/subcarrier_resampler_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/accumulate_array_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/spirent_prs_code_generation_test.cc
${CMAKE_CURRENT_SOURCE_DIR}/arithmetic/file_long_code_generator_test.cc
)
if(NOT ${ENABLE_PACKAGING})
set_property(TARGET arithmetic_test PROPERTY EXCLUDE_FROM_ALL TRUE)

View File

@@ -0,0 +1,185 @@
/*!
* \file file_long_code_generation_test.cc
* \brief This file implements tests for the generation of the long codes
* whose chips are read from file
* \author Cillian O'Driscoll, 2016. cillian.odriscoll(at)gmail.com
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2016 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include <gtest/gtest.h>
#include <sstream>
#include <fstream>
#include <algorithm>
#include "file_long_code_generator.h"
const uint64_t kFirstChipInd = 204900;
const uint64_t kCodeLength = 1023000*2.5*3600*24*7;
const std::vector< short > kChipVec = { 1, 1, -1, -1, +1, -1, +1, -1, +1, +1 };
class FileLongCodeTestGen : public ::testing::Test
{
public:
FileLongCodeTestGen()
: ios("")
{
};
protected:
virtual void SetUp()
{
ios << kFirstChipInd << std::endl;
ios << kCodeLength << std::endl;
for( std::vector< short >::const_iterator it = kChipVec.begin();
it != kChipVec.end(); ++it )
{
ios << *it << std::endl;
}
ios.seekg( 0 );
}
std::stringstream ios;
};
TEST_F(FileLongCodeTestGen, CheckFileContents )
{
uint64_t firstChipIndex;
ios >> firstChipIndex;
EXPECT_EQ( kFirstChipInd, firstChipIndex );
uint64_t code_length;
ios >> code_length;
EXPECT_EQ( code_length, kCodeLength );
// Count the lines in the file:
ios.seekg( 0 );
unsigned long numLines =
std::count(std::istreambuf_iterator<char>(ios),
std::istreambuf_iterator<char>(), '\n');
EXPECT_EQ( kChipVec.size() + 2, numLines );
}
TEST_F(FileLongCodeTestGen, GetKnownBits)
{
FileLongCodeGenerator codeGen( 1, ios );
std::vector< short > theChips;
bool res = codeGen.get_chips( kFirstChipInd, kChipVec.size(), theChips );
EXPECT_TRUE( res );
EXPECT_EQ( kChipVec.size(), theChips.size() );
for( unsigned int ii = 0; ii < theChips.size(); ++ii )
{
EXPECT_EQ( kChipVec[ii], theChips[ii] ) << "Chip error at index: " << ii;
}
}
TEST_F(FileLongCodeTestGen, CantGetEarlyBits )
{
FileLongCodeGenerator codeGen( 1, ios );
std::vector< short > theChips;
bool res = codeGen.get_chips( kFirstChipInd - 1, kChipVec.size(), theChips );
EXPECT_FALSE( res );
}
TEST_F(FileLongCodeTestGen, CanGetSomeBitsAtEnd )
{
FileLongCodeGenerator codeGen( 1, ios );
std::vector< short > theChips;
bool res = codeGen.get_chips( kFirstChipInd + kChipVec.size() - 3,
kChipVec.size(), theChips );
EXPECT_TRUE( res );
EXPECT_EQ( 3, theChips.size() );
for( unsigned int ii = 0; ii < 3; ++ii )
{
EXPECT_EQ( kChipVec[ kChipVec.size()-3+ii ], theChips[ii] );
}
}
TEST_F( FileLongCodeTestGen, CantGetLateBits )
{
FileLongCodeGenerator codeGen( 1, ios );
std::vector< short > theChips;
bool res = codeGen.get_chips( kFirstChipInd + kChipVec.size(),
kChipVec.size(), theChips );
EXPECT_FALSE( res );
}
/*
TEST_F( FileLongCodeTestGen, CanWorkFromFile )
{
std::ifstream ifs( "sample_file_long_code.txt" );
ASSERT_TRUE( ifs.is_open() );
FileLongCodeGenerator codeGen( 1, ifs );
EXPECT_EQ( 1546776000000, codeGen.get_code_length() );
uint64_t first_chip_index = 0;
ifs.clear();
ifs.seekg( 0 );
ifs >> first_chip_index;
EXPECT_EQ( 564426801213, first_chip_index );
std::vector< short > the_chips;
bool res = codeGen.get_chips( first_chip_index, 10, the_chips );
EXPECT_TRUE( res );
EXPECT_EQ( 10, the_chips.size() );
}
*/