Пример #1
0
void
AAKR::normalize(Math::Matrix& mean, Math::Matrix& std)
{
    // Resize mean and standard deviation variables.
    mean.resizeAndFill(1, sampleSize(), 0);
    std.resizeAndFill(1, sampleSize(), 0);

    // Compute mean.
    for (unsigned i = 0; i < sampleSize(); i++)
        mean(i) = sum(m_data.get(0, m_num_values - 1, i, i)) / m_num_values;

    // Compute standard deviation.
    for (unsigned j = 0; j < sampleSize(); j++)
    {
        double sum = 0;

        // Sum of the power of two difference
        // between the value and the mean.
        for (unsigned i = 0; i < m_num_values; i++)
            sum += std::pow(m_data(i, j) - mean(j), 2);

        // Standard deviation.
        std(j) = std::sqrt(sum / m_num_values);

        // Normalize each member of the data set.
        for (unsigned i = 0; i < m_num_values; i++)
        {
            if (std(j))
                m_norm(i, j) = (m_data(i, j) - mean(j)) / std(j);
            else
                m_norm(i, j) = 0;
        }
    }
}
Пример #2
0
TEST(MatrixTest, DetTest)
{
    const Math::Matrix mat1(
        {
            { -0.95880162984708284f,  0.24004047608997131f, -0.78172309932665407f, -0.11604124457222834f },
            { -0.36230592086261376f, -0.75778166876017261f,  0.33041059404631740f, -1.06001391941094836f },
            {  0.00260215210936187f,  1.27485610196385113f, -0.26149859846418033f, -0.59669701186364876f },
            {  0.36899429848485432f,  3.01720896813933104f,  2.10311476609438719f, -1.68627076626448269f }
        }
    );

    const float expectedDet1 = 4.07415413729671f;

    float ret1 = mat1.Det();
    EXPECT_TRUE(Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE));

    const Math::Matrix mat2(
        {
            { -1.0860073221346871f,  0.9150354098189495f, -0.2723201933559999f,  0.2922832160271507f },
            { -1.0248331304801788f, -2.5081237461125205f, -1.0277123574586633f, -0.2254690663329798f },
            { -1.4227635282899367f, -0.0403846809122684f,  0.9216148477171653f,  1.2517067488015878f },
            { -0.1160254467152022f,  0.8270675274393656f,  1.0327218739781614f, -0.3674886870220400f }
        }
    );

    const float expectedDet2 = -6.35122307880942f;

    float ret2 = mat2.Det();
    EXPECT_TRUE(Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE));
}
Пример #3
0
 DWI2QBI (const Math::Matrix<value_type>& FRT_SHT, Math::Matrix<value_type>& normalise_SHT, const DWI::Shells& shells) :
   FRT_SHT (FRT_SHT), 
   normalise_SHT (normalise_SHT), 
   shells (shells),
   dwi (FRT_SHT.columns()),
   qbi (FRT_SHT.rows()),
   amps (normalise ? normalise_SHT.rows() : 0) { }
Пример #4
0
    bool load_data (const Image::Iterator& pos) {
      Image::voxel_assign (dwi, pos);
      Image::voxel_assign (dt, pos);

      size_t nvox = dwi.dim (row_axis);
      if (mask) {
        size_t N = 0;
        Image::voxel_assign (*mask, pos);
        for ((*mask)[row_axis] = 0; (*mask)[row_axis] < mask->dim(row_axis); ++(*mask)[row_axis]) 
          if (mask->value())
            ++N;
        nvox = N;
      }
      if (!nvox) 
        return false;

      signals.allocate (nvox, dwi.dim (sig_axis));
      logsignals.allocate (nvox, dwi.dim (sig_axis));
      tensors.allocate (nvox, 7);

      size_t N = 0;
      for (dwi[row_axis] = 0; dwi[row_axis] < dwi.dim(row_axis); ++dwi[row_axis]) {
        if (mask) {
          (*mask)[row_axis] = dwi[row_axis];
          if (!mask->value()) continue;
        }
        for (dwi[sig_axis] = 0; dwi[sig_axis] < dwi.dim(sig_axis); ++dwi[sig_axis]) {
          cost_value_type val = std::max (cost_value_type (dwi.value()), cost_value_type (1.0));
          signals(N, dwi[sig_axis]) = val;
          logsignals(N, dwi[sig_axis]) = -Math::log (val);
        }
        ++N;
      }
      return true;
    }
Пример #5
0
void run ()
{

  DWI::Tractography::Properties properties;

  DWI::Tractography::Writer<> writer (argument.back(), properties);

  for (size_t n = 0; n < argument.size()-1; n++) {
    Math::Matrix<float> M;
    try {
      M.load (argument[n]);
      if (M.columns() != 3)
        throw Exception ("file \"" + argument[n] + "\" does not contain 3 columns - ignored");

      DWI::Tractography::Streamline<float> tck (M.rows());
      for (size_t i = 0; i < M.rows(); i++) {
        tck[i].set (M (i,0), M (i,1), M (i,2));
      }
      writer (tck);
      writer.total_count++;
    }
    catch (Exception) { }
  }

}
Пример #6
0
TEST(MatrixTest, CofactorTest)
{
    const Math::Matrix mat1(
        {
            {  0.610630320796245f,  1.059932357918312f, -1.581674311378210f,  1.782214448453331f },
            {  0.191028848211526f, -0.813898708757524f,  1.516114203870644f,  0.395202639476002f },
            {  0.335142750345279f, -0.346586619596529f,  0.545382042472336f, -0.879268918923072f },
            {  1.417588151657198f,  1.450841789070141f,  0.219080104196171f,  0.378724047481655f }
        }
    );

    const Math::Matrix expectedCofactors1(
        {
            { -2.402679369186782f,  2.282452509293019f,  1.722732204057644f, -0.746939701104385f },
            { -0.687677756877654f,  1.168949180331164f, -0.985354966837796f, -1.334071111592705f },
            { -5.115621958424845f,  4.229724770159009f,  2.529000630782808f,  1.481632618355891f },
            {  0.147480897398694f, -2.140677680337111f, -1.207189492265546f,  0.151236920408051f }
        }
    );

    for (int r = 0; r < 4; ++r)
    {
        for (int c = 0; c < 4; ++c)
        {
            float ret = mat1.Cofactor(r, c);
            float exp = expectedCofactors1.m[4*c+r];
            EXPECT_TRUE(Math::IsEqual(ret, exp, TEST_TOLERANCE));
        }
    }

    const Math::Matrix mat2(
        {
            {  0.9845099464982393f, -0.9091233416532389f, -0.6272243714245945f,  0.4645001858944354f },
            { -0.1333308471483736f,  0.9128181433725897f, -1.0937461393836190f,  0.3180936795928376f },
            { -0.0654324396846289f,  0.1014641705415945f,  1.5107709042683430f, -0.0240560430414690f },
            {  0.0179638644093347f, -1.0695585982782767f, -0.1741250853101032f,  1.0803106709464336f }
        }
    );

    const Math::Matrix expectedCofactors2(
        {
            {  2.0861102207614466f,  0.2989010779528912f,  0.0746276150537432f,  0.2732659822656097f },
            {  0.6850002886584565f,  1.5513169659641379f, -0.0503743176545917f,  1.5163672441575642f },
            {  1.2385556680997216f,  1.1827709562505695f,  1.2282813085138962f,  1.3483789679871401f },
            { -1.0710790241539783f, -0.5589604503588883f,  0.0100959837872308f,  1.1897872684455839f }
        }
    );


    for (int r = 0; r < 4; ++r)
    {
        for (int c = 0; c < 4; ++c)
        {
            float ret = mat2.Cofactor(r, c);
            float exp = expectedCofactors2.m[4*c+r];
            EXPECT_TRUE(Math::IsEqual(ret, exp, TEST_TOLERANCE));
        }
    }
}
Пример #7
0
void CalibrationWnd::calcAdcI2Curr()
{
    // Make linear assumption, e.i.
    //I = a*adc + b*1;
    Math::Matrix<2> XtX;
    Math::Vector<2> XtY;
    int sz = adcI.size();
    for ( int i=0; i<2; i++ )
    {
        QVector<int> * a;
        if ( i==0 )
            a = &adcI;
        else
            a = 0;
        for ( int j=0; j<2; j++ )
        {
            QVector<int> * b;
            if ( j==0 )
                b = &adcI;
            else
                b = 0;
            qreal v = 0.0;
            for ( int k=0; k<sz; k++ )
            {
                qreal va = ( a ) ? a->at( k ) : 1.0;
                qreal vb = ( b ) ? b->at( k ) : 1.0;
                v += va * vb;
            }
            XtX[i][j] = v;
        }

        qreal v = 0.0;
        for ( int k=0; k<sz; k++ )
        {
            qreal va = ( a ) ? a->at( k ) : 1.0;
            qreal vy = curr.at( k );
            v += va * vy;
        }
        XtY[i] = v;
    }
    // A = (XtX)^-1 * XtY;
    Math::Matrix<2> invXtX;
    invXtX = XtX.inv();
    Math::Vector<2> A;
    for ( int i=0; i<2; i++ )
    {
        qreal v = 0.0;
        for ( int j=0; j<2; j++ )
        {
            v += invXtX[i][j] * XtY[j];
        }
        A[i] = v;
    }
    aAdcI = A[0];
    bAdcI = A[1];
}
Пример #8
0
  void writeAsciiMatrix(const std::string& fname, const Math::Matrix<T,P,S>& M,
                        const std::string& meta, const bool trans = false) {
    Math::Range start(0,0);
    Math::Range end(M.rows(), M.cols());

    std::ofstream ofs(fname.c_str());
    if (!ofs.is_open())
      throw(std::runtime_error("Cannot open " + fname + " for writing."));
    MatrixWriteImpl<T,P,S,internal::BasicMatrixFormatter<T> >::write(ofs, M, meta, start, end, trans);
  }
