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; } } }
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)); }
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) { }
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; }
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) { } } }
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)); } } }
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]; }
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); }
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 }
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); }
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)); }
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))); }; }
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(); }
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(); }
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); }
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); }
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()); } }
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; } } }
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); }
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); } } }
//============================================================================== //捕獲判定ボックスの生成 //============================================================================== //[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 ); }
//============================================================================== //捕獲判定ボックスの生成 //============================================================================== 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 ); }
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, ¶ms_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; }
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 }
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; }
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; } }
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(); } }
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]; }
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 }
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(); }