void CtrlrPanelProcessor::processBlock(MidiBuffer &midiMessages, MidiBuffer &leftoverBuffer)
{	
	if (owner.getMidiOptionBool(panelMidiInputFromHostCompare))
	{
		owner.getMIDIInputThread().handleMIDIFromHost(midiMessages);
	}

	MidiBuffer::Iterator i(midiMessages);
	MidiMessage m;
	int time;

	while (i.getNextEvent(m,time))
	{		
		_MIN("VST INPUT", m);

		if (owner.getMidiOptionBool(panelMidiThruH2D) == true)
		{
			if (owner.getMidiOptionBool(panelMidiThruH2DChannelize))
			{
				m.setChannel (owner.getMidiChannel(panelMidiOutputChannelDevice));				
			}

			owner.sendMidi(m);
		}			

		if (owner.getMidiOptionBool(panelMidiThruH2H) == true)
		{
			if (owner.getMidiOptionBool(panelMidiThruH2HChannelize))
			{
				m.setChannel (owner.getMidiChannel(panelMidiOutputChannelHost));
			}

			leftoverBuffer.addEvent (m, m.getTimeStamp());
		}
	}
}
Example #2
0
int ReadH264VideoHeader( H264_VIDEO *pH264Video, const unsigned char* pData, int Size )
{
	const unsigned char* p;
	unsigned char rbsp[256*2];
	int zero_bytes;
	BITS_I bits;
	zero_bytes  = 0;
	p = pData;

	bits.error_flag = 0;
	
	while ( 1 )
	{
		//start code prefix search
		while ( p < pData+Size-1 )
		{
			if ( *p == 0 ) 
				zero_bytes++;
			if ( zero_bytes >= 3 && *p )
			{
				if ( *p != 1 && *p != 3 )
				{
					//illeag byte codes in H.264
					if ( pH264Video->guessH264 > -200 ) pH264Video->guessH264 -= 20; //not H.264 stream
					return 0;
				} else
				if ( *p == 1 ) 
				{
					if ( *(p+1) & 0x80 )  //forbidden bits
					{
						if ( pH264Video->guessH264 > -200 )  pH264Video->guessH264 -= 20; //not H.264 stream
						return 0;
					} else
					{
						p++;
						zero_bytes = 0;
						break;                        //found HAL header
					}
				}
			}
			if ( *p ) zero_bytes = 0;
			p++;
		}

		if ( p < pData+Size-1 )
		{
			int nal_ref_idc, nal_unit_type;
			int bit_num;
			nal_ref_idc = *p>>5;
			nal_unit_type = *p&0x1F;
			p++;

			//static_type[nal_unit_type]++;
			if ( nal_unit_type == NAL_SPS )
			{
				int bytes = ( Size-(int)(p-pData) < (int)sizeof(rbsp) ) ? Size-(int)(p-pData) : (int)sizeof(rbsp) ;
				bytes = NAL2RBSP( (unsigned char*)p, (unsigned char*)rbsp, bytes );
				p += bytes;
				if ( bytes < 4 )
					return 0;  //too little data to parse information

				pH264Video->profile = rbsp[0]; 
				pH264Video->constraint_set0 = rbsp[1] & 0x80 ?  1:0;
				pH264Video->constraint_set1 = rbsp[1] & 0x40 ?  1:0;
				pH264Video->constraint_set2 = rbsp[1] & 0x20 ?  1:0;
				pH264Video->level = rbsp[2];

				if ( ( rbsp[1] & 0x1f ) )
				{
					if ( pH264Video->guessH264 > -200 )  pH264Video->guessH264 -= 20; //not H.264 stream
					return 0;
				}
				
				bits.buffer = rbsp;
				bits.bits_offset = 24;
				bits.total_bits = bytes * 8 - 24;
				
				pH264Video->sps_id = UE( &bits, &bit_num  );
				if ( bit_num > 0 )
				{
					bits.bits_offset += bit_num;
					bits.total_bits  -= bit_num;
				} else
				{
					if ( pH264Video->guessH264 > -200 ) pH264Video->guessH264 -= 10; 
					return 0;
				}
				
				if ( pH264Video->guessH264 < 200 )	pH264Video->guessH264 += 20;

				////////////////////////////////////////////////////////////

				if(( pH264Video->profile == 100 ) ||                                                                  
					(pH264Video->profile == 110 ) ||                                                                       
					(pH264Video->profile ==122 )  ||                                                                       
					(pH264Video->profile ==144 ))                                                                      
				{                                                                                                        
				     // ue("SPS: chroma_format_idc")                                                                             
					int chroma_format_idc  = ReadUE( &bits );
					 // Residue Color Transform                                                                             
					if( chroma_format_idc == 3 ) 
					{	
						ReadBitsU( &bits, 1 ); //int residue_transform_flag = ReadBitsU( &bits, 1 );
					}
					{        
						int seq_scaling_matrix_present_flag;
						ReadUE( &bits );  //int bit_depth_luma_minus8   = ReadUE( &bits );
						ReadUE( &bits );  //int bit_depth_chroma_minus8 = ReadUE( &bits );  
						ReadBitsU( &bits, 1 );  //int lossless_qpprime_flag   = ReadBitsU( &bits, 1 );
						seq_scaling_matrix_present_flag  = ReadBitsU( &bits, 1 );
						if( seq_scaling_matrix_present_flag )           
						{   int i;                                                                                      
							for(i=0; i<8; i++)         
							{                                                                                       
								int seq_scaling_list_present_flag   = ReadBitsU( &bits, 1 );
								if( seq_scaling_list_present_flag )                                   
								{      
									if(i<6)                             
										skip_scaling_List( 16, &bits );              
									else                          
										skip_scaling_List( 64, &bits );    
								}                 
							}                                                                                       
						}                                                                                 
					}  
				}
				{                         
					int pic_order_cnt_type;
					ReadUE( &bits ); //int log2_max_frame_num_minus4              = ReadUE( &bits );
					pic_order_cnt_type  = ReadUE( &bits );
				                                                                                                                                                                                        
					if ( pic_order_cnt_type == 0) 
					{
						ReadUE( &bits );; //int log2_max_pic_order_cnt_lsb_minus4 = ReadUE( &bits );
					}
					else if ( pic_order_cnt_type == 1 )                                                                       
					{        
						int i;
						int num_ref_frames_in_pic_order_cnt_cycle;
						ReadBitsU( &bits, 1 );//int delta_pic_order_always_zero_flag      = ReadBitsU( &bits, 1 );
						ReadSE( &bits ); //int offset_for_non_ref_pic                = ReadSE( &bits );
						ReadSE( &bits ); //int offset_for_top_to_bottom_field        = ReadSE( &bits );
						num_ref_frames_in_pic_order_cnt_cycle = ReadUE( &bits );
						for( i=0; i<num_ref_frames_in_pic_order_cnt_cycle; i++) 
						{
							ReadSE( &bits ); //int offset_for_ref_frame          = ReadSE( &bits );
						}
					} 
				}
				{
					int pic_width_in_mbs_minus1;
					int pic_height_in_map_units_minus1;
					int frame_mbs_only_flag;
					int frame_cropping_flag, frame_cropping_rect_right_offset=0, frame_cropping_rect_bottom_offset=0;

					ReadUE( &bits ); //int num_ref_frames                        = ReadUE( &bits );
					ReadBitsU( &bits, 1 ); //int gaps_in_frame_num_value_allowed_flag  = ReadBitsU( &bits, 1 ); 
					pic_width_in_mbs_minus1               = ReadUE( &bits );
					pic_height_in_map_units_minus1        = ReadUE( &bits );
					frame_mbs_only_flag                   = ReadBitsU( &bits, 1 ); 
					pH264Video->progressive = 0;
					if (!frame_mbs_only_flag)                                                                     
					{                                                                           
						ReadBitsU( &bits, 1 );  //int mb_adaptive_frame_field_flag        = ReadBitsU( &bits, 1 ); 
						pH264Video->progressive = 1;
					}
					pH264Video->width = (pic_width_in_mbs_minus1+1) * 16;
					pH264Video->height = (pic_height_in_map_units_minus1+1) * (2-frame_mbs_only_flag) * 16;

					if ( ( pH264Video->width < 48 || pH264Video->height < 32 ) || /* rule out too small picture 48x32 */
						 ( pH264Video->width * 3 < pH264Video->height * 2 ) ||    /* rule out ratio <2/3 */
						 ( pH264Video->width    > pH264Video->height * 4 )  )      /* rule out ratio > 4 */
					{
						if ( pH264Video->guessH264 > -200 ) pH264Video->guessH264 -= 10; 
						return 0;
					}

					ReadBitsU( &bits, 1 );   //int direct_8x8_inference_flag             = ReadBitsU( &bits, 1 ); 
					frame_cropping_flag                   = ReadBitsU( &bits, 1 ); 
				    
					if (frame_cropping_flag)                                                                      
					{                                                                          
						ReadUE( &bits ); //int frame_cropping_rect_left_offset      = ReadUE( &bits );
						frame_cropping_rect_right_offset     = ReadUE( &bits );
						ReadUE( &bits ); //int frame_cropping_rect_top_offset       = ReadUE( &bits );
						frame_cropping_rect_bottom_offset    = ReadUE( &bits );
					}                                                                          
 
					pH264Video->width -= 2*_MIN( frame_cropping_rect_right_offset, 7 );
					if ( frame_mbs_only_flag )  
						pH264Video->height -= 2 * _MIN( frame_cropping_rect_bottom_offset, 7 );
					else
						pH264Video->height -= 4 * _MIN( frame_cropping_rect_bottom_offset, 3 );

					if ( ReadBitsU( &bits, 1 ) ) //vui_parameters_present_flag
					{
						 if ( ReadBitsU( &bits, 1 ) ) //aspect_ratio_info_present_flag
						 {
					        unsigned int aspect_ratio_idc= ReadBitsU(&bits, 8);
							if( aspect_ratio_idc == 0xff ) 
							{
								pH264Video->ar_nomi = ReadBitsU(&bits, 16);
								pH264Video->ar_deno = ReadBitsU(&bits, 16);
							}else 
							if(aspect_ratio_idc < sizeof(pixel_aspect))
							{
								pH264Video->ar_nomi =  pixel_aspect[aspect_ratio_idc].nom;
								pH264Video->ar_deno =  pixel_aspect[aspect_ratio_idc].den;
							}
							else{
								if ( pH264Video->guessH264 > -200 ) pH264Video->guessH264 -= 10; 
								return 0;
							}
						}
					}
				    if( ReadBitsU( &bits, 1 ) )      // overscan_info_present_flag
						ReadBitsU( &bits, 1 );     // overscan_appropriate_flag 
    
					if( ReadBitsU( &bits, 1 ) )      // video_signal_type_present_flag
					{
						ReadBitsU( &bits, 3 );    // video_format
						ReadBitsU( &bits, 1 );     // video_full_range_flag
						if(ReadBitsU( &bits, 1 ))   // colour_description_present_flag 
						{  
							ReadBitsU( &bits, 8 ); // colour_primaries
							ReadBitsU( &bits, 8 ); // transfer_characteristics
							ReadBitsU( &bits, 8 ); // matrix_coefficients
						}
					 }

					if( ReadBitsU( &bits, 1 ) )	// chroma_location_info_present_flag 
					{      
						ReadUE( &bits );  // chroma_sample_location_type_top_field 
						ReadUE( &bits );  // chroma_sample_location_type_bottom_field 
					}

					if( ReadBitsU( &bits, 1 ) )
					{
						unsigned long num_units_in_tick = ReadBitsU( &bits, 32 );
						unsigned long time_scale        = ReadBitsU( &bits, 32 );
						int fixed_frame_rate_flag       = ReadBitsU( &bits, 1 );
						if ( fixed_frame_rate_flag )
						{
							int nomi, deno;
							nomi = time_scale;
							deno = 2*num_units_in_tick;
							pH264Video->frame_rate_nomi = LCMNomiCalculator( nomi, deno );
							pH264Video->frame_rate_deno = LCMDenoCalculator( nomi, deno );
						}
					}
					pH264Video->sps_length=_MIN((unsigned short)bytes, sizeof(pH264Video->sps)-5) ;
					memcpy( pH264Video->sps+5, rbsp, pH264Video->sps_length);
					pH264Video->sps[0]=pH264Video->sps[1]=pH264Video->sps[2]=0;
					pH264Video->sps[3]=1; pH264Video->sps[4]=0x27;
					pH264Video->sps_length += 5;
					pH264Video->guessH264 = 200;
					break;
				}


				//printf( "profile:%d level:%d width:%d height:%d(spsid:%d)\n", pH264Video->profile, pH264Video->level, 
				//	pH264Video->width, pH264Video->height, pH264Video->sps_id );

/////////////////////////////////////////////////////////////
			} else
			if ( nal_unit_type == NAL_SEI )
			{
				int bytes = ( Size-(int)(p-pData) < (int)sizeof(rbsp) ) ? Size-(int)(p-pData) : (int)sizeof(rbsp) ;
				//printf( "NALU SEI:%d\n", nal_unit_type );
				bytes = NAL2RBSP( (unsigned char*)p, (unsigned char*)rbsp, bytes );
				p += bytes;
			} else
			{
				//skip NALU
				//printf( "NALU type:%d\n", nal_unit_type );
			}
		} else
			break;
Example #3
0
void Router::incCredit()
{
    if (m_credit_deposit_vec.size() == 0) // no credits to deposit?
        return;

    int num_org_credit_reqs = m_credit_deposit_vec.size(); // for sanity check
    int num_complete_credit_reqs = 0;
    int num_deposited_credits = 0;	// total deposited credits

    // deposit a credit to the corresponding output module
    for (vector< Credit* >::iterator pos=m_credit_deposit_vec.begin(); pos != m_credit_deposit_vec.end(); ++pos) {
        Credit* p_credit = *pos;

        if (p_credit->m_clk_deposit > simtime())
            break;	// all other deposited credits must be increased later.

        switch (g_cfg.router_buffer_type) {
        case ROUTER_BUFFER_SAMQ:
            m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit += p_credit->m_num_credits;
            assert(m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit <= m_inbuf_depth);
            break;
        case ROUTER_BUFFER_DAMQ_P:
        case ROUTER_BUFFER_DAMQ_R:
        {
            int num_shared_credits = p_credit->m_num_credits;
            if (m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit_rsv < g_cfg.router_num_rsv_credit) {
                int num_rsv_credits = _MIN(g_cfg.router_num_rsv_credit - m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit_rsv, p_credit->m_num_credits);
                num_shared_credits = p_credit->m_num_credits - num_rsv_credits;
                assert(num_shared_credits >= 0);

                m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit_rsv += num_rsv_credits;
            }

            m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit += num_shared_credits;
        }
        break;
        default:
            assert(0);
        }

#ifdef _DEBUG_CREDIT
        printf("incCredit router=%d deposit_clk=%.0lf clk=%.0lf out_pc=%d out_vc=%d credits=%d\n", id(), p_credit->m_clk_deposit, simtime(), p_credit->m_out_pc, p_credit->m_out_vc, m_out_mod_vec[p_credit->m_out_pc][p_credit->m_out_vc].m_num_credit);
#endif

        num_complete_credit_reqs++;
        num_deposited_credits += p_credit->m_num_credits;
        g_CreditPool.reclaim(p_credit);
    }

    // delete successfully deposited credits
    if (num_complete_credit_reqs > 0)
        m_credit_deposit_vec.erase(m_credit_deposit_vec.begin(), m_credit_deposit_vec.begin()+num_complete_credit_reqs);

#ifdef _DEBUG_CREDIT
    printf("incCredit router=%d clk=%.0lf\n", m_id, simtime());
    printf("  num_org_credit_reqs=%d\n", num_org_credit_reqs);
    printf("  num_complete_credit_reqs=%d\n", num_complete_credit_reqs);
    printf("  m_credit_deposit_vec.size()=%d\n", m_credit_deposit_vec.size());
    printf("  num_deposited_credits=%d\n", num_deposited_credits);
#endif

    assert((num_org_credit_reqs - num_complete_credit_reqs) == ((int) m_credit_deposit_vec.size()));
}
// Sort the bunch in ascending z (ct) order, and return
// a vector of iterators which point to the equal-spaced
// bin boundaries defines by zmin to zmax in steps of dz
//
// Returns the number of particles removed from tails
// i.e. z<zmin || z>=zmax
//
// hdp contains the derivative of the distribution
// calculated using the Savitzky-Golay filter c
// If c is empty, then the derivative will be zero.
size_t ParticleBinList(ParticleBunch& bunch, double zmin, double zmax, size_t nbins,
                       vector<ParticleBunch::iterator>& pbins,
                       vector<double>& hd, vector<double>& hdp, vector<double>* c)
{
//cout << "In ParticleBinList" << endl;
//cout << zmin << "\t" << zmax << "\t" << nbins << endl;
	double dz = (zmax-zmin)/double(nbins);
	vector<ParticleBunch::iterator> bins;
	vector<double> hbins(nbins,0);
	bins.reserve(nbins+1);

	bunch.SortByCT();

	size_t lost = TruncateZ(bunch,zmin,zmax);

	ParticleBunch::iterator p = bunch.begin();
	bins.push_back(p);

	double z=zmin;
	double total=0;
	size_t n;

	for(n=0; n<nbins; n++)
	{
		z+=dz;
		while(p!=bunch.end() && p->ct()<z)
		{
			total++;
			hbins[n]++;
			p++;
		}
		bins.push_back(p);
	}


	if(p!=bunch.end())
	{
#ifdef ENABLE_MPI
		cerr << "bad slicing in rank: " << MPI::COMM_WORLD.Get_rank() << endl;
#endif

#ifndef ENABLE_MPI
		cerr << "bad slicing" << endl;
#endif

		cerr << "z = " << z << " ct = " << p->ct() << " zmax = " << zmax << endl;
		//Dump out the bad bunch
		/*
			ofstream* badbunch = new ofstream("badbunch.bunch");
			bunch.Output(*badbunch);
			badbunch->close();
			delete badbunch;
			cerr << "Output of the current bunch is to badbunch.bunch" << endl;
		*/
#ifndef ENABLE_MPI
		abort();
#endif

#ifdef ENABLE_MPI
		MPI::COMM_WORLD.Abort(1);
#endif
	}

	//	bins.push_back(p); // should be end()

	// normalise distribution
	// and apply filter

	vector<double> fbins(nbins,0);
	vector<double> fpbins(nbins,0);

	double a = 1/total/dz;
	int w = c ? (c->size()-1)/2 : 0;
	size_t m;

	for(n=0; n<nbins; n++)
	{
		fbins[n] = hbins[n]*a;
		if(c)
			//for(m=_MAX(0,int(n)-w); m<=_MIN(nbins,int(n)+w); m++)// ERROR! m can be set to nbins -> out of range!
			for(m=_MAX(0,int(n)-w); m<_MIN(nbins,size_t(n)+w); m++)   // This needs to be checked!
			{
				fpbins[n] += hbins[m]*(*c)[m-n+w]*a;
			}
	}

	pbins.swap(bins);
	hd.swap(fbins);
	hdp.swap(fpbins);

	return lost;
}
Example #5
0
void copy_psa_to_sockaddr(struct polymorphic_sockaddr *psa, struct sockaddr *address, unsigned int *address_len)
{
	memcpy(address, &psa->sockaddr.sa, _MIN(*address_len, psa->sa_len));
	*address_len = psa->sa_len;
}
Example #6
0
void CStdItemSpecial::UpgradeRandomItem(BYTE* btValue, WORD &nDura, WORD &nDuraMax)//_LPTMAKEITEMRCD lpMakeItemRcd)
{
    int nUpgrade, nIncp, nVal;

    switch (btType)
    {
    case 0:	// 무기
    {
        // 파괴 옵션
        nUpgrade = GetUpgrade(12, 15);
        if (rand() % 15 == 0)
            btValue[0] = 1 + nUpgrade;	// DC

        // 공격 속도
        nUpgrade = GetUpgrade(12, 15);
        if (rand() % 20 == 0)
        {
            nIncp = (int)((1 + nUpgrade) / 3);

            if (nIncp > 0)
            {
                if (rand() % 3 != 0) btValue[6] = nIncp;	// 공격 속도 (-)
                else
                    btValue[6] = 10 + nIncp; // 공격 속도 (+)
            }
        }

        // 마력
        nUpgrade = GetUpgrade(12, 15);
        if (rand() % 15 == 0)
            btValue[1] = 1 + nUpgrade;	// MC

        // 도력
        nUpgrade = GetUpgrade(12, 15);
        if (rand() % 15 == 0)
            btValue[2] = 1 + nUpgrade;	// SC

        // 정확
        nUpgrade = GetUpgrade(12, 15);
        if (rand() % 24 == 0)
            btValue[5] = 1 + ((int)nUpgrade / 2);	// 정확 (+)

        // 내구
        nUpgrade = GetUpgrade(12, 12);
        if (rand() % 3 < 2)
        {
            nVal = (1 + nUpgrade) * 2000;

            nDuraMax	= _MIN(65000, nDuraMax + nVal);
            nDura		= _MIN(65000, nDura + nVal);
        }

        // 강도
        nUpgrade = GetUpgrade(12, 15);
        if (rand() % 10 == 0)
            btValue[7] = 1 + ((int)nUpgrade / 2);

        break;
    }
    case 1:	// 방어구류
    {
        //방어
        nUpgrade = GetUpgrade(6, 15);
        if (rand() % 40 == 0)
            btValue[0] = 1 + nUpgrade;	// AC

        //마항
        nUpgrade = GetUpgrade(6, 15);
        if (rand() % 40 == 0)
            btValue[1] = 1 + nUpgrade;	// MAC

        //파괴
        nUpgrade = GetUpgrade(6, 20);
        if (rand() % 40 == 0)
            btValue[2] = 1 + nUpgrade;	// DC

        //마법
        nUpgrade = GetUpgrade(6, 20);
        if (rand() % 40 == 0)
            btValue[3] = 1 + nUpgrade;	// MC

        //도력
        nUpgrade = GetUpgrade(6, 20);
        if (rand() % 40 == 0)
            btValue[4] = 1 + nUpgrade;	// SC

        //내구
        nUpgrade = GetUpgrade(6, 10);
        if (rand() % 8 < 6)
        {
            nVal = (1 + nUpgrade) * 2000;

            nDuraMax	= _MIN(65000, nDuraMax + nVal);
            nDura		= _MIN(65000, nDura + nVal);
        }

        break;
    }
    case 2:	// 반지, 팔지, 목걸이
    {
        // 정확
        nUpgrade = GetUpgrade(6, 30);
        if (rand() % 60 == 0)
            btValue[0] = 1 + nUpgrade;	// AC(HIT)

        //민첩
        nUpgrade = GetUpgrade(6, 30);
        if (rand() % 60 == 0)
            btValue[1] = 1 + nUpgrade;	// MAC(SPEED)

        //파괴
        nUpgrade = GetUpgrade(6, 20);
        if (rand() % 30 == 0)
            btValue[2] = 1 + nUpgrade;	// DC

        //마법
        nUpgrade = GetUpgrade(6, 20);
        if (rand() % 30 == 0)
            btValue[3] = 1 + nUpgrade;	// MC

        //도력
        nUpgrade = GetUpgrade(6, 20);
        if (rand() % 30 == 0)
            btValue[4] = 1 + nUpgrade;	// SC

        //내구
        nUpgrade = GetUpgrade(6, 12);
        if (rand() % 20 < 15)
        {
            nVal = (1 + nUpgrade) * 1000;

            nDuraMax	= _MIN(65000, nDuraMax + nVal);
            nDura		= _MIN(65000, nDura + nVal);
        }

        break;
    }
    }
}
Example #7
0
void MatrixQuaternionSlerp(
	QUATERNION			&qOut,
	const QUATERNION	&qA,
	const QUATERNION	&qB,
	const float				t)
{
	float		fCosine, fAngle, A, B;

	/* Parameter checking */
	if (t<0.0f || t>1.0f)
	{
		printf("MatrixQuaternionSlerp : Bad parameters\n");
		qOut.x = 0;
		qOut.y = 0;
		qOut.z = 0;
		qOut.w = 1;
		return;
	}

	/* Find sine of Angle between Quaternion A and B (dot product between quaternion A and B) */
	fCosine = qA.w*qB.w + qA.x*qB.x + qA.y*qB.y + qA.z*qB.z;

	if (fCosine < 0)
	{
		QUATERNION qi;

		/*
			<http://www.magic-software.com/Documentation/Quaternions.pdf>

			"It is important to note that the quaternions q and -q represent
			the same rotation... while either quaternion will do, the
			interpolation methods require choosing one over the other.

			"Although q1 and -q1 represent the same rotation, the values of
			Slerp(t; q0, q1) and Slerp(t; q0,-q1) are not the same. It is
			customary to choose the sign... on q1 so that... the angle
			between q0 and q1 is acute. This choice avoids extra
			spinning caused by the interpolated rotations."
		*/
		qi.x = -qB.x;
		qi.y = -qB.y;
		qi.z = -qB.z;
		qi.w = -qB.w;

		MatrixQuaternionSlerp(qOut, qA, qi, t);
		return;
	}

	fCosine = _MIN(fCosine, 1.0f);
	fAngle = (float)acos(fCosine);

	/* Avoid a division by zero */
	if (fAngle==0.0f)
	{
		qOut = qA;
		return;
	}

	/* Precompute some values */
	A = (float)(sin((1.0f-t)*fAngle) / sin(fAngle));
	B = (float)(sin(t*fAngle) / sin(fAngle));

	/* Compute resulting quaternion */
	qOut.x = A * qA.x + B * qB.x;
	qOut.y = A * qA.y + B * qB.y;
	qOut.z = A * qA.z + B * qB.z;
	qOut.w = A * qA.w + B * qB.w;

	/* Normalise result */
	MatrixQuaternionNormalize(qOut);
}
Example #8
0
// The method used to distribute values of beliefs associated with centroid that
// is going to be deleted. It helps when deleted centroid is very close to good
// learned centroids. This centroids from neighbourhood get additional weighted
// belief of deleted centroid where more weights have centroids that are closer.
void _distributeEvidenceOfDeletedCentroidToNeighbours(Destin *d, uint l, uint idx, uint nearest)
{
    uint i, j, k, nb, ns;

    Node * n = GetNodeFromDestin(d, l, 0, 0);
    nb = n->nb;
    ns = n->ns;

    if (nb < 2)
    {
        fprintf (stderr, "DistributeWeightsOfDeletedCentroid(): called when the layer %d has only single centroid!", l);
        return;
    }

    _Neighbour neighbours[nb];
    for (i = 0; i < nb; i++)
    {
        neighbours[i].index = i;
        neighbours[i].distance = _calcNeighboursDistanceEuc(d->uf_mu[l][i], d->uf_mu[l][idx], ns) + EPSILON;
        neighbours[i].weight = 0;
    }
    qsort((void *)neighbours, nb, sizeof(_Neighbour), (void *)&_compareNeighboursByDistance);
    nearest = _MIN(nearest, nb-1);

    float sumDistance = 0;
    for (i = 1; i <= nearest; i++)
    {
        sumDistance += neighbours[i].distance;
    }
    float sumWeights = 0;
    for (i = 1; i <= nearest; i++)
    {
        neighbours[i].weight = sumDistance / neighbours[i].distance;
        sumWeights += neighbours[i].weight;
    }
    for (i = 1; i <= nearest; i++)
    {
        neighbours[i].weight /= sumWeights;
    }

    // Layer l+1
    if (l+1 < d->nLayers)
    {
        n = GetNodeFromDestin(d, l+1, 0, 0);
        for (i = 0; i < n->nb; i++)
        {
            for (j = 0; j < n->nChildren; j++)
            {
                for (k = 1; k <= nearest; k++)
                {
                    d->uf_mu[l+1][i][nb*j + neighbours[k].index] += d->uf_mu[l+1][i][nb*j + idx] * neighbours[k].weight;
                    d->uf_sigma[l+1][i][nb*j + neighbours[k].index] += d->uf_sigma[l+1][i][nb*j + idx] * neighbours[k].weight;
                }
                // centroid evidence has been distributed
                d->uf_mu[l+1][i][nb*j + idx] = 0;
                d->uf_sigma[l+1][i][nb*j + idx] = 0;
            }
        }
    }

    // TODO: RECURRENT MODE: move evidence for l layer and l-1 layer
}
Example #9
0
/**
 * @function EntryDraw
 * @brief user entry draw function
 * @param void *_g_obj: generic object
 * @param void *_obj: frame object
 * @return none
 */
static void EntryDraw(void *_g_obj, void *_obj) {

  g_obj_st *g_obj;
  usr_entry_st *entry;

  uint8_t glyph;
  uint16_t ii, selStart, selStop;
  coord_t x, xInsertLine, xMin, yMin, xMax, yMax;
  rect_st rec;
  color_t colBack, colText;

  /*retreive generic & specific object*/
  if(_g_obj != NULL && _obj != NULL) {
    g_obj = (g_obj_st *) _g_obj;
    entry =  (usr_entry_st*) _obj;

    /*P2D configuration*/
    P2D_SetDisplayMode(DISPLAY_SOLID);
    P2D_SetLineType(LINE_SOLID);
    SetFont(entry->font);

    if(GUI_ObjIsDisabled(g_obj)) {
      colBack = GetColor(G_COL_BACKGROUND);
      colText = GetColor(G_COL_D_TEXT);
    }
    else {
      colBack = GetColor(G_COL_E_BACKGROUND);
      colText = entry->colText;
    }

    /*retrieve text coord*/
    GetTextCoords(&(g_obj->rec), &xMin, &yMin, &xMax, &yMax);

    /*display usr_entry glyphs, one by one*/
    selStart = _MIN(entry->cursStart, entry->cursStop);
    selStop = _MAX(entry->cursStart, entry->cursStop);
    x = xMin;
    xInsertLine = x;
    ii = entry->offsetDisplay;

    while(x < xMax && entry->buffer[ii] != 0) {

      /*select the color of the text, according to the user selection (i.e. reverse colors if the current glyph is a part of the user selection)*/
      if(entry->bEditable == false || selStart == selStop || ii < selStart || ii >= selStop) {
        P2D_SetColors(colText, colBack);
      }
      else {
        P2D_SetColors(colBack, GetColor(G_COL_SPECIAL));
      }

      /*display the glyph*/
      glyph = entry->buffer[ii];
      P2D_PutGlyph(x, yMin, glyph);
      x += P2D_GetGlyphWidth(glyph);

      /*if the car corresponds to the user selection bar, store its coord*/
      if(ii == entry->cursStop - 1) xInsertLine = x;

      /*next car*/
      ii++;
    }

    /*clear from last car to the end of the entry*/
    P2D_SetColors(colBack, colBack);
    (void) P2D_CoordToRect(&rec, x, yMin, xMax, yMax);
    P2D_FillRect(&rec);

    /*clear between text and object rect (1 px width)*/
    (void) P2D_CoordToRect(&rec, xMin-1, yMin-1, xMax+1, yMax+1);
    P2D_Rect(&rec);

    /*display the insert line*/
    if(entry->bEditable && entry->bBlink) {
      P2D_SetColor(colText);
      P2D_Line(xInsertLine, yMin, xInsertLine, yMax);
    }

    /*object rect*/
    P2D_SetColor(GetColor(G_COL_LOWER_REC));
    P2D_Rect(&(g_obj->rec));
  }
}
Example #10
0
bool Aeromatic::fdm()
{
    Aircraft *aircraft = _aircraft[_atype];
    std::vector<System*> systems = _aircraft[_atype]->get_systems();

    _engines = _MIN(_no_engines, 4);
    aircraft->_engines = _engines;


//***** METRICS ***************************************
    _payload = _max_weight;
    _stall_weight = _max_weight;

    // first, estimate wing loading in psf
    float wing_loading = aircraft->get_wing_loading();

    // if no wing area given, use wing loading to estimate
    bool wingarea_input;
    if (_wing.area == 0)
    {
        wingarea_input = false;
        _wing.area = _max_weight / wing_loading;
    }
    else
    {
        wingarea_input = true;
        wing_loading = _max_weight / _wing.area;
    }

    // calculate wing chord
    if (_wing.aspect == 0) {
        _wing.aspect = aircraft->get_aspect_ratio();
    } else {
        _user_wing_data++;
    }
    if (_wing.chord == 0)
    {
        if (_wing.aspect > 0) {
            _wing.chord = _wing.span / _wing.aspect;
        } else {
            _wing.chord = _wing.area / _wing.span;
        }
    }
    else {
        _user_wing_data++;
    }

    // calculate aspect ratio
    if (_wing.aspect == 0) {
        _wing.aspect = (_wing.span*_wing.span) / _wing.area;
    } else {
        _user_wing_data++;
    }

    if (_wing.taper == 0) {
        _wing.taper = 1.0f;
    }

    float TR = _wing.taper;
    _wing.chord_mean = 0.75f*_wing.chord*(1.0f+TR+TR*TR)/(1.0f+TR);
    _wing.de_da = 4.0f/(_wing.aspect+2.0f);

    // leading edge sweep
    // devide the span by two and account for fuselage width
    float span = 0.45f*_wing.span;
    float root_tip = _wing.chord*(1.0f - _wing.taper);

    if (_wing.sweep_le == 0)
    {
        _wing.sweep_le = atanf(root_tip/span);
        if (_wing.shape != DELTA) {
            _wing.sweep_le *= 0.5f;
        }
        _wing.sweep_le *= RAD_TO_DEG;
        _wing.sweep_le += _wing.sweep;
    }

    if (_wing.thickness == 0)
    {
        // Hofman equation for t/c
//      float Ws = _stall_weight;
        float Vs = _stall_speed * KNOTS_TO_FPS;
        float sweep = _wing.sweep * DEG_TO_RAD;
        float TC = 0.051f * _wing.area * powf(cosf(sweep), 5.0f)/Vs;
        _wing.thickness = TC * _wing.chord;
    }

    // for now let's use a standard 2 degrees wing incidence
    if (_wing.incidence == 0) {
        _wing.incidence = 2.0;
    }

    // estimate horizontal tail area
    if (_htail.area == 0) {
        _htail.area = _wing.area * aircraft->get_htail_area();
    }

    // estimate distance from CG to horizontal tail aero center
    if (_htail.arm == 0) {
        _htail.arm = _length * aircraft->get_htail_arm();
    }

    if (_htail.aspect == 0) {
        _htail.aspect = 5.0f;	// ht_w * _wing.aspect;
    }
    if (_htail.taper == 0) {
        _htail.taper = 0.5f;
    }

    float ht_w = 0.33f; // sqrtf(_htail.area / _wing.area);
    if (_htail.span == 0) {
        _htail.span = ht_w * _wing.span;
    }

    TR = _htail.taper;
    _htail.chord_mean = 0.75f*_htail.chord*(1.0f+TR+TR*TR)/(1.0f+TR);
    _htail.de_da = 4.0f/(_htail.aspect+2.0f);

    // estimate vertical tail area
    if (_vtail.area == 0) {
        _vtail.area = _wing.area * aircraft->get_vtail_area();
    }

    // estimate distance from CG to vertical tail aero center
    if (_vtail.arm == 0) {
        _vtail.arm = _length * aircraft->get_vtail_arm();
    }

    float vt_w = 0.15f; // sqrtf(_vtail.area / _wing.area*0.5f);
    if (_vtail.span == 0) {
        _vtail.span = vt_w * _wing.span;
    }
    if (_vtail.aspect == 0) {
        _vtail.aspect = 1.7f;	// vt_w * _wing.aspect;
    }
    if (_vtail.taper == 0) {
        _vtail.taper = 0.7f;
    }

    TR = _vtail.taper;
    _vtail.chord_mean = 0.75f*_vtail.chord*(1.0f+TR+TR*TR)/(1.0f+TR);
    _vtail.de_da = 4.0f/(_vtail.aspect+2.0f);

//***** EMPTY WEIGHT *********************************

    // estimate empty weight, based on max weight
    if (_empty_weight == 0) {
        _empty_weight = _max_weight * aircraft->get_empty_weight();
    }

//***** MOMENTS OF INERTIA ******************************

    // use Roskam's formulae to estimate moments of inertia
    if (_inertia[X] == 0.0f && _inertia[Y] == 0.0f && _inertia[Z] == 0.0f)
    {
        float slugs = (_empty_weight / 32.2f);	// sluggishness
        const float *R = aircraft->get_roskam();

        // These are for an empty airplane
        _inertia[X] = slugs * powf((R[X] * _wing.span / 2), 2);
        _inertia[Y] = slugs * powf((R[Y] * _length / 2), 2);
        _inertia[Z] = slugs * powf((R[Z] * ((_wing.span + _length)/2)/2), 2);
    }

//***** CG LOCATION ***********************************

    _cg_loc[X] = (_length - _htail.arm) * FEET_TO_INCH;
    _cg_loc[Y] = 0;
    _cg_loc[Z] = -(_length / 40.0f) * FEET_TO_INCH;

//***** AERO REFERENCE POINT **************************

    _aero_rp[X] = _cg_loc[X];
    _aero_rp[Y] = 0;
    _aero_rp[Z] = 0;

//***** PILOT EYEPOINT *********************************

    // place pilot's eyepoint based on airplane type
    const float *_eyept_loc = aircraft->get_eyept_loc();
    float eyept_loc[3];
    eyept_loc[X] = (_length * _eyept_loc[X]) * FEET_TO_INCH;
    eyept_loc[Y] = _eyept_loc[Y];
    eyept_loc[Z] = _eyept_loc[Z];

//***** PAYLOAD ***************************************

    // A point mass will be placed at the CG weighing
    // 1/2 of the usable aircraft load.
    float payload_loc[3];
    payload_loc[X] = _cg_loc[X];
    payload_loc[Y] = _cg_loc[Y];
    payload_loc[Z] = _cg_loc[Z];
    _payload -= _empty_weight;

//***** SYSTEMS ***************************************
    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled()) {
            systems[i]->set(_cg_loc);
        }
    }

//***** COEFFICIENTS **********************************
    aircraft->set_lift();
    aircraft->set_drag();
    aircraft->set_side();
    aircraft->set_roll();
    aircraft->set_pitch();
    aircraft->set_yaw();

//************************************************
//*                                              *
//*  Print out xml document                      *
//*                                              *
//************************************************

    char str[64];
    time_t t;

    time(&t);
#ifdef _MSC_VER
    struct tm ti;
    localtime_s(&ti, &t);
    strftime(str, sizeof(str), "%d %b %Y", &ti);
#else
    struct tm *ti= localtime(&t);
    strftime(str, sizeof(str), "%d %b %Y", ti);
#endif

    _dir = _subdir ? create_dir(_path, _name) : _path;
    if (_dir.empty()) {
        std::cout << "Unable to create directory: " << _path << "/" << _name << std::endl;
        return false;
    }

    std::string systems_dir;
    if (_system_files)
    {
        systems_dir = create_dir(_dir, "Systems");
        if (systems_dir.empty())
        {
            std::cout << "Unable to create directory: " << _dir<< "/Systems" << std::endl;
            _system_files = false;
        }
    }

    std::string fname = _dir + "/" + std::string(_name) + ".xml";

    std::string version = AEROMATIC_VERSION_STR;

    if (!_overwrite && overwrite(fname)) {
        std::cout << "File already exists: " << fname << std::endl;
        return false;
    }

    std::ofstream file;
    file.open(fname.c_str());
    if (file.fail() || file.bad())
    {
        file.close();
        return false;
    }

    file.precision(2);
    file.flags(std::ios::right);
    file << std::fixed << std::showpoint;

    file << "<?xml version=\"1.0\"?>" << std::endl;
    file << "<?xml-stylesheet type=\"text/xsl\" href=\"http://jsbsim.sourceforge.net/JSBSim.xsl\"?>" << std::endl;
    file << std::endl;
    file << "<fdm_config name=\"" << _name << "\" version=\"2.0\" release=\"ALPHA\"" << std::endl;
    file << "   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << std::endl;
    file << "   xsi:noNamespaceSchemaLocation=\"http://jsbsim.sourceforge.net/JSBSim.xsd\">" << std::endl;
    file << std::endl;
    file << " <fileheader>" << std::endl;
    file << "  <author> Aeromatic v " << version << " </author>" << std::endl;
    file << "  <filecreationdate> " << str << " </filecreationdate>" << std::endl;
    file << "  <version>$Revision: 1.50 $</version>" << std::endl;
    file << "  <description> Models a " << _name << ". </description>" << std::endl;
    file << " </fileheader>" << std::endl;
    file << std::endl;
    file << "<!--\n  File:     " << _name << ".xml" << std::endl;
    file << "  Inputs:" << std::endl;
    file << "    name:          " << _name << std::endl;
    file << "    type:          ";
    switch(_atype)
    {
    case LIGHT:
        if (_no_engines == 0) {
            file << "glider" << std::endl;
        } else {
            file << "light commuter with " << _no_engines << " engines" << std::endl;
        }
        break;
    case PERFORMANCE:
        file << "WWII fighter, subsonic sport, aerobatic" << std::endl;
        break;
    case FIGHTER:
        file << _no_engines << " engine transonic/supersonic fighter" << std::endl;
        break;
    case JET_TRANSPORT:
        file << _no_engines << " engine transonic transport" << std::endl;
        break;
    case PROP_TRANSPORT:
        file << "multi-engine prop transport" << std::endl;
        break;
    }
    file << "    stall speed:   " << _stall_speed << "kts" << std::endl;
    file << "    max weight:    " << _max_weight << " lb" << std::endl;
    file << "    length:        " << _length << " ft" << std::endl;
    file << "    wing: " << std::endl;
    file << "     span:         " << _wing.span << " ft" << std::endl;
    file << "     area:         ";
    if (wingarea_input) {
        file << _wing.area << " sq-ft" << std::endl;
    } else {
        file << "unspecified" << std::endl;
    }
    file << "     chord:        " << _wing.chord << " ft" << std::endl;
    file << "     aspect ratio: " << _wing.aspect << ":1" << std::endl;
    file << "     taper ratio:  " << _wing.taper << ":1" << std::endl;
    file << "     incidence:    " << _wing.incidence << " degrees" << std::endl;
    file << "     dihedral:     " << _wing.dihedral << " degrees" << std::endl;
    file << "     sweep:        " << _wing.sweep << " degrees" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled()) {
            std::string comment = systems[i]->comment();
            if (!comment.empty()) {
                file << comment << std::endl;
            }
        }
    }

    file << "  Outputs:" << std::endl;
    file << "    wing loading:  " << wing_loading << " lb/sq-ft" << std::endl;
    file << "    payload:       " << _payload << " lbs" << std::endl;
    file << "    CL-alpha:      " << _CLalpha[0] << " per radian" << std::endl;
    file << "    CL-0:          " << _CL0 << std::endl;
    file << "    CL-max:        " << _CLmax[0] << std::endl;
    file << "    CD-0:          " << _CD0 << std::endl;
    file << "    K:             " << _Kdi << std::endl;
    file << "    Mcrit:         " << _Mcrit << std::endl;
    file << "-->" << std::endl;
    file << std::endl;