Пример #9
0
void
TestMatrix::runSubTest18(double& res, double& expected, std::string& subTestName)
{
    expected = 1;
    subTestName = "simple_symmetric_invert";

#ifdef COSMO_LAPACK
    Math::SymmetricMatrix<double> mat(2, 2);
    mat(0, 0) = 2;
    mat(1, 1) = 3;
    mat(1, 0) = 1;

    mat.writeIntoTextFile("test_files/matrix_test_18_original.txt");

    Math::SymmetricMatrix<double> invMat = mat;
    invMat.invert();

    invMat.writeIntoTextFile("test_files/matrix_test_18_inverse.txt");

    Math::Matrix<double> prod = mat;
    prod *= invMat;
    prod.writeIntoTextFile("test_files/matrix_test_18_product.txt");

    res = 1;
    for(int i = 0; i < prod.rows(); ++i)
    {
        for(int j = 0; j < prod.rows(); ++j)
        {
            if(i == j)
            {
                if(!Math::areEqual(prod(i, j), 1.0, 1e-5))
                {
                    output_screen("FAIL! Diagonal element " << i << " must be 1 but it is " << prod(i, j) << std::endl);
                    res = 0;
                }
            }
            else
            {
                if(!Math::areEqual(prod(i, j), 0.0, 1e-5))
                {
                    output_screen("FAIL! Non-diagonal element " << i << " " << j << " must be 0 but it is " << prod(i, j) << std::endl);
                    res = 0;
                }
            }
        }
    }
#else
    output_screen_clean("This test (below) is skipped because Cosmo++ has not been linked to lapack" << std::endl);
    res = 1;
#endif
}
Пример #10
0
void run()
{
  InputBufferType dwi_buffer (argument[0], Image::Stride::contiguous_along_axis (3));
  Math::Matrix<cost_value_type> grad = DWI::get_valid_DW_scheme<cost_value_type> (dwi_buffer);

  size_t dwi_axis = 3;
  while (dwi_buffer.dim (dwi_axis) < 2) ++dwi_axis;
  INFO ("assuming DW images are stored along axis " + str (dwi_axis));

  Math::Matrix<cost_value_type> bmatrix;
  DWI::grad2bmatrix (bmatrix, grad);

  Math::Matrix<cost_value_type> binv (bmatrix.columns(), bmatrix.rows());
  Math::pinv (binv, bmatrix);

  int method = 1;
  Options opt = get_options ("method");
  if (opt.size()) method = opt[0][0];

  opt = get_options ("regularisation");
  cost_value_type regularisation = 5000.0;
  if (opt.size()) regularisation = opt[0][0];

  opt = get_options ("mask");
  Ptr<MaskBufferType> mask_buffer;
  Ptr<MaskBufferType::voxel_type> mask_vox;
  if (opt.size()){
    mask_buffer = new MaskBufferType (opt[0][0]);
    Image::check_dimensions (*mask_buffer, dwi_buffer, 0, 3);
    mask_vox = new MaskBufferType::voxel_type (*mask_buffer);
  }


  Image::Header dt_header (dwi_buffer);
  dt_header.set_ndim (4);
  dt_header.dim (3) = 6;
  dt_header.datatype() = DataType::Float32;
  dt_header.DW_scheme() = grad;

  OutputBufferType dt_buffer (argument[1], dt_header);

  InputBufferType::voxel_type dwi_vox (dwi_buffer);
  OutputBufferType::voxel_type dt_vox (dt_buffer);

  Image::ThreadedLoop loop ("estimating tensor components...", dwi_vox, 1, 0, 3);
  Processor processor (dwi_vox, dt_vox, mask_vox, bmatrix, binv, method, regularisation, loop.inner_axes()[0], dwi_axis);

  loop.run_outer (processor);
}
Пример #11
0
TEST(MatrixTest, InverseTest)
{
    const Math::Matrix mat1(
        {
            { -2.2829352811514658f, -0.9103222363187888f,  0.2792976509411680f, -0.7984393573193174f },
            {  2.4823665798689589f, -0.0599056759070980f,  0.3832364352926366f, -1.6404257204372739f },
            { -0.3841952272526398f, -0.8377700696457873f, -0.3416328338427138f,  1.1746577275723329f },
            {  0.1746031241954947f, -0.4952532117949962f,  0.2155084379835037f, -1.6586460437329220f }
        }
    );

    const Math::Matrix expectedInverse1(
        {
            { -0.119472603171041f,  0.331675963276297f,  0.187516809009720f, -0.137720814290806f },
            { -0.387591686166085f, -0.487284946727583f, -0.798527541290274f,  0.102991635972060f },
            {  2.601905603425902f,  2.606899016264679f, -0.528006148839176f, -4.204703326522837f },
            {  0.441220327151392f,  0.519128136207318f,  0.189567009205522f, -1.194469716136194f }
        }
    );

    Math::Matrix inverse1 = mat1.Inverse();

    EXPECT_TRUE(Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE));

    const Math::Matrix mat2(
        {
            { -0.05464332404298505f, -0.64357755258235749f, -0.13017671677619302f, -0.56742332785888006f },
            {  0.29048383600458222f, -0.91517047043724875f,  0.84517524415561684f,  0.51628195547960565f },
            {  0.00946488004480186f, -0.89077382212689293f,  0.73565573766341397f, -0.15932513521840930f },
            { -1.01244718912499132f, -0.27840911963972276f, -0.39189681211309862f,  1.18315064340192055f }
        }
    );

    const Math::Matrix expectedInverse2(
        {
            {  0.771302711132012f,  1.587542278361995f, -2.003075114445104f, -0.592574156227379f },
            { -1.208929259769431f, -0.786598967848473f,  0.607335305808052f, -0.154759693303324f },
            { -1.500037668208218f, -0.774300278997914f,  1.917800427261255f, -0.123268572651291f },
            { -0.121314770937944f,  0.916925149209746f, -0.935924950785014f,  0.260875394250671f }
        }
    );

    Math::Matrix inverse2 = mat2.Inverse();

    EXPECT_TRUE(Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE));
}
Пример #12
0
void
AAKR::computeDistance(Math::Matrix query)
{
    if (query.rows() != 1)
        throw std::runtime_error("unable to compute distance: reference is not row vector.");

    if ((unsigned)query.columns() != sampleSize())
        throw std::runtime_error("unable to compute distance: sample size does not match.");

    m_distances.fill(0.0);

    // Fill distances vector.
    for (unsigned i = 0; i < m_num_values; i++)
    {
        Math::Matrix q = query - m_norm.row(i);
        m_distances(i) = std::sqrt(sum(q * transpose(q)));
    };
}
Пример #13
0
void Render(Gfx::CGLDevice *device, Gfx::CModelFile *modelFile)
{
    device->BeginScene();

    Math::Matrix persp;
    Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f);
    device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);

    Math::Matrix id;
    id.LoadIdentity();
    device->SetTransform(Gfx::TRANSFORM_WORLD, id);

    Math::Matrix viewMat;
    Math::LoadTranslationMatrix(viewMat, TRANSLATION);
    Math::Matrix rot;
    Math::LoadRotationXZYMatrix(rot, ROTATION);
    viewMat = Math::MultiplyMatrices(viewMat, rot);
    device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);

    const std::vector<Gfx::ModelTriangle> &triangles = modelFile->GetTriangles();

    Gfx::VertexTex2 tri[3];

    for (int i = 0; i < static_cast<int>( triangles.size() ); ++i)
    {
        device->SetTexture(0, GetTexture(triangles[i].tex1Name));
        device->SetTexture(1, GetTexture(triangles[i].tex2Name));
        device->SetTextureEnabled(0, true);
        device->SetTextureEnabled(1, true);

        device->SetMaterial(triangles[i].material);

        tri[0] = triangles[i].p1;
        tri[1] = triangles[i].p2;
        tri[2] = triangles[i].p3;

        device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, tri, 3);
    }

    device->EndScene();
}
Пример #14
0
void
AAKR::add(Math::Matrix v)
{
    if (dataSize() == 0)
        throw std::runtime_error("unable to add: data window size is undefined.");

    if (v.rows() != 1)
        throw std::runtime_error("unable to add: new sample is not a row vector.");

    if (sampleSize() == 0)
        m_data.resize(dataSize(), v.columns());

    if ((unsigned)v.columns() != sampleSize())
        throw std::runtime_error("unable to add: sample size does not match.");

    // Write to the data set.
    m_data.set(m_index, m_index, 0, sampleSize() - 1, v);

    // Increment data set index.
    increment();
}
Пример #15
0
void TSmatrix::testInversion()
{
	Math::Matrix m = Math::Matrix::zeros(4,4);
	for (int i=0; i<3; i++)
		for (int j=0; j<3; j++)
			if (j<=i)
				m(i,j) = 1;
	m(3,3) = 1;
	Math::Matrix minv(4,4);
	Math::Matrix::invert(m, minv);
	

	Math::Matrix identity = Math::Matrix::eye(4);
	Math::Matrix minv2(4,4);
	m.linearSolve(minv2, identity);

	minv.sub(minv2);
	for (int i=0;i<4;i++)
		for (int j=0;j<4;j++)
			TEST_ASSERT(fabs(minv(i,j)) < 0.0001); 
}
Пример #16
0
void run () 
{
  Math::Matrix<value_type> directions = DWI::Directions::load_cartesian<value_type> (argument[0]);

  size_t num_permutations = 1e8;
  Options opt = get_options ("permutations");
  if (opt.size())
    num_permutations = opt[0][0];

  Shared eddy_shared (directions, num_permutations);
  Thread::run (Thread::multi (Processor (eddy_shared)), "eval thread");

  auto& signs = eddy_shared.get_best_signs();

  for (size_t n = 0; n < directions.rows(); ++n) 
    if (signs[n] < 0)
      directions.row(n) *= -1.0;

  bool cartesian = get_options("cartesian").size();
  DWI::Directions::save (directions, argument[1], cartesian);
}
Пример #17
0
    void solve_nonlinear () {
      for (size_t i = 0; i < signals.rows(); ++i) {
        const Math::Vector<cost_value_type> signal (signals.row(i));
        Math::Vector<cost_value_type> values (tensors.row(i));

        cost.set_voxel (&signal, &values);

        Math::Vector<cost_value_type> x (cost.size());
        cost.init (x);
        //Math::check_function_gradient (cost, x, 1e-10, true);

        Math::GradientDescent<Cost> optim (cost);
        try { optim.run (10000, 1e-8); }
        catch (Exception& E) {
          E.display();
        }

        //x = optim.state();
        //Math::check_function_gradient (cost, x, 1e-10, true);

        cost.get_values (values, optim.state());
      }
    }
Пример #18
0
void verify_matrix (Math::Matrix<float>& in, const node_t num_nodes)
{
  if (in.rows() != in.columns())
    throw Exception ("Connectome matrix is not square (" + str(in.rows()) + " x " + str(in.columns()) + ")");
  if (in.rows() != num_nodes)
    throw Exception ("Connectome matrix contains " + str(in.rows()) + " nodes; expected " + str(num_nodes));

  for (node_t row = 0; row != num_nodes; ++row) {
    for (node_t column = row+1; column != num_nodes; ++column) {

      const float lower_value = in (column, row);
      const float upper_value = in (row, column);

      if (upper_value && lower_value && (upper_value != lower_value))
        throw Exception ("Connectome matrix is not symmetrical");

      if (!upper_value && lower_value)
        in (row, column) = lower_value;

      in (column, row) = 0.0f;

  } }
}
Пример #19
0
    void save_bvecs_bvals (const Image::Header& header, const std::string& path)
    {

      std::string bvecs_path, bvals_path;
      if (path.size() >= 5 && path.substr (path.size() - 5, path.size()) == "bvecs") {
        bvecs_path = path;
        bvals_path = path.substr (0, path.size() - 5) + "bvals";
      } else if (path.size() >= 5 && path.substr (path.size() - 5, path.size()) == "bvals") {
        bvecs_path = path.substr (0, path.size() - 5) + "bvecs";
        bvals_path = path;
      } else {
        bvecs_path = path + "bvecs";
        bvals_path = path + "bvals";
      }

      const Math::Matrix<float>& grad (header.DW_scheme());
      Math::Matrix<float> G (grad.rows(), 3);

      // rotate vectors from scanner space to image space
      Math::Matrix<float> D (header.transform());
      Math::Permutation p (4);
      int signum;
      Math::LU::decomp (D, p, signum);
      Math::Matrix<float> image2scanner (4,4);
      Math::LU::inv (image2scanner, D, p);
      Math::Matrix<float> rotation = image2scanner.sub (0,3,0,3);
      Math::Matrix<float> grad_G = grad.sub (0, grad.rows(), 0, 3);
      Math::mult (G, float(0.0), float(1.0), CblasNoTrans, grad_G, CblasTrans, rotation);

      // deal with FSL requiring gradient directions to coincide with data strides
      // also transpose matrices in preparation for file output
      std::vector<size_t> order = Image::Stride::order (header, 0, 3);
      Math::Matrix<float> bvecs (3, grad.rows());
      Math::Matrix<float> bvals (1, grad.rows());
      for (size_t n = 0; n < G.rows(); ++n) {
        bvecs(0,n) = header.stride(order[0]) > 0 ? G(n,order[0]) : -G(n,order[0]);
        bvecs(1,n) = header.stride(order[1]) > 0 ? G(n,order[1]) : -G(n,order[1]);
        bvecs(2,n) = header.stride(order[2]) > 0 ? G(n,order[2]) : -G(n,order[2]);
        bvals(0,n) = grad(n,3);
      }

      bvecs.save (bvecs_path);
      bvals.save (bvals_path);

    }
