// RETRIEVING THE WRENCH COLLECTION
if (!m_P->GetBtkC3DFileIO()->CanReadFile(filename)) return false; m_P->GetBtkC3DFileIO()->Read(filename, m_P->GetBtkAcquisition());
// Retrieve force platformsauto forceExtractor = btk::ForcePlatformsExtractor::New();forceExtractor->SetInput(m_P->GetBtkAcquisition());forceExtractor->Update();btk::ForcePlatformCollection::Pointer forcePlatforms = forceExtractor->GetOutput();
// Precompute global forces and momentsauto wrenchFilter = btk::ForcePlatformWrenchFilter::New();wrenchFilter->SetTransformToGlobalFrame(true);wrenchFilter->SetInput(forcePlatforms);wrenchFilter->Update();btk::WrenchCollection::Pointer pBtkwrenches = wrenchFilter->GetOutput();// QUERYING THE WRENCH COLLECTION
bool C3DFile::GetForceChannelValues(size_t plate, size_t frame, std::vector<std::vector<double> >& results) const{ if ((int)plate >= m_P->m_pBtkwrenches->GetItemNumber()) return false; results.resize(GetNbAnalogSamplesPerFrame(), std::vector<double>(9, 0.0));
for ( size_t s = 0; s < GetNbAnalogSamplesPerFrame(); s++) { size_t offset = frame*GetNbAnalogSamplesPerFrame();
if ( offset + s >= size_t(m_P->m_pBtkwrenches->GetItem(plate)->GetForce()->GetValues().size()) ) return false;
if ( offset + s >= size_t(m_P->m_pBtkwrenches->GetItem(plate)->GetMoment()->GetValues().size()) ) return false;
auto force = m_P->m_pBtkwrenches->GetItem(plate)->GetForce()->GetValues().row(offset + s); results[s][0] = force[0]; results[s][1] = force[1]; results[s][2] = force[2];
auto moment = m_P->m_pBtkwrenches->GetItem(plate)->GetMoment()->GetValues().row(offset + s); results[s][3] = moment[0]; results[s][4] = moment[1]; results[s][5] = moment[2]; auto position = m_P->m_pBtkwrenches->GetItem(plate)->GetPosition()->GetValues().row(offset + s);
results[s][6] = position[0];
results[s][7] = position[1];
results[s][8] = position[2];
}
return true;}
Thanks for your swift reply. I'll see if I can subclass GroundReactionWrenchFilter such that it calculates the COP (I think it would be a nice enhancement if the user can select which wrench position (COP or PWA) is being calculated.)
Regards, Ben
// C++11 code
// Load the content of the C3D fileauto root = ma::io::read("yourfile.c3d");// Extract all the force plates foundauto fps = root.findChildren<ma::instrument::ForcePlate*>();// For each force plates, compute the wrench at the centre of pressure expressed in the glbal frame.std::vector<ma::TimeSequence*> wrenches;for (const auto& fp : fps) wrenches.push_back(fp->wrench(ma::instrument::Location::CentreOfPressure));// ...// IMPORTANT: Delete the variable root as this was allocated on the heap.delete root;