//***** METRICS **********************************

    file << " <metrics>" << std::endl;
    file << "   <wingarea  unit=\"FT2\"> " << std::setw(8) << _wing.area << " </wingarea>" << std::endl;
    file << "   <wingspan  unit=\"FT\" > " << std::setw(8) << _wing.span << " </wingspan>" << std::endl;
    file << "   <wing_incidence>       " << std::setw(8) << _wing.incidence << " </wing_incidence>" << std::endl;
    file << "   <chord     unit=\"FT\" > " << std::setw(8) << _wing.chord << " </chord>" << std::endl;
    file << "   <htailarea unit=\"FT2\"> " << std::setw(8) << _htail.area << " </htailarea>" << std::endl;
    file << "   <htailarm  unit=\"FT\" > " << std::setw(8) << _htail.arm << " </htailarm>" << std::endl;
    file << "   <vtailarea  unit=\"FT2\">" << std::setw(8) << _vtail.area << " </vtailarea>" << std::endl;
    file << "   <vtailarm  unit=\"FT\" > " << std::setw(8) << _vtail.arm << " </vtailarm>" << std::endl;
    file << "   <location name=\"AERORP\" unit=\"IN\">" << std::endl;
    file << "     <x> " << std::setw(8) << _aero_rp[X] << " </x>" << std::endl;
    file << "     <y> " << std::setw(8) << _aero_rp[Y] << " </y>" << std::endl;
    file << "     <z> " << std::setw(8) << _aero_rp[Z] << " </z>" << std::endl;
    file << "   </location>" << std::endl;
    file << "   <location name=\"EYEPOINT\" unit=\"IN\">" << std::endl;
    file << "     <x> " << std::setw(8) << eyept_loc[X] << " </x>" << std::endl;
    file << "     <y> " << std::setw(8) << eyept_loc[Y] << " </y>" << std::endl;
    file << "     <z> " << std::setw(8) << eyept_loc[Z] << " </z>" << std::endl;
    file << "   </location>" << std::endl;
    file << "   <location name=\"VRP\" unit=\"IN\">" << std::endl;
    file << "     <x>     0.0 </x>" << std::endl;
    file << "     <y>     0.0 </y>" << std::endl;
    file << "     <z>     0.0 </z>" << std::endl;
    file << "   </location>" << std::endl;
    file << " </metrics>"<< std::endl;
    file << std::endl;
    file << " <mass_balance>" << std::endl;
    file << "   <ixx unit=\"SLUG*FT2\">  " << std::setw(8) << _inertia[X] << " </ixx>" << std::endl;
    file << "   <iyy unit=\"SLUG*FT2\">  " << std::setw(8) << _inertia[Y] << " </iyy>" << std::endl;
    file << "   <izz unit=\"SLUG*FT2\">  " << std::setw(8) << _inertia[Z] << " </izz>" << std::endl;
    file << "   <emptywt unit=\"LBS\" >  " << std::setw(8) << _empty_weight << " </emptywt>" << std::endl;
    file << "   <location name=\"CG\" unit=\"IN\">" << std::endl;
    file << "     <x> " << std::setw(8) << _cg_loc[X] << " </x>" << std::endl;
    file << "     <y> " << std::setw(8) << _cg_loc[Y] << " </y>" << std::endl;
    file << "     <z> " << std::setw(8) << _cg_loc[Z] << " </z>" << std::endl;
    file << "   </location>" << std::endl;
    file << "   <pointmass name=\"Payload\">" << std::endl;
    file << "    <description> " << _payload << " LBS should bring model up to entered max weight </description>" << std::endl;
    file << "    <weight unit=\"LBS\"> " << (_payload* 0.5f) << " </weight>" << std::endl;
    file << "    <location name=\"POINTMASS\" unit=\"IN\">" << std::endl;
    file << "     <x> " << std::setw(8) << payload_loc[X] << " </x>" << std::endl;
    file << "     <y> " << std::setw(8) << payload_loc[Y] << " </y>" << std::endl;
    file << "     <z> " << std::setw(8) << payload_loc[Z] << " </z>" << std::endl;
    file << "   </location>" << std::endl;
    file << "  </pointmass>" << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string mass_balance = systems[i]->mass_balance();
            if (!mass_balance.empty()) {
                file << mass_balance << std::endl;
            }
        }
    }

    file << " </mass_balance>" << std::endl;
    file << std::endl;

//***** FDM_CONFIG ********************************************

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string fdm = systems[i]->fdm();
            if (!fdm.empty()) {
                file << fdm << std::endl;
            }
        }
    }

//***** SYSTEMS ***********************************************

    if (_system_files == true)
    {
        for (unsigned i=0; i<systems.size(); ++i)
        {
            if (systems[i]->enabled())
            {
                std::string system = systems[i]->system();
                if (!system.empty())
                {
                    std::string sname = systems[i]->get_description();
                    std::string sfname = sname + ".xml";

                    if (!_overwrite && overwrite(sfname))
                    {
                        std::cout << "File already exists: " << fname << std::endl;
                        std::cout << "Skipping." << std::endl;
                    }
                    else
                    {
                        file << " <system file=\"" << sfname << "\"/>" << std::endl;

                        std::string sfpath = systems_dir + "/" + sfname;
                        std::ofstream sfile;
                        sfile.open(sfpath.c_str());
                        if (sfile.fail() || sfile.bad())
                        {
                            std::cout << "Error opening file: " << fname << std::endl;
                            std::cout << "Skipping." << std::endl;
                        }
                        else
                        {
                            sfile << "<?xml version=\"1.0\"?>" << std::endl;
                            sfile << "<system name=\"" << sname << "\">" << std::endl;
                            sfile << system << std::endl;
                            sfile << "</system>" << std::endl;
                        }
                        sfile.close();
                    }
                }
            }
        }
        file << std::endl;
    }

    file << " <flight_control name=\"FCS: " << _name << "\">" << std::endl;
    file << std::endl;

    if (_system_files == false)
    {
        for (unsigned i=0; i<systems.size(); ++i)
        {
            if (systems[i]->enabled())
            {
                std::string system = systems[i]->system();
                if (!system.empty()) {
                    file << system << std::endl;
                }
            }
        }
    }

    file << " </flight_control>"<< std::endl;
    file << std::endl;