Пример #20
0
void run () 
{
  try {
    Math::Matrix<value_type> directions = DWI::Directions::load_cartesian<value_type> (argument[0]);
    report (str(argument[0]), directions);
  }
  catch (Exception& E) {
    Math::Matrix<value_type> directions (str(argument[0]));
    DWI::normalise_grad (directions);
    if (directions.columns() < 3) 
      throw Exception ("unexpected matrix size for DW scheme \"" + str(argument[0]) + "\"");

    print (str(argument[0]) + " [ " + str(directions.rows()) + " volumes ]\n");
    DWI::Shells shells (directions);

    for (size_t n = 0; n < shells.count(); ++n) {
      Math::Matrix<value_type> subset (shells[n].count(), 3);
      for (size_t i = 0; i < subset.rows(); ++i)
        subset.row(i) = directions.row(shells[n].get_volumes()[i]).sub(0,3);
      report ("\nb = " + str(shells[n].get_mean()), subset);
    }
  }
}
Пример #21
0
//==============================================================================
//捕獲判定ボックスの生成
//==============================================================================
//[input]
//	pCam:カメラクラス
//==============================================================================
void CPlayer::CreateShootBox( CCamera *pCam, CSceneManager *pSceneMgr )
{
	Math::Matrix matTemp;
	Math::Matrix matWorld;
	
	/*初期化*/
	matTemp.Identity();
	matWorld.Identity();
	
	//matWorld = pCam->GetCamera()->WorldToView();
	
	//GetModelActor( 0 )->Collision_Check(
	
	//matWorld = pCam->GetCamera()->WorldToView();
	
	///*X軸回転*/
	matTemp.RotationX( toI( pCam->GetRotate().x ) );
	//
	matWorld *= matTemp;
	//
	///*Y軸回転*/
	matTemp.RotationY( toI( m_Rot.x - DEG_TO_ANGLE( 180 ) ) );
	
	matWorld *= matTemp;
	
	/*移動*/
	matTemp.Translation( m_vPos.x, m_vPos.y, m_vPos.z );
	
	matWorld *= matTemp;
	
	//Math::Vector3D vPt1 = pSceneMgr->GetSceneMgr()->TransformFromScreen( Math::Vector3D( 0, 0, 0 ) );
	//Math::Vector3D vPt2 = pSceneMgr->GetSceneMgr()->TransformFromScreen( Math::Vector3D( SCREEN_WIDTH, SCREEN_HEIGHT, 2.0f ) );
	
	/*ボックスの生成*/
	//m_ShootChkBox.
//	m_ShootChkBox.CreateBox( vPt1, vPt2, matWorld );
}
Пример #22
0
//==============================================================================
//捕獲判定ボックスの生成
//==============================================================================
void CPlayer::CreateCapBox()
{
	Math::Matrix matTemp;
	Math::Matrix matWorld;
	
	/*初期化*/
	matTemp.Identity();
	matWorld.Identity();
	
	/*回転*/
	matTemp.RotationY( toI( m_Rot.x - DEG_TO_ANGLE( 180 ) ) );
	
	matWorld *= matTemp;
	
	/*移動*/
	matTemp.Translation( m_vPos.x, m_vPos.y, m_vPos.z );
	
	matWorld *= matTemp;
	
	/*ボックスの生成*/
	m_CapChkBox.CreateBox( Math::Vector3D( -2, 0, 0 ), Math::Vector3D( 2, 5, 30 ), matWorld );
	

}
Пример #23
0
void
FixedwingAttitudeControl::task_main()
{
	/*
	 * do subscriptions
	 */
	_att_sub = orb_subscribe(ORB_ID(vehicle_attitude));
	_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
	_vcontrol_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
	_params_sub = orb_subscribe(ORB_ID(parameter_update));
	_manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
	_global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
	_vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
	_vehicle_land_detected_sub = orb_subscribe(ORB_ID(vehicle_land_detected));
	_battery_status_sub = orb_subscribe(ORB_ID(battery_status));

	parameters_update();

	/* get an initial update for all sensor and status data */
	vehicle_setpoint_poll();
	vehicle_control_mode_poll();
	vehicle_manual_poll();
	vehicle_status_poll();
	vehicle_land_detected_poll();
	battery_status_poll();
	_sub_airspeed.update();

	/* wakeup source */
	px4_pollfd_struct_t fds[1];

	/* Setup of loop */
	fds[0].fd = _att_sub;
	fds[0].events = POLLIN;

	_task_running = true;

	while (!_task_should_exit) {
		static int loop_counter = 0;

		/* wait for up to 500ms for data */
		int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 100);

		/* timed out - periodic check for _task_should_exit, etc. */
		if (pret == 0) {
			continue;
		}

		/* this is undesirable but not much we can do - might want to flag unhappy status */
		if (pret < 0) {
			PX4_WARN("poll error %d, %d", pret, errno);
			continue;
		}

		perf_begin(_loop_perf);

		/* only update parameters if they changed */
		bool params_updated = false;
		orb_check(_params_sub, &params_updated);

		if (params_updated) {
			/* read from param to clear updated flag */
			parameter_update_s update;
			orb_copy(ORB_ID(parameter_update), _params_sub, &update);

			/* update parameters from storage */
			parameters_update();
		}

		/* only run controller if attitude changed */
		if (fds[0].revents & POLLIN) {
			static uint64_t last_run = 0;
			float deltaT = (hrt_absolute_time() - last_run) / 1000000.0f;
			last_run = hrt_absolute_time();

			/* guard against too large deltaT's */
			if (deltaT > 1.0f) {
				deltaT = 0.01f;
			}

			/* load local copies */
			orb_copy(ORB_ID(vehicle_attitude), _att_sub, &_att);

			/* get current rotation matrix and euler angles from control state quaternions */
			math::Quaternion q_att(_att.q[0], _att.q[1], _att.q[2], _att.q[3]);
			_R = q_att.to_dcm();

			math::Vector<3> euler_angles;
			euler_angles = _R.to_euler();
			_roll    = euler_angles(0);
			_pitch   = euler_angles(1);
			_yaw     = euler_angles(2);

			if (_vehicle_status.is_vtol && _parameters.vtol_type == vtol_type::TAILSITTER) {
				/* vehicle is a tailsitter, we need to modify the estimated attitude for fw mode
				 *
				 * Since the VTOL airframe is initialized as a multicopter we need to
				 * modify the estimated attitude for the fixed wing operation.
				 * Since the neutral position of the vehicle in fixed wing mode is -90 degrees rotated around
				 * the pitch axis compared to the neutral position of the vehicle in multicopter mode
				 * we need to swap the roll and the yaw axis (1st and 3rd column) in the rotation matrix.
				 * Additionally, in order to get the correct sign of the pitch, we need to multiply
				 * the new x axis of the rotation matrix with -1
				 *
				 * original:			modified:
				 *
				 * Rxx  Ryx  Rzx		-Rzx  Ryx  Rxx
				 * Rxy	Ryy  Rzy		-Rzy  Ryy  Rxy
				 * Rxz	Ryz  Rzz		-Rzz  Ryz  Rxz
				 * */
				math::Matrix<3, 3> R_adapted = _R;		//modified rotation matrix

				/* move z to x */
				R_adapted(0, 0) = _R(0, 2);
				R_adapted(1, 0) = _R(1, 2);
				R_adapted(2, 0) = _R(2, 2);

				/* move x to z */
				R_adapted(0, 2) = _R(0, 0);
				R_adapted(1, 2) = _R(1, 0);
				R_adapted(2, 2) = _R(2, 0);

				/* change direction of pitch (convert to right handed system) */
				R_adapted(0, 0) = -R_adapted(0, 0);
				R_adapted(1, 0) = -R_adapted(1, 0);
				R_adapted(2, 0) = -R_adapted(2, 0);
				euler_angles = R_adapted.to_euler();  //adapted euler angles for fixed wing operation

				/* fill in new attitude data */
				_R = R_adapted;
				_roll    = euler_angles(0);
				_pitch   = euler_angles(1);
				_yaw     = euler_angles(2);

				/* lastly, roll- and yawspeed have to be swaped */
				float helper = _att.rollspeed;
				_att.rollspeed = -_att.yawspeed;
				_att.yawspeed = helper;
			}

			_sub_airspeed.update();
			vehicle_setpoint_poll();
			vehicle_control_mode_poll();
			vehicle_manual_poll();
			global_pos_poll();
			vehicle_status_poll();
			vehicle_land_detected_poll();
			battery_status_poll();

			// the position controller will not emit attitude setpoints in some modes
			// we need to make sure that this flag is reset
			_att_sp.fw_control_yaw = _att_sp.fw_control_yaw && _vcontrol_mode.flag_control_auto_enabled;

			/* lock integrator until control is started */
			bool lock_integrator = !(_vcontrol_mode.flag_control_rates_enabled && !_vehicle_status.is_rotary_wing);

			/* Simple handling of failsafe: deploy parachute if failsafe is on */
			if (_vcontrol_mode.flag_control_termination_enabled) {
				_actuators_airframe.control[7] = 1.0f;
				//warnx("_actuators_airframe.control[1] = 1.0f;");

			} else {
				_actuators_airframe.control[7] = 0.0f;
				//warnx("_actuators_airframe.control[1] = -1.0f;");
			}

			/* if we are in rotary wing mode, do nothing */
			if (_vehicle_status.is_rotary_wing && !_vehicle_status.is_vtol) {
				continue;
			}

			/* default flaps to center */
			float flap_control = 0.0f;

			/* map flaps by default to manual if valid */
			if (PX4_ISFINITE(_manual.flaps) && _vcontrol_mode.flag_control_manual_enabled
			    && fabsf(_parameters.flaps_scale) > 0.01f) {
				flap_control = 0.5f * (_manual.flaps + 1.0f) * _parameters.flaps_scale;

			} else if (_vcontrol_mode.flag_control_auto_enabled
				   && fabsf(_parameters.flaps_scale) > 0.01f) {
				flap_control = _att_sp.apply_flaps ? 1.0f * _parameters.flaps_scale : 0.0f;
			}

			// move the actual control value continuous with time, full flap travel in 1sec
			if (fabsf(_flaps_applied - flap_control) > 0.01f) {
				_flaps_applied += (_flaps_applied - flap_control) < 0 ? deltaT : -deltaT;

			} else {
				_flaps_applied = flap_control;
			}

			/* default flaperon to center */
			float flaperon_control = 0.0f;

			/* map flaperons by default to manual if valid */
			if (PX4_ISFINITE(_manual.aux2) && _vcontrol_mode.flag_control_manual_enabled
			    && fabsf(_parameters.flaperon_scale) > 0.01f) {
				flaperon_control = 0.5f * (_manual.aux2 + 1.0f) * _parameters.flaperon_scale;

			} else if (_vcontrol_mode.flag_control_auto_enabled
				   && fabsf(_parameters.flaperon_scale) > 0.01f) {
				flaperon_control = _att_sp.apply_flaps ? 1.0f * _parameters.flaperon_scale : 0.0f;
			}

			// move the actual control value continuous with time, full flap travel in 1sec
			if (fabsf(_flaperons_applied - flaperon_control) > 0.01f) {
				_flaperons_applied += (_flaperons_applied - flaperon_control) < 0 ? deltaT : -deltaT;

			} else {
				_flaperons_applied = flaperon_control;
			}

			// Check if we are in rattitude mode and the pilot is above the threshold on pitch
			if (_vcontrol_mode.flag_control_rattitude_enabled) {
				if (fabsf(_manual.y) > _parameters.rattitude_thres ||
				    fabsf(_manual.x) > _parameters.rattitude_thres) {
					_vcontrol_mode.flag_control_attitude_enabled = false;
				}
			}

			/* decide if in stabilized or full manual control */
			if (_vcontrol_mode.flag_control_rates_enabled) {
				/* scale around tuning airspeed */
				float airspeed;

				/* if airspeed is non-finite or not valid or if we are asked not to control it, we assume the normal average speed */
				const bool airspeed_valid = PX4_ISFINITE(_sub_airspeed.get().indicated_airspeed_m_s)
							    && ((_sub_airspeed.get().timestamp - hrt_absolute_time()) < 1e6);

				if (airspeed_valid) {
					/* prevent numerical drama by requiring 0.5 m/s minimal speed */
					airspeed = math::max(0.5f, _sub_airspeed.get().indicated_airspeed_m_s);

				} else {
					airspeed = _parameters.airspeed_trim;
					perf_count(_nonfinite_input_perf);
				}

				/*
				 * For scaling our actuators using anything less than the min (close to stall)
				 * speed doesn't make any sense - its the strongest reasonable deflection we
				 * want to do in flight and its the baseline a human pilot would choose.
				 *
				 * Forcing the scaling to this value allows reasonable handheld tests.
				 */
				float airspeed_scaling = _parameters.airspeed_trim / ((airspeed < _parameters.airspeed_min) ? _parameters.airspeed_min :
							 airspeed);

				/* Use min airspeed to calculate ground speed scaling region.
				 * Don't scale below gspd_scaling_trim
				 */
				float groundspeed = sqrtf(_global_pos.vel_n * _global_pos.vel_n +
							  _global_pos.vel_e * _global_pos.vel_e);
				float gspd_scaling_trim = (_parameters.airspeed_min * 0.6f);
				float groundspeed_scaler = gspd_scaling_trim / ((groundspeed < gspd_scaling_trim) ? gspd_scaling_trim : groundspeed);

				// in STABILIZED mode we need to generate the attitude setpoint
				// from manual user inputs
				if (!_vcontrol_mode.flag_control_climb_rate_enabled && !_vcontrol_mode.flag_control_offboard_enabled) {
					_att_sp.timestamp = hrt_absolute_time();
					_att_sp.roll_body = _manual.y * _parameters.man_roll_max + _parameters.rollsp_offset_rad;
					_att_sp.roll_body = math::constrain(_att_sp.roll_body, -_parameters.man_roll_max, _parameters.man_roll_max);
					_att_sp.pitch_body = -_manual.x * _parameters.man_pitch_max + _parameters.pitchsp_offset_rad;
					_att_sp.pitch_body = math::constrain(_att_sp.pitch_body, -_parameters.man_pitch_max, _parameters.man_pitch_max);
					_att_sp.yaw_body = 0.0f;
					_att_sp.thrust = _manual.z;

					Quatf q(Eulerf(_att_sp.roll_body, _att_sp.pitch_body, _att_sp.yaw_body));
					q.copyTo(_att_sp.q_d);
					_att_sp.q_d_valid = true;

					int instance;
					orb_publish_auto(_attitude_setpoint_id, &_attitude_sp_pub, &_att_sp, &instance, ORB_PRIO_DEFAULT);
				}

				/* reset integrals where needed */
				if (_att_sp.roll_reset_integral) {
					_roll_ctrl.reset_integrator();
				}

				if (_att_sp.pitch_reset_integral) {
					_pitch_ctrl.reset_integrator();
				}

				if (_att_sp.yaw_reset_integral) {
					_yaw_ctrl.reset_integrator();
					_wheel_ctrl.reset_integrator();
				}

				/* Reset integrators if the aircraft is on ground
				 * or a multicopter (but not transitioning VTOL)
				 */
				if (_vehicle_land_detected.landed
				    || (_vehicle_status.is_rotary_wing && !_vehicle_status.in_transition_mode)) {

					_roll_ctrl.reset_integrator();
					_pitch_ctrl.reset_integrator();
					_yaw_ctrl.reset_integrator();
					_wheel_ctrl.reset_integrator();
				}

				float roll_sp = _att_sp.roll_body;
				float pitch_sp = _att_sp.pitch_body;
				float yaw_sp = _att_sp.yaw_body;
				float throttle_sp = _att_sp.thrust;

				/* Prepare data for attitude controllers */
				struct ECL_ControlData control_input = {};
				control_input.roll = _roll;
				control_input.pitch = _pitch;
				control_input.yaw = _yaw;
				control_input.body_x_rate = _att.rollspeed;
				control_input.body_y_rate = _att.pitchspeed;
				control_input.body_z_rate = _att.yawspeed;
				control_input.roll_setpoint = roll_sp;
				control_input.pitch_setpoint = pitch_sp;
				control_input.yaw_setpoint = yaw_sp;
				control_input.airspeed_min = _parameters.airspeed_min;
				control_input.airspeed_max = _parameters.airspeed_max;
				control_input.airspeed = airspeed;
				control_input.scaler = airspeed_scaling;
				control_input.lock_integrator = lock_integrator;
				control_input.groundspeed = groundspeed;
				control_input.groundspeed_scaler = groundspeed_scaler;

				/* Run attitude controllers */
				if (_vcontrol_mode.flag_control_attitude_enabled) {
					if (PX4_ISFINITE(roll_sp) && PX4_ISFINITE(pitch_sp)) {
						_roll_ctrl.control_attitude(control_input);
						_pitch_ctrl.control_attitude(control_input);
						_yaw_ctrl.control_attitude(control_input); //runs last, because is depending on output of roll and pitch attitude
						_wheel_ctrl.control_attitude(control_input);

						/* Update input data for rate controllers */
						control_input.roll_rate_setpoint = _roll_ctrl.get_desired_rate();
						control_input.pitch_rate_setpoint = _pitch_ctrl.get_desired_rate();
						control_input.yaw_rate_setpoint = _yaw_ctrl.get_desired_rate();

						/* Run attitude RATE controllers which need the desired attitudes from above, add trim */
						float roll_u = _roll_ctrl.control_euler_rate(control_input);
						_actuators.control[actuator_controls_s::INDEX_ROLL] = (PX4_ISFINITE(roll_u)) ? roll_u + _parameters.trim_roll :
								_parameters.trim_roll;

						if (!PX4_ISFINITE(roll_u)) {
							_roll_ctrl.reset_integrator();
							perf_count(_nonfinite_output_perf);

							if (_debug && loop_counter % 10 == 0) {
								warnx("roll_u %.4f", (double)roll_u);
							}
						}

						float pitch_u = _pitch_ctrl.control_euler_rate(control_input);
						_actuators.control[actuator_controls_s::INDEX_PITCH] = (PX4_ISFINITE(pitch_u)) ? pitch_u + _parameters.trim_pitch :
								_parameters.trim_pitch;

						if (!PX4_ISFINITE(pitch_u)) {
							_pitch_ctrl.reset_integrator();
							perf_count(_nonfinite_output_perf);

							if (_debug && loop_counter % 10 == 0) {
								warnx("pitch_u %.4f, _yaw_ctrl.get_desired_rate() %.4f,"
								      " airspeed %.4f, airspeed_scaling %.4f,"
								      " roll_sp %.4f, pitch_sp %.4f,"
								      " _roll_ctrl.get_desired_rate() %.4f,"
								      " _pitch_ctrl.get_desired_rate() %.4f"
								      " att_sp.roll_body %.4f",
								      (double)pitch_u, (double)_yaw_ctrl.get_desired_rate(),
								      (double)airspeed, (double)airspeed_scaling,
								      (double)roll_sp, (double)pitch_sp,
								      (double)_roll_ctrl.get_desired_rate(),
								      (double)_pitch_ctrl.get_desired_rate(),
								      (double)_att_sp.roll_body);
							}
						}

						float yaw_u = 0.0f;

						if (_parameters.w_en && _att_sp.fw_control_yaw) {
							yaw_u = _wheel_ctrl.control_bodyrate(control_input);

						} else {
							yaw_u = _yaw_ctrl.control_euler_rate(control_input);
						}

						_actuators.control[actuator_controls_s::INDEX_YAW] = (PX4_ISFINITE(yaw_u)) ? yaw_u + _parameters.trim_yaw :
								_parameters.trim_yaw;

						/* add in manual rudder control in manual modes */
						if (_vcontrol_mode.flag_control_manual_enabled) {
							_actuators.control[actuator_controls_s::INDEX_YAW] += _manual.r;
						}

						if (!PX4_ISFINITE(yaw_u)) {
							_yaw_ctrl.reset_integrator();
							_wheel_ctrl.reset_integrator();
							perf_count(_nonfinite_output_perf);

							if (_debug && loop_counter % 10 == 0) {
								warnx("yaw_u %.4f", (double)yaw_u);
							}
						}

						/* throttle passed through if it is finite and if no engine failure was detected */
						_actuators.control[actuator_controls_s::INDEX_THROTTLE] = (PX4_ISFINITE(throttle_sp)
								&& !_vehicle_status.engine_failure) ? throttle_sp : 0.0f;

						/* scale effort by battery status */
						if (_parameters.bat_scale_en && _battery_status.scale > 0.0f &&
						    _actuators.control[actuator_controls_s::INDEX_THROTTLE] > 0.1f) {
							_actuators.control[actuator_controls_s::INDEX_THROTTLE] *= _battery_status.scale;
						}


						if (!PX4_ISFINITE(throttle_sp)) {
							if (_debug && loop_counter % 10 == 0) {
								warnx("throttle_sp %.4f", (double)throttle_sp);
							}
						}

					} else {
						perf_count(_nonfinite_input_perf);

						if (_debug && loop_counter % 10 == 0) {
							warnx("Non-finite setpoint roll_sp: %.4f, pitch_sp %.4f", (double)roll_sp, (double)pitch_sp);
						}
					}

				} else {
					// pure rate control
					_roll_ctrl.set_bodyrate_setpoint(_manual.y * _parameters.acro_max_x_rate_rad);
					_pitch_ctrl.set_bodyrate_setpoint(-_manual.x * _parameters.acro_max_y_rate_rad);
					_yaw_ctrl.set_bodyrate_setpoint(_manual.r * _parameters.acro_max_z_rate_rad);

					float roll_u = _roll_ctrl.control_bodyrate(control_input);
					_actuators.control[actuator_controls_s::INDEX_ROLL] = (PX4_ISFINITE(roll_u)) ? roll_u + _parameters.trim_roll :
							_parameters.trim_roll;

					float pitch_u = _pitch_ctrl.control_bodyrate(control_input);
					_actuators.control[actuator_controls_s::INDEX_PITCH] = (PX4_ISFINITE(pitch_u)) ? pitch_u + _parameters.trim_pitch :
							_parameters.trim_pitch;

					float yaw_u = _yaw_ctrl.control_bodyrate(control_input);
					_actuators.control[actuator_controls_s::INDEX_YAW] = (PX4_ISFINITE(yaw_u)) ? yaw_u + _parameters.trim_yaw :
							_parameters.trim_yaw;

					_actuators.control[actuator_controls_s::INDEX_THROTTLE] = PX4_ISFINITE(throttle_sp) ? throttle_sp : 0.0f;
				}

				/*
				 * Lazily publish the rate setpoint (for analysis, the actuators are published below)
				 * only once available
				 */
				_rates_sp.roll = _roll_ctrl.get_desired_bodyrate();
				_rates_sp.pitch = _pitch_ctrl.get_desired_bodyrate();
				_rates_sp.yaw = _yaw_ctrl.get_desired_bodyrate();

				_rates_sp.timestamp = hrt_absolute_time();

				if (_rate_sp_pub != nullptr) {
					/* publish the attitude rates setpoint */
					orb_publish(_rates_sp_id, _rate_sp_pub, &_rates_sp);

				} else if (_rates_sp_id) {
					/* advertise the attitude rates setpoint */
					_rate_sp_pub = orb_advertise(_rates_sp_id, &_rates_sp);
				}

				rate_ctrl_status_s rate_ctrl_status;
				rate_ctrl_status.timestamp = hrt_absolute_time();
				rate_ctrl_status.rollspeed = _att.rollspeed;
				rate_ctrl_status.pitchspeed = _att.pitchspeed;
				rate_ctrl_status.yawspeed = _att.yawspeed;
				rate_ctrl_status.rollspeed_integ = _roll_ctrl.get_integrator();
				rate_ctrl_status.pitchspeed_integ = _pitch_ctrl.get_integrator();
				rate_ctrl_status.yawspeed_integ = _yaw_ctrl.get_integrator();
				rate_ctrl_status.additional_integ1 = _wheel_ctrl.get_integrator();

				int instance;
				orb_publish_auto(ORB_ID(rate_ctrl_status), &_rate_ctrl_status_pub, &rate_ctrl_status, &instance, ORB_PRIO_DEFAULT);

			} else {
				/* manual/direct control */
				_actuators.control[actuator_controls_s::INDEX_ROLL] = _manual.y * _parameters.man_roll_scale + _parameters.trim_roll;
				_actuators.control[actuator_controls_s::INDEX_PITCH] = -_manual.x * _parameters.man_pitch_scale +
						_parameters.trim_pitch;
				_actuators.control[actuator_controls_s::INDEX_YAW] = _manual.r * _parameters.man_yaw_scale + _parameters.trim_yaw;
				_actuators.control[actuator_controls_s::INDEX_THROTTLE] = _manual.z;
			}

			// Add feed-forward from roll control output to yaw control output
			// This can be used to counteract the adverse yaw effect when rolling the plane
			_actuators.control[actuator_controls_s::INDEX_YAW] += _parameters.roll_to_yaw_ff * math::constrain(
						_actuators.control[actuator_controls_s::INDEX_ROLL], -1.0f, 1.0f);

			_actuators.control[actuator_controls_s::INDEX_FLAPS] = _flaps_applied;
			_actuators.control[5] = _manual.aux1;
			_actuators.control[actuator_controls_s::INDEX_AIRBRAKES] = _flaperons_applied;
			// FIXME: this should use _vcontrol_mode.landing_gear_pos in the future
			_actuators.control[7] = _manual.aux3;

			/* lazily publish the setpoint only once available */
			_actuators.timestamp = hrt_absolute_time();
			_actuators.timestamp_sample = _att.timestamp;
			_actuators_airframe.timestamp = hrt_absolute_time();
			_actuators_airframe.timestamp_sample = _att.timestamp;

			/* Only publish if any of the proper modes are enabled */
			if (_vcontrol_mode.flag_control_rates_enabled ||
			    _vcontrol_mode.flag_control_attitude_enabled ||
			    _vcontrol_mode.flag_control_manual_enabled) {
				/* publish the actuator controls */
				if (_actuators_0_pub != nullptr) {
					orb_publish(_actuators_id, _actuators_0_pub, &_actuators);

				} else if (_actuators_id) {
					_actuators_0_pub = orb_advertise(_actuators_id, &_actuators);
				}

				if (_actuators_2_pub != nullptr) {
					/* publish the actuator controls*/
					orb_publish(ORB_ID(actuator_controls_2), _actuators_2_pub, &_actuators_airframe);

				} else {
					/* advertise and publish */
					_actuators_2_pub = orb_advertise(ORB_ID(actuator_controls_2), &_actuators_airframe);
				}
			}
		}

		loop_counter++;
		perf_end(_loop_perf);
	}

	warnx("exiting.\n");

	_control_task = -1;
	_task_running = false;
}
Пример #24
0
void CCloud::Draw()
{
    if (! m_enabled) return;
    if (m_level == 0.0f) return;
    if (m_lines.empty()) return;

    std::vector<VertexTex2> vertices((m_brickCount+2)*2, VertexTex2());

    float iDeep = m_engine->GetDeepView();
    float deep = (m_brickCount*m_brickSize)/2.0f;
    m_engine->SetDeepView(deep);
    m_engine->SetFocus(m_engine->GetFocus());
    m_engine->UpdateMatProj();  // increases the depth of view

    float fogStart = deep*0.15f;
    float fogEnd   = deep*0.24f;

    CDevice* device = m_engine->GetDevice();

    // TODO: do this better?
    device->SetFogParams(FOG_LINEAR, m_engine->GetFogColor( m_engine->GetRankView() ),
                        fogStart, fogEnd, 1.0f);

    device->SetTransform(TRANSFORM_VIEW, m_engine->GetMatView());

    Material material;
    material.diffuse = m_diffuse;
    material.ambient = m_ambient;
    m_engine->SetMaterial(material);

    m_engine->SetTexture(m_fileName, 0);
    m_engine->SetTexture(m_fileName, 1);

    m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_FOG | ENG_RSTATE_WRAP);

    Math::Matrix matrix;
    matrix.LoadIdentity();
    device->SetTransform(TRANSFORM_WORLD, matrix);

    float size = m_brickSize/2.0f;
    Math::Vector eye = m_engine->GetEyePt();
    Math::Vector n = Math::Vector(0.0f, -1.0f, 0.0f);

    // Draws all the lines
    for (int i = 0; i < static_cast<int>( m_lines.size() ); i++)
    {
        Math::Vector pos;
        pos.y = m_level;
        pos.z = m_lines[i].pz;
        pos.x = m_lines[i].px1;

        int vertexIndex = 0;

        Math::Vector p;
        Math::Point uv1, uv2;

        p.x = pos.x-size;
        p.z = pos.z+size;
        p.y = pos.y;
        AdjustLevel(p, eye, deep, uv1, uv2);
        vertices[vertexIndex++] = VertexTex2(p, n, uv1, uv2);

        p.x = pos.x-size;
        p.z = pos.z-size;
        p.y = pos.y;
        AdjustLevel(p, eye, deep, uv1, uv2);
        vertices[vertexIndex++] = VertexTex2(p, n, uv1, uv2);

        for (int j = 0; j < m_lines[i].len; j++)
        {
            p.x = pos.x+size;
            p.z = pos.z+size;
            p.y = pos.y;
            AdjustLevel(p, eye, deep, uv1, uv2);
            vertices[vertexIndex++] = VertexTex2(p, n, uv1, uv2);

            p.x = pos.x+size;
            p.z = pos.z-size;
            p.y = pos.y;
            AdjustLevel(p, eye, deep, uv1, uv2);
            vertices[vertexIndex++] = VertexTex2(p, n, uv1, uv2);

            pos.x += size*2.0f;
        }

        device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, &vertices[0], vertexIndex);
        m_engine->AddStatisticTriangle(vertexIndex - 2);
    }

    m_engine->SetDeepView(iDeep);
    m_engine->SetFocus(m_engine->GetFocus());
    m_engine->UpdateMatProj();  // gives depth to initial
}
Пример #25
0
void
FixedwingAttitudeControl::task_main()
{
	/*
	 * do subscriptions
	 */
	_att_sp_sub = orb_subscribe(ORB_ID(vehicle_attitude_setpoint));
	_ctrl_state_sub = orb_subscribe(ORB_ID(control_state));
	_accel_sub = orb_subscribe_multi(ORB_ID(sensor_accel), 0);
	_vcontrol_mode_sub = orb_subscribe(ORB_ID(vehicle_control_mode));
	_params_sub = orb_subscribe(ORB_ID(parameter_update));
	_manual_sub = orb_subscribe(ORB_ID(manual_control_setpoint));
	_global_pos_sub = orb_subscribe(ORB_ID(vehicle_global_position));
	_vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
	_vehicle_land_detected_sub = orb_subscribe(ORB_ID(vehicle_land_detected));

	parameters_update();

	/* get an initial update for all sensor and status data */
	vehicle_setpoint_poll();
	vehicle_accel_poll();
	vehicle_control_mode_poll();
	vehicle_manual_poll();
	vehicle_status_poll();
	vehicle_land_detected_poll();

	/* wakeup source */
	px4_pollfd_struct_t fds[2];

	/* Setup of loop */
	fds[0].fd = _params_sub;
	fds[0].events = POLLIN;
	fds[1].fd = _ctrl_state_sub;
	fds[1].events = POLLIN;

	_task_running = true;

	while (!_task_should_exit) {
		static int loop_counter = 0;

		/* wait for up to 500ms for data */
		int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 100);

		/* timed out - periodic check for _task_should_exit, etc. */
		if (pret == 0) {
			continue;
		}

		/* this is undesirable but not much we can do - might want to flag unhappy status */
		if (pret < 0) {
			warn("poll error %d, %d", pret, errno);
			continue;
		}

		perf_begin(_loop_perf);

		/* only update parameters if they changed */
		if (fds[0].revents & POLLIN) {
			/* read from param to clear updated flag */
			struct parameter_update_s update;
			orb_copy(ORB_ID(parameter_update), _params_sub, &update);

			/* update parameters from storage */
			parameters_update();
		}

		/* only run controller if attitude changed */
		if (fds[1].revents & POLLIN) {
			static uint64_t last_run = 0;
			float deltaT = (hrt_absolute_time() - last_run) / 1000000.0f;
			last_run = hrt_absolute_time();

			/* guard against too large deltaT's */
			if (deltaT > 1.0f) {
				deltaT = 0.01f;
			}

			/* load local copies */
			orb_copy(ORB_ID(control_state), _ctrl_state_sub, &_ctrl_state);


			/* get current rotation matrix and euler angles from control state quaternions */
			math::Quaternion q_att(_ctrl_state.q[0], _ctrl_state.q[1], _ctrl_state.q[2], _ctrl_state.q[3]);
			_R = q_att.to_dcm();

			math::Vector<3> euler_angles;
			euler_angles = _R.to_euler();
			_roll    = euler_angles(0);
			_pitch   = euler_angles(1);
			_yaw     = euler_angles(2);

			if (_vehicle_status.is_vtol && _parameters.vtol_type == 0) {
				/* vehicle is a tailsitter, we need to modify the estimated attitude for fw mode
				 *
				 * Since the VTOL airframe is initialized as a multicopter we need to
				 * modify the estimated attitude for the fixed wing operation.
				 * Since the neutral position of the vehicle in fixed wing mode is -90 degrees rotated around
				 * the pitch axis compared to the neutral position of the vehicle in multicopter mode
				 * we need to swap the roll and the yaw axis (1st and 3rd column) in the rotation matrix.
				 * Additionally, in order to get the correct sign of the pitch, we need to multiply
				 * the new x axis of the rotation matrix with -1
				 *
				 * original:			modified:
				 *
				 * Rxx  Ryx  Rzx		-Rzx  Ryx  Rxx
				 * Rxy	Ryy  Rzy		-Rzy  Ryy  Rxy
				 * Rxz	Ryz  Rzz		-Rzz  Ryz  Rxz
				 * */
				math::Matrix<3, 3> R_adapted = _R;		//modified rotation matrix

				/* move z to x */
				R_adapted(0, 0) = _R(0, 2);
				R_adapted(1, 0) = _R(1, 2);
				R_adapted(2, 0) = _R(2, 2);

				/* move x to z */
				R_adapted(0, 2) = _R(0, 0);
				R_adapted(1, 2) = _R(1, 0);
				R_adapted(2, 2) = _R(2, 0);

				/* change direction of pitch (convert to right handed system) */
				R_adapted(0, 0) = -R_adapted(0, 0);
				R_adapted(1, 0) = -R_adapted(1, 0);
				R_adapted(2, 0) = -R_adapted(2, 0);
				euler_angles = R_adapted.to_euler();  //adapted euler angles for fixed wing operation

				/* fill in new attitude data */
				_R = R_adapted;
				_roll    = euler_angles(0);
				_pitch   = euler_angles(1);
				_yaw     = euler_angles(2);

				/* lastly, roll- and yawspeed have to be swaped */
				float helper = _ctrl_state.roll_rate;
				_ctrl_state.roll_rate = -_ctrl_state.yaw_rate;
				_ctrl_state.yaw_rate = helper;
			}

			vehicle_setpoint_poll();

			vehicle_accel_poll();

			vehicle_control_mode_poll();

			vehicle_manual_poll();

			global_pos_poll();

			vehicle_status_poll();

			vehicle_land_detected_poll();

			// the position controller will not emit attitude setpoints in some modes
			// we need to make sure that this flag is reset
			_att_sp.fw_control_yaw = _att_sp.fw_control_yaw && _vcontrol_mode.flag_control_auto_enabled;

			/* lock integrator until control is started */
			bool lock_integrator;

			if (_vcontrol_mode.flag_control_attitude_enabled && !_vehicle_status.is_rotary_wing) {
				lock_integrator = false;

			} else {
				lock_integrator = true;
			}

			/* Simple handling of failsafe: deploy parachute if failsafe is on */
			if (_vcontrol_mode.flag_control_termination_enabled) {
				_actuators_airframe.control[7] = 1.0f;
				//warnx("_actuators_airframe.control[1] = 1.0f;");

			} else {
				_actuators_airframe.control[7] = 0.0f;
				//warnx("_actuators_airframe.control[1] = -1.0f;");
			}

			/* if we are in rotary wing mode, do nothing */
			if (_vehicle_status.is_rotary_wing && !_vehicle_status.is_vtol) {
				continue;
			}

			/* default flaps to center */
			float flaps_control = 0.0f;

			static float delta_flaps = 0;

			/* map flaps by default to manual if valid */
			if (PX4_ISFINITE(_manual.flaps) && _vcontrol_mode.flag_control_manual_enabled) {
				flaps_control = 0.5f * (_manual.flaps + 1.0f) * _parameters.flaps_scale;

			} else if (_vcontrol_mode.flag_control_auto_enabled) {
				flaps_control = _att_sp.apply_flaps ? 1.0f * _parameters.flaps_scale : 0.0f;
			}

			// move the actual control value continuous with time
			static hrt_abstime t_flaps_changed = 0;

			if (fabsf(flaps_control - _flaps_cmd_last) > 0.01f) {
				t_flaps_changed = hrt_absolute_time();
				delta_flaps = flaps_control - _flaps_cmd_last;
				_flaps_cmd_last = flaps_control;
			}

			static float flaps_applied = 0.0f;

			if (fabsf(flaps_applied - flaps_control) > 0.01f) {
				flaps_applied = (flaps_control - delta_flaps) + (float)hrt_elapsed_time(&t_flaps_changed) * (delta_flaps) / 1000000;
			}

			/* default flaperon to center */
			float flaperon = 0.0f;

			static float delta_flaperon = 0.0f;

			/* map flaperons by default to manual if valid */
			if (PX4_ISFINITE(_manual.aux2) && _vcontrol_mode.flag_control_manual_enabled) {
				flaperon = 0.5f * (_manual.aux2 + 1.0f) * _parameters.flaperon_scale;

			} else if (_vcontrol_mode.flag_control_auto_enabled) {
				flaperon = _att_sp.apply_flaps ? 1.0f * _parameters.flaperon_scale : 0.0f;
			}

			// move the actual control value continuous with time
			static hrt_abstime t_flaperons_changed = 0;

			if (fabsf(flaperon - _flaperons_cmd_last) > 0.01f) {
				t_flaperons_changed = hrt_absolute_time();
				delta_flaperon = flaperon - _flaperons_cmd_last;
				_flaperons_cmd_last = flaperon;
			}

			static float flaperon_applied = 0.0f;

			if (fabsf(flaperon_applied - flaperon) > 0.01f) {
				flaperon_applied = (flaperon - delta_flaperon) + (float)hrt_elapsed_time(&t_flaperons_changed) *
						   (delta_flaperon) / 1000000;
			}

			/* decide if in stabilized or full manual control */
			if (_vcontrol_mode.flag_control_attitude_enabled) {
				/* scale around tuning airspeed */
				float airspeed;

				/* if airspeed is not updating, we assume the normal average speed */
				if (bool nonfinite = !PX4_ISFINITE(_ctrl_state.airspeed) || !_ctrl_state.airspeed_valid) {
					airspeed = _parameters.airspeed_trim;

					if (nonfinite) {
						perf_count(_nonfinite_input_perf);
					}

				} else {
					/* prevent numerical drama by requiring 0.5 m/s minimal speed */
					airspeed = math::max(0.5f, _ctrl_state.airspeed);
				}

				/*
				 * For scaling our actuators using anything less than the min (close to stall)
				 * speed doesn't make any sense - its the strongest reasonable deflection we
				 * want to do in flight and its the baseline a human pilot would choose.
				 *
				 * Forcing the scaling to this value allows reasonable handheld tests.
				 */
				float airspeed_scaling = _parameters.airspeed_trim / ((airspeed < _parameters.airspeed_min) ? _parameters.airspeed_min :
							 airspeed);

				/* Use min airspeed to calculate ground speed scaling region.
				 * Don't scale below gspd_scaling_trim
				 */
				float groundspeed = sqrtf(_global_pos.vel_n * _global_pos.vel_n +
							  _global_pos.vel_e * _global_pos.vel_e);
				float gspd_scaling_trim = (_parameters.airspeed_min * 0.6f);
				float groundspeed_scaler = gspd_scaling_trim / ((groundspeed < gspd_scaling_trim) ? gspd_scaling_trim : groundspeed);

				float roll_sp = _parameters.rollsp_offset_rad;
				float pitch_sp = _parameters.pitchsp_offset_rad;
				float yaw_sp = 0.0f;
				float yaw_manual = 0.0f;
				float throttle_sp = 0.0f;

				/* Read attitude setpoint from uorb if
				 * - velocity control or position control is enabled (pos controller is running)
				 * - manual control is disabled (another app may send the setpoint, but it should
				 *   for sure not be set from the remote control values)
				 */
				if (_vcontrol_mode.flag_control_auto_enabled ||
				    !_vcontrol_mode.flag_control_manual_enabled) {
					/* read in attitude setpoint from attitude setpoint uorb topic */
					roll_sp = _att_sp.roll_body + _parameters.rollsp_offset_rad;
					pitch_sp = _att_sp.pitch_body + _parameters.pitchsp_offset_rad;
					yaw_sp = _att_sp.yaw_body;
					throttle_sp = _att_sp.thrust;

					/* reset integrals where needed */
					if (_att_sp.roll_reset_integral) {
						_roll_ctrl.reset_integrator();
					}

					if (_att_sp.pitch_reset_integral) {
						_pitch_ctrl.reset_integrator();
					}

					if (_att_sp.yaw_reset_integral) {
						_yaw_ctrl.reset_integrator();
						_wheel_ctrl.reset_integrator();
					}

				} else if (_vcontrol_mode.flag_control_velocity_enabled) {

					/* the pilot does not want to change direction,
					 * take straight attitude setpoint from position controller
					 */
					if (fabsf(_manual.y) < 0.01f && fabsf(_roll) < 0.2f) {
						roll_sp = _att_sp.roll_body + _parameters.rollsp_offset_rad;

					} else {
						roll_sp = (_manual.y * _parameters.man_roll_max)
							  + _parameters.rollsp_offset_rad;
					}

					pitch_sp = _att_sp.pitch_body + _parameters.pitchsp_offset_rad;
					throttle_sp = _att_sp.thrust;

					/* reset integrals where needed */
					if (_att_sp.roll_reset_integral) {
						_roll_ctrl.reset_integrator();
					}

					if (_att_sp.pitch_reset_integral) {
						_pitch_ctrl.reset_integrator();
					}

					if (_att_sp.yaw_reset_integral) {
						_yaw_ctrl.reset_integrator();
						_wheel_ctrl.reset_integrator();
					}

				} else if (_vcontrol_mode.flag_control_altitude_enabled) {
					/*
					 * Velocity should be controlled and manual is enabled.
					*/
					roll_sp = (_manual.y * _parameters.man_roll_max) + _parameters.rollsp_offset_rad;
					pitch_sp = _att_sp.pitch_body + _parameters.pitchsp_offset_rad;
					throttle_sp = _att_sp.thrust;

					/* reset integrals where needed */
					if (_att_sp.roll_reset_integral) {
						_roll_ctrl.reset_integrator();
					}

					if (_att_sp.pitch_reset_integral) {
						_pitch_ctrl.reset_integrator();
					}

					if (_att_sp.yaw_reset_integral) {
						_yaw_ctrl.reset_integrator();
						_wheel_ctrl.reset_integrator();
					}

				} else {
					/*
					 * Scale down roll and pitch as the setpoints are radians
					 * and a typical remote can only do around 45 degrees, the mapping is
					 * -1..+1 to -man_roll_max rad..+man_roll_max rad (equivalent for pitch)
					 *
					 * With this mapping the stick angle is a 1:1 representation of
					 * the commanded attitude.
					 *
					 * The trim gets subtracted here from the manual setpoint to get
					 * the intended attitude setpoint. Later, after the rate control step the
					 * trim is added again to the control signal.
					 */
					roll_sp = (_manual.y * _parameters.man_roll_max) + _parameters.rollsp_offset_rad;
					pitch_sp = -(_manual.x * _parameters.man_pitch_max) + _parameters.pitchsp_offset_rad;
					/* allow manual control of rudder deflection */
					yaw_manual = _manual.r;
					throttle_sp = _manual.z;

					/*
					 * in manual mode no external source should / does emit attitude setpoints.
					 * emit the manual setpoint here to allow attitude controller tuning
					 * in attitude control mode.
					 */
					struct vehicle_attitude_setpoint_s att_sp;
					att_sp.timestamp = hrt_absolute_time();
					att_sp.roll_body = roll_sp;
					att_sp.pitch_body = pitch_sp;
					att_sp.yaw_body = 0.0f - _parameters.trim_yaw;
					att_sp.thrust = throttle_sp;

					/* lazily publish the setpoint only once available */
					if (_attitude_sp_pub != nullptr) {
						/* publish the attitude setpoint */
						orb_publish(_attitude_setpoint_id, _attitude_sp_pub, &att_sp);

					} else if (_attitude_setpoint_id) {
						/* advertise and publish */
						_attitude_sp_pub = orb_advertise(_attitude_setpoint_id, &att_sp);
					}
				}

				/* If the aircraft is on ground reset the integrators */
				if (_vehicle_land_detected.landed || _vehicle_status.is_rotary_wing) {
					_roll_ctrl.reset_integrator();
					_pitch_ctrl.reset_integrator();
					_yaw_ctrl.reset_integrator();
					_wheel_ctrl.reset_integrator();
				}

				/* Prepare speed_body_u and speed_body_w */
				float speed_body_u = _R(0, 0) * _global_pos.vel_n + _R(1, 0) * _global_pos.vel_e + _R(2, 0) * _global_pos.vel_d;
				float speed_body_v = _R(0, 1) * _global_pos.vel_n + _R(1, 1) * _global_pos.vel_e + _R(2, 1) * _global_pos.vel_d;
				float speed_body_w = _R(0, 2) * _global_pos.vel_n + _R(1, 2) * _global_pos.vel_e + _R(2, 2) * _global_pos.vel_d;

				/* Prepare data for attitude controllers */
				struct ECL_ControlData control_input = {};
				control_input.roll = _roll;
				control_input.pitch = _pitch;
				control_input.yaw = _yaw;
				control_input.roll_rate = _ctrl_state.roll_rate;
				control_input.pitch_rate = _ctrl_state.pitch_rate;
				control_input.yaw_rate = _ctrl_state.yaw_rate;
				control_input.speed_body_u = speed_body_u;
				control_input.speed_body_v = speed_body_v;
				control_input.speed_body_w = speed_body_w;
				control_input.acc_body_x = _accel.x;
				control_input.acc_body_y = _accel.y;
				control_input.acc_body_z = _accel.z;
				control_input.roll_setpoint = roll_sp;
				control_input.pitch_setpoint = pitch_sp;
				control_input.yaw_setpoint = yaw_sp;
				control_input.airspeed_min = _parameters.airspeed_min;
				control_input.airspeed_max = _parameters.airspeed_max;
				control_input.airspeed = airspeed;
				control_input.scaler = airspeed_scaling;
				control_input.lock_integrator = lock_integrator;
				control_input.groundspeed = groundspeed;
				control_input.groundspeed_scaler = groundspeed_scaler;

				_yaw_ctrl.set_coordinated_method(_parameters.y_coordinated_method);

				/* Run attitude controllers */
				if (PX4_ISFINITE(roll_sp) && PX4_ISFINITE(pitch_sp)) {
					_roll_ctrl.control_attitude(control_input);
					_pitch_ctrl.control_attitude(control_input);
					_yaw_ctrl.control_attitude(control_input); //runs last, because is depending on output of roll and pitch attitude
					_wheel_ctrl.control_attitude(control_input);

					/* Update input data for rate controllers */
					control_input.roll_rate_setpoint = _roll_ctrl.get_desired_rate();
					control_input.pitch_rate_setpoint = _pitch_ctrl.get_desired_rate();
					control_input.yaw_rate_setpoint = _yaw_ctrl.get_desired_rate();

					/* Run attitude RATE controllers which need the desired attitudes from above, add trim */
					float roll_u = _roll_ctrl.control_bodyrate(control_input);
					_actuators.control[0] = (PX4_ISFINITE(roll_u)) ? roll_u + _parameters.trim_roll : _parameters.trim_roll;

					if (!PX4_ISFINITE(roll_u)) {
						_roll_ctrl.reset_integrator();
						perf_count(_nonfinite_output_perf);

						if (_debug && loop_counter % 10 == 0) {
							warnx("roll_u %.4f", (double)roll_u);
						}
					}

					float pitch_u = _pitch_ctrl.control_bodyrate(control_input);
					_actuators.control[1] = (PX4_ISFINITE(pitch_u)) ? pitch_u + _parameters.trim_pitch : _parameters.trim_pitch;

					if (!PX4_ISFINITE(pitch_u)) {
						_pitch_ctrl.reset_integrator();
						perf_count(_nonfinite_output_perf);

						if (_debug && loop_counter % 10 == 0) {
							warnx("pitch_u %.4f, _yaw_ctrl.get_desired_rate() %.4f,"
							      " airspeed %.4f, airspeed_scaling %.4f,"
							      " roll_sp %.4f, pitch_sp %.4f,"
							      " _roll_ctrl.get_desired_rate() %.4f,"
							      " _pitch_ctrl.get_desired_rate() %.4f"
							      " att_sp.roll_body %.4f",
							      (double)pitch_u, (double)_yaw_ctrl.get_desired_rate(),
							      (double)airspeed, (double)airspeed_scaling,
							      (double)roll_sp, (double)pitch_sp,
							      (double)_roll_ctrl.get_desired_rate(),
							      (double)_pitch_ctrl.get_desired_rate(),
							      (double)_att_sp.roll_body);
						}
					}

					float yaw_u = 0.0f;

					if (_att_sp.fw_control_yaw == true) {
						yaw_u = _wheel_ctrl.control_bodyrate(control_input);
					}

					else {
						yaw_u = _yaw_ctrl.control_bodyrate(control_input);
					}

					_actuators.control[2] = (PX4_ISFINITE(yaw_u)) ? yaw_u + _parameters.trim_yaw : _parameters.trim_yaw;

					/* add in manual rudder control */
					_actuators.control[2] += yaw_manual;

					if (!PX4_ISFINITE(yaw_u)) {
						_yaw_ctrl.reset_integrator();
						_wheel_ctrl.reset_integrator();
						perf_count(_nonfinite_output_perf);

						if (_debug && loop_counter % 10 == 0) {
							warnx("yaw_u %.4f", (double)yaw_u);
						}
					}

					/* throttle passed through if it is finite and if no engine failure was
					 * detected */
					_actuators.control[3] = (PX4_ISFINITE(throttle_sp) &&
								 !(_vehicle_status.engine_failure ||
								   _vehicle_status.engine_failure_cmd)) ?
								throttle_sp : 0.0f;

					if (!PX4_ISFINITE(throttle_sp)) {
						if (_debug && loop_counter % 10 == 0) {
							warnx("throttle_sp %.4f", (double)throttle_sp);
						}
					}

				} else {
					perf_count(_nonfinite_input_perf);

					if (_debug && loop_counter % 10 == 0) {
						warnx("Non-finite setpoint roll_sp: %.4f, pitch_sp %.4f", (double)roll_sp, (double)pitch_sp);
					}
				}

				/*
				 * Lazily publish the rate setpoint (for analysis, the actuators are published below)
				 * only once available
				 */
				_rates_sp.roll = _roll_ctrl.get_desired_rate();
				_rates_sp.pitch = _pitch_ctrl.get_desired_rate();
				_rates_sp.yaw = _yaw_ctrl.get_desired_rate();

				_rates_sp.timestamp = hrt_absolute_time();

				if (_rate_sp_pub != nullptr) {
					/* publish the attitude rates setpoint */
					orb_publish(_rates_sp_id, _rate_sp_pub, &_rates_sp);

				} else if (_rates_sp_id) {
					/* advertise the attitude rates setpoint */
					_rate_sp_pub = orb_advertise(_rates_sp_id, &_rates_sp);
				}

			} else {
				/* manual/direct control */
				_actuators.control[actuator_controls_s::INDEX_ROLL] = _manual.y + _parameters.trim_roll;
				_actuators.control[actuator_controls_s::INDEX_PITCH] = -_manual.x + _parameters.trim_pitch;
				_actuators.control[actuator_controls_s::INDEX_YAW] = _manual.r + _parameters.trim_yaw;
				_actuators.control[actuator_controls_s::INDEX_THROTTLE] = _manual.z;
			}

			_actuators.control[actuator_controls_s::INDEX_FLAPS] = flaps_applied;
			_actuators.control[5] = _manual.aux1;
			_actuators.control[actuator_controls_s::INDEX_AIRBRAKES] = flaperon_applied;
			_actuators.control[7] = _manual.aux3;

			/* lazily publish the setpoint only once available */
			_actuators.timestamp = hrt_absolute_time();
			_actuators.timestamp_sample = _ctrl_state.timestamp;
			_actuators_airframe.timestamp = hrt_absolute_time();
			_actuators_airframe.timestamp_sample = _ctrl_state.timestamp;

			/* Only publish if any of the proper modes are enabled */
			if (_vcontrol_mode.flag_control_rates_enabled ||
			    _vcontrol_mode.flag_control_attitude_enabled ||
			    _vcontrol_mode.flag_control_manual_enabled) {
				/* publish the actuator controls */
				if (_actuators_0_pub != nullptr) {
					orb_publish(_actuators_id, _actuators_0_pub, &_actuators);

				} else if (_actuators_id) {
					_actuators_0_pub = orb_advertise(_actuators_id, &_actuators);
				}

				if (_actuators_2_pub != nullptr) {
					/* publish the actuator controls*/
					orb_publish(ORB_ID(actuator_controls_2), _actuators_2_pub, &_actuators_airframe);

				} else {
					/* advertise and publish */
					_actuators_2_pub = orb_advertise(ORB_ID(actuator_controls_2), &_actuators_airframe);
				}
			}
		}

		loop_counter++;
		perf_end(_loop_perf);
	}

	warnx("exiting.\n");

	_control_task = -1;
	_task_running = false;
}
Пример #26
0
void CLightning::Draw()
{
    if (!m_lightningExists) return;
    if (m_phase != LP_FLASH) return;

    CDevice* device = m_engine->GetDevice();

    Math::Matrix mat;
    mat.LoadIdentity();
    device->SetTransform(TRANSFORM_WORLD, mat);

    m_engine->SetTexture("effect00.png");
    m_engine->SetState(ENG_RSTATE_TTEXTURE_BLACK);

    Math::Point texInf;
    texInf.x = 64.5f/256.0f;
    texInf.y = 33.0f/256.0f;
    Math::Point texSup;
    texSup.x = 95.5f/256.0f;
    texSup.y = 34.0f/256.0f;  // blank

    Math::Vector p1 = m_pos;
    Math::Vector eye = m_engine->GetEyePt();
    float a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
    Math::Vector n = Math::Normalize(p1-eye);

    Math::Vector corner[4];
    Vertex vertex[4];

    for (int i = 0; i < FLASH_SEGMENTS-1; i++)
    {
        Math::Vector p2 = p1;
        p2.y += 8.0f+0.2f*i;

        Math::Point rot;

        Math::Vector p = p1;
        p.x += m_width[i];
        rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
        corner[0].x = rot.x+m_shift[i].x;
        corner[0].y = p1.y;
        corner[0].z = rot.y+m_shift[i].y;
        rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
        corner[1].x = rot.x+m_shift[i].x;
        corner[1].y = p1.y;
        corner[1].z = rot.y+m_shift[i].y;

        p = p2;
        p.x += m_width[i+1];
        rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
        corner[2].x = rot.x+m_shift[i+1].x;
        corner[2].y = p2.y;
        corner[2].z = rot.y+m_shift[i+1].y;
        rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
        corner[3].x = rot.x+m_shift[i+1].x;
        corner[3].y = p2.y;
        corner[3].z = rot.y+m_shift[i+1].y;

        if (p2.y < p1.y)
        {
            vertex[0] = Vertex(corner[1], n, Math::Point(texSup.x, texSup.y));
            vertex[1] = Vertex(corner[0], n, Math::Point(texInf.x, texSup.y));
            vertex[2] = Vertex(corner[3], n, Math::Point(texSup.x, texInf.y));
            vertex[3] = Vertex(corner[2], n, Math::Point(texInf.x, texInf.y));
        }
        else
        {
            vertex[0] = Vertex(corner[0], n, Math::Point(texSup.x, texSup.y));
            vertex[1] = Vertex(corner[1], n, Math::Point(texInf.x, texSup.y));
            vertex[2] = Vertex(corner[2], n, Math::Point(texSup.x, texInf.y));
            vertex[3] = Vertex(corner[3], n, Math::Point(texInf.x, texInf.y));
        }

        device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
        m_engine->AddStatisticTriangle(2);

        p1 = p2;
    }
}
Пример #27
0
void TestApp::OnUpdate()
{
	if (mWindow.HandleMessage())
	{
		mRunning = false;
	}
	else
	{
		// Update our time
		mTimer.Update();

		// Update animation
		mAnimationController.Update(mTimer.GetElapsedTime() * 1000.0f);

		// Camera movement
		const float kMoveSpeed = 10.0f;
		const float kTurnSpeed = 5.0f;
		if (mKeyStates[VK_UP] || mKeyStates['W'])
		{
			mCamera.Walk(kMoveSpeed * mTimer.GetElapsedTime());
		}
		else if (mKeyStates[VK_DOWN] || mKeyStates['S'])
		{
			mCamera.Walk(-kMoveSpeed * mTimer.GetElapsedTime());
		}
		else if (mKeyStates[VK_RIGHT] || mKeyStates['D'])
		{
			mCamera.Strafe(kMoveSpeed * mTimer.GetElapsedTime());
		}
		else if (mKeyStates[VK_LEFT] || mKeyStates['A'])
		{
			mCamera.Strafe(-kMoveSpeed * mTimer.GetElapsedTime());
		}
		else if (mKeyStates['K'])
		{
			mDrawSkeleton = !mDrawSkeleton;
		}
		
		// Render scene
		mGraphicsSystem.BeginRender(Color::Black());

		mRenderer.SetCamera(mCamera);

		if(mDrawSkeleton)
		{
			DrawSkeleton();
		}

		// for each mesh
		for(u32 i = 0; i < mModel.mMeshes.size(); ++i)
		{
			const Mesh* mesh = mModel.mMeshes[i];
			// copy vertexweights
			const VertexWeights& vertexWeights = mesh->GetVertexWeights();

			// if vw not empty
			if(!vertexWeights.empty())
			{
				const std::vector<Math::Matrix>& boneTransforms = mAnimationController.BoneTransforms();
				// copy vertices
				const Mesh::Vertex* vertices = mesh->GetVertices();
				// get vertex count
				const u32 count = mesh->GetVertexCount();
				// create new vertexarray of size vertex count
				Mesh::Vertex* newVertices = new Mesh::Vertex[count];
				// for each vertex
				for(u32 j = 0; j < count; ++j)
				{
					// create zero transform
					Math::Matrix transform;
					transform = transform.Zero();

					// copy boneweights from this vertexweight
					const BoneWeights& boneWeights = vertexWeights[j];

					if(i == 1)
					{
						transform = boneTransforms[22];
					}
					else
					{
						// for each boneweight
						for(u32 k = 0; k < boneWeights.size(); ++k)
						{
							const BoneWeight& boneWeight = boneWeights[k];
						
							transform = transform + boneTransforms[i == 1 ? 22 : boneWeight.boneIndex] * boneWeight.weight;
						}
					}
					// insert position into newVertices 
					newVertices[j].position = Math::TransformCoord(vertices[j].position, transform);
					// insert normal into newVertices 
					newVertices[j].normal = Math::Normalize(Math::TransformNormal(vertices[j].normal, transform));
					// insert texcoord into newVertices
					newVertices[j].texcoord = vertices[j].texcoord;
				}
				// update mesh buffer at index with newVertices
				mModel.mMeshBuffers[i]->UpdateBuffer(mGraphicsSystem, newVertices, count);
				// safedelete newVertices
				SafeDeleteArray(newVertices);
			}
		}

		mModel.Render(mRenderer);

		SimpleDraw::Render(mCamera);

		mGraphicsSystem.EndRender();
	}

	
}
Пример #28
0
void CalibrationWnd::calcDac2Volt()
{
    // Make linear assumption, e.i.
    //V = a*dacLow + b*dacHigh + c*1;
    Math::Matrix<> XtX;
    Math::Vector<> XtY;
    int sz = dacLowV.size();
    for ( int i=0; i<3; i++ )
    {
        QVector<int> * a;
        if ( i==0 )
            a = &dacLowV;
        else if ( i==1 )
            a = &dacHighV;
        else
            a = 0;
        for ( int j=0; j<3; j++ )
        {
            QVector<int> * b;
            if ( j==0 )
                b = &dacLowV;
            else if ( j==1 )
                b = &dacHighV;
            else
                b = 0;
            qreal v = 0.0;
            for ( int k=0; k<sz; k++ )
            {
                qreal va = ( a ) ? a->at( k ) : 1.0;
                qreal vb = ( b ) ? b->at( k ) : 1.0;
                v += va * vb;
            }
            XtX[i][j] = v;
        }

        qreal v = 0.0;
        for ( int k=0; k<sz; k++ )
        {
            qreal va = ( a ) ? a->at( k ) : 1.0;
            qreal vy = volt.at( k );
            v += va * vy;
        }
        XtY[i] = v;
    }
    // A = (XtX)^-1 * XtY;
    Math::Matrix<> invXtX;
    invXtX = XtX.inv();
    Math::Vector<> A;
    for ( int i=0; i<3; i++ )
    {
        qreal v = 0.0;
        for ( int j=0; j<3; j++ )
        {
            v += invXtX[i][j] * XtY[j];
        }
        A[i] = v;
    }
    aDacLow  = A[0];
    aDacHigh = A[1];
    bDac     = A[2];
}
Пример #29
0
void
TestMatrix::runSubTestEigen(double& res, double& expected, std::string& subTestName, bool pd)
{
    subTestName = "simple_symmetric_eigen";
    if(pd)
        subTestName = "simple_symmetric_positive_eigen";

#ifdef COSMO_LAPACK
    Math::SymmetricMatrix<double> mat(3, 3);
    mat(0, 0) = 3;
    mat(1, 1) = 10;
    mat(2, 2) = 4;
    mat(0, 2) = 2;

    std::vector<double> eigenvals;
    Math::Matrix<double> eigenvecs;

    const int info = mat.getEigen(&eigenvals, &eigenvecs, pd);
    if(info)
    {
        output_screen_clean("FAIL! Eigenvalue/eigenvector decomposition failed. Info = " << info << std::endl);
        res = 0;
        return;
    }

    //output_screen_clean("Eigenvalues: " << eigenvals[0] << ", " << eigenvals[1] << ", " << eigenvals[2] << std::endl);

    if(pd)
        eigenvecs.writeIntoTextFile("test_files/matrix_test_eigenvecs.txt");
    else
        eigenvecs.writeIntoTextFile("test_files/matrix_test_eigenvecs_pos.txt");

    res = 1;
    expected = 1;

    Math::Matrix<double> m = mat;

    for(int i = 0; i < 3; ++i)
    {
        Math::Matrix<double> v = eigenvecs.getCol(i);
        Math::Matrix<double> prod = m * v;
        for(int j = 0; j < 3; ++j)
        {
            if(!Math::areEqual(prod(j, 0), eigenvals[i] * v(j, 0), 1e-5))
            {
                output_screen_clean("FAIL! The eigenvalue " << i << " times the eigenvector doesn't match the matrix times the eigenvector." << std::endl);
                output_screen_clean("\tLooking at index " << j << ", expected " << eigenvals[i] * v(j, 0) << " obtained " << prod(j, 0) << std::endl);
                res = 0;
            }
        }
    }

    Math::Matrix<double> diag = eigenvecs.getTranspose() * mat * eigenvecs;

    for(int i = 0; i < 3; ++i)
    {
        for(int j = 0; j < 3; ++j)
        {
            if(i == j)
            {
                if(!Math::areEqual(diag(i, i), eigenvals[i], 1e-5))
                {
                    output_screen_clean("FAIL! The diagonalized matrix has " << diag(i, i) << " on the diagonal at index " << i << " but the corresponding eigenvalue is " << eigenvals[i] << std::endl);
                    res = 0;
                }
            }
            else
            {
                if(!Math::areEqual(diag(i, j), 0.0, 1e-5))
                {
                    output_screen_clean("FAIL! The diagonalized matrix has " << diag(i, j) << " as the off-diagonal element (" << i << ", " << j << "). Must be 0." << std::endl);
                    res = 0;
                }
            }
        }
    }

#else
    output_screen_clean("This test (below) is skipped because Cosmo++ has not been linked to lapack" << std::endl);
    res = 1;
    expected = 1;
#endif
}
Пример #30
0
void Render(Gfx::CGLDevice *device)
{
    device->BeginScene();

    /* Unlit part of scene */

    device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false);
    device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); // Double-sided drawing

    Math::Matrix persp;
    Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 50.0f);
    device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);


    Math::Matrix viewMat;
    Math::Matrix mat;

    viewMat.LoadIdentity();

    Math::LoadRotationXMatrix(mat, -ROTATION.x);
    viewMat = Math::MultiplyMatrices(viewMat, mat);

    Math::LoadRotationYMatrix(mat, -ROTATION.y);
    viewMat = Math::MultiplyMatrices(viewMat, mat);

    Math::LoadTranslationMatrix(mat, -TRANSLATION);
    viewMat = Math::MultiplyMatrices(viewMat, mat);

    device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);

    Math::Matrix worldMat;
    worldMat.LoadIdentity();
    device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);

    Gfx::VertexCol line[2] = {};

    for (int x = -40; x <= 40; ++x)
    {
        line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
        line[0].coord.z = -40;
        line[0].coord.x = x;
        line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
        line[1].coord.z =  40;
        line[1].coord.x = x;
        device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
    }

    for (int z = -40; z <= 40; ++z)
    {
        line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
        line[0].coord.z = z;
        line[0].coord.x = -40;
        line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
        line[1].coord.z = z;
        line[1].coord.x =  40;
        device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
    }


    Gfx::VertexCol quad[6] = {};

    quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f);
    quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f);
    quad[2].coord = Math::Vector(-1.0f,  1.0f, 0.0f);
    quad[3].coord = Math::Vector( 1.0f,  1.0f, 0.0f);

    for (int i = 0; i < 6; ++i)
        quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f);

    Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f));
    device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);

    device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);

    for (int i = 0; i < 6; ++i)
        quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f);

    Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f));
    device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);

    int planes = device->ComputeSphereVisibility(Math::Vector(0.0f, 0.0f, 0.0f), 1.0f);
    printf("Planes:");
    if (planes == 0)
        printf(" (none)");

    if (planes & Gfx::FRUSTUM_PLANE_LEFT)
        printf(" LEFT");

    if (planes & Gfx::FRUSTUM_PLANE_RIGHT)
        printf(" RIGHT");

    if (planes & Gfx::FRUSTUM_PLANE_BOTTOM)
        printf(" BOTTOM");

    if (planes & Gfx::FRUSTUM_PLANE_TOP)
        printf(" TOP");

    if (planes & Gfx::FRUSTUM_PLANE_FRONT)
        printf(" FRONT");

    if (planes & Gfx::FRUSTUM_PLANE_BACK)
        printf(" BACK");

    printf("\n");

    device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);

    for (int i = 0; i < 6; ++i)
        quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f);

    Math::LoadTranslationMatrix(worldMat, Math::Vector(10.0f, 4.5f, 5.0f));
    device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);

    device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);

    /* Moving lit cube */
    device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true);
    device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); // Culling (CCW faces)

    device->SetGlobalAmbient(Gfx::Color(0.4f, 0.4f, 0.4f));

    Gfx::Light light1;
    light1.type = Gfx::LIGHT_POINT;
    light1.position = Math::Vector(10.0f, 4.5f, 5.0f);
    light1.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
    light1.diffuse = Gfx::Color(1.0f, 0.1f, 0.1f);
    light1.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
    device->SetLight(0, light1);
    device->SetLightEnabled(0, true);

    /*Gfx::Light light2;
    device->SetLight(1, light2);
    device->SetLightEnabled(1, true);*/

    Gfx::Material material;
    material.ambient = Gfx::Color(0.3f, 0.3f, 0.3f);
    material.diffuse = Gfx::Color(0.8f, 0.7f, 0.6f);
    material.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
    device->SetMaterial(material);

    const Gfx::Vertex cube[6][4] =
    {
        {
            // Front
            Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f,  0.0f, -1.0f)),
            Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f,  0.0f, -1.0f)),
            Gfx::Vertex(Math::Vector(-1.0f,  1.0f, -1.0f), Math::Vector( 0.0f,  0.0f, -1.0f)),
            Gfx::Vertex(Math::Vector( 1.0f,  1.0f, -1.0f), Math::Vector( 0.0f,  0.0f, -1.0f))
        },

        {
            // Back
            Gfx::Vertex(Math::Vector( 1.0f, -1.0f,  1.0f), Math::Vector( 0.0f,  0.0f,  1.0f)),
            Gfx::Vertex(Math::Vector(-1.0f, -1.0f,  1.0f), Math::Vector( 0.0f,  0.0f,  1.0f)),
            Gfx::Vertex(Math::Vector( 1.0f,  1.0f,  1.0f), Math::Vector( 0.0f,  0.0f,  1.0f)),
            Gfx::Vertex(Math::Vector(-1.0f,  1.0f,  1.0f), Math::Vector( 0.0f,  0.0f,  1.0f))
        },

        {
            // Top
            Gfx::Vertex(Math::Vector(-1.0f,  1.0f, -1.0f), Math::Vector( 0.0f,  1.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f,  1.0f, -1.0f), Math::Vector( 0.0f,  1.0f,  0.0f)),
            Gfx::Vertex(Math::Vector(-1.0f,  1.0f,  1.0f), Math::Vector( 0.0f,  1.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f,  1.0f,  1.0f), Math::Vector( 0.0f,  1.0f,  0.0f))
        },

        {
            // Bottom
            Gfx::Vertex(Math::Vector(-1.0f, -1.0f,  1.0f), Math::Vector( 0.0f, -1.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f, -1.0f,  1.0f), Math::Vector( 0.0f, -1.0f,  0.0f)),
            Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f,  0.0f))
        },

        {
            // Left
            Gfx::Vertex(Math::Vector(-1.0f, -1.0f,  1.0f), Math::Vector(-1.0f,  0.0f,  0.0f)),
            Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector(-1.0f,  0.0f,  0.0f)),
            Gfx::Vertex(Math::Vector(-1.0f,  1.0f,  1.0f), Math::Vector(-1.0f,  0.0f,  0.0f)),
            Gfx::Vertex(Math::Vector(-1.0f,  1.0f, -1.0f), Math::Vector(-1.0f,  0.0f,  0.0f))
        },

        {
            // Right
            Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 1.0f,  0.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f, -1.0f,  1.0f), Math::Vector( 1.0f,  0.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f,  1.0f, -1.0f), Math::Vector( 1.0f,  0.0f,  0.0f)),
            Gfx::Vertex(Math::Vector( 1.0f,  1.0f,  1.0f), Math::Vector( 1.0f,  0.0f,  0.0f))
        }
    };

    Math::Matrix cubeTrans;
    Math::LoadTranslationMatrix(cubeTrans, Math::Vector(10.0f, 2.0f, 5.0f));
    Math::Matrix cubeRot;
    Math::LoadRotationMatrix(cubeRot, Math::Vector(0.0f, 1.0f, 0.0f), CUBE_ORBIT);
    Math::Matrix cubeRotInv;
    Math::LoadRotationMatrix(cubeRotInv, Math::Vector(0.0f, 1.0f, 0.0f), -CUBE_ORBIT);
    Math::Matrix cubeTransRad;
    Math::LoadTranslationMatrix(cubeTransRad, Math::Vector(0.0f, 0.0f, 6.0f));
    worldMat = Math::MultiplyMatrices(cubeTransRad, cubeRotInv);
    worldMat = Math::MultiplyMatrices(cubeRot, worldMat);
    worldMat = Math::MultiplyMatrices(cubeTrans, worldMat);
    device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);

    for (int i = 0; i < 6; ++i)
        device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, cube[i], 4);

    device->EndScene();
}