//***** AERODYNAMICS ******************************************

    file << " <aerodynamics>" << std::endl;
    file << std::endl;

    // ***** LIFT ******************************************

    file << "  <axis name=\"LIFT\">" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string lift = systems[i]->lift();
            if (!lift.empty()) {
                file << lift << std::endl;
            }
        }
    }

    file << "  </axis>" << std::endl;
    file << std::endl;

    // ***** DRAG ******************************************

    file << "  <axis name=\"DRAG\">" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string drag = systems[i]->drag();
            if (!drag.empty()) {
               file << drag << std::endl;
            }
        }
    }

    file << "  </axis>" << std::endl;
    file << std::endl;

    // ***** SIDE ******************************************

    file << "  <axis name=\"SIDE\">" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string side = systems[i]->side();
            if (!side.empty()) {
                file << side << std::endl;
            }
        }
    }

    file << "  </axis>" << std::endl;
    file << std::endl;

    // ***** PITCH *****************************************

    file << "  <axis name=\"PITCH\">" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string pitch = systems[i]->pitch();
            if (!pitch.empty()) {
                file << pitch << std::endl;
            }
        }
    }

    file << "  </axis>" << std::endl;
    file << std::endl;

    // ***** ROLL ******************************************

    file << "  <axis name=\"ROLL\">" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string roll = systems[i]->roll();
            if (!roll.empty()) {
                file << roll << std::endl;
            }
        }
    }

    file << "  </axis>" << std::endl;
    file << std::endl;

    // ***** YAW *******************************************

    file << "  <axis name=\"YAW\">" << std::endl;
    file << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string yaw = systems[i]->yaw();
            if (!yaw.empty()) {
                file << yaw << std::endl;
            }
        }
    }

    file << "  </axis>" << std::endl;
    file << std::endl;
    
    file << " </aerodynamics>" << std::endl;
    file << std::endl;

    file << " <external_reactions>" << std::endl;

    for (unsigned i=0; i<systems.size(); ++i)
    {
        if (systems[i]->enabled())
        {
            std::string force = systems[i]->external_force();
            if (!force.empty()) {
                file << force << std::endl;
            }
        }
    }

    file << " </external_reactions>" << std::endl;

    file << std::endl;
    file << "</fdm_config>" << std::endl;

    file.close();

    return true;
}