216 lines
6.5 KiB
C++
216 lines
6.5 KiB
C++
|
/*
|
||
|
* Copyright (C) 2015 Open Source Robotics Foundation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <boost/program_options.hpp>
|
||
|
#include <gazebo/gazebo.hh>
|
||
|
#include <gazebo/common/common.hh>
|
||
|
#include <gazebo/physics/physics.hh>
|
||
|
|
||
|
/////////////////////////////////////////////////
|
||
|
int main(int _argc, char **_argv)
|
||
|
{
|
||
|
boost::program_options::options_description desc("Data collection options");
|
||
|
|
||
|
// Maximum number of collection iterations.
|
||
|
int maxIterations = 2000;
|
||
|
// Number of timesteps between samples.
|
||
|
int sampleTimesteps = 1;
|
||
|
// How much to scale the actuator's maximum torque by
|
||
|
float maxTorqueAdj = 2;
|
||
|
|
||
|
desc.add_options()("max_iter,i", boost::program_options::value<int>(),
|
||
|
"number of collection iterations")
|
||
|
("sample_ts,s", boost::program_options::value<int>(),
|
||
|
"number of timesteps between samples")
|
||
|
("torque_scale,t", boost::program_options::value<float>(),
|
||
|
"scale factor for applied torque");
|
||
|
|
||
|
boost::program_options::variables_map vm;
|
||
|
boost::program_options::store(boost::program_options::parse_command_line(
|
||
|
_argc, _argv, desc), vm);
|
||
|
boost::program_options::notify(vm);
|
||
|
|
||
|
if (vm.count("max_iter"))
|
||
|
{
|
||
|
maxIterations = vm["max_iter"].as<int>();
|
||
|
}
|
||
|
|
||
|
if (vm.count("sample_ts"))
|
||
|
{
|
||
|
sampleTimesteps = vm["sample_ts"].as<int>();
|
||
|
}
|
||
|
|
||
|
if (vm.count("torque_scale"))
|
||
|
{
|
||
|
maxTorqueAdj = vm["sample_ts"].as<float>();
|
||
|
}
|
||
|
|
||
|
// The joint index which we are collecting data on.
|
||
|
unsigned int index;
|
||
|
// The torque we are commanding to the actuator
|
||
|
float maxTorque;
|
||
|
|
||
|
// Initialize gazebo.
|
||
|
gazebo::setupServer(_argc, _argv);
|
||
|
|
||
|
// Load a world with two models: one actuated, one not
|
||
|
gazebo::physics::WorldPtr world =
|
||
|
gazebo::loadWorld("../actuator_example.world");
|
||
|
if (!world)
|
||
|
{
|
||
|
std::cout << "Could not load world actuator_example" << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Get the models and pointers to their joints
|
||
|
std::vector<std::string> modelNames;
|
||
|
modelNames.push_back("actuator_example");
|
||
|
modelNames.push_back("unactuated_example");
|
||
|
|
||
|
std::string jointName;
|
||
|
|
||
|
std::vector<gazebo::physics::JointPtr> joints;
|
||
|
|
||
|
for (unsigned int i = 0; i < modelNames.size(); i++)
|
||
|
{
|
||
|
gazebo::physics::ModelPtr model = world->GetModel(modelNames[i]);
|
||
|
if (!model)
|
||
|
{
|
||
|
std::cout << "Couldn't find model: " << modelNames[i] << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (modelNames[i].compare("actuator_example") == 0)
|
||
|
{
|
||
|
const sdf::ElementPtr modelSDF = model->GetSDF();
|
||
|
// Find the ActuatorPlugin SDF block
|
||
|
if (!modelSDF->HasElement("plugin"))
|
||
|
{
|
||
|
std::cout << "ERROR: couldn't find index element." << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
sdf::ElementPtr elem = modelSDF->GetElement("plugin");
|
||
|
while (elem->GetAttribute("filename")->GetAsString().
|
||
|
compare("libActuatorPlugin.so"))
|
||
|
{
|
||
|
elem = elem->GetNextElement("plugin");
|
||
|
}
|
||
|
|
||
|
if (!elem->HasElement("actuator"))
|
||
|
{
|
||
|
std::cout << "ERROR: couldn't find actuator element" << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
elem = elem->GetElement("actuator");
|
||
|
|
||
|
if (!elem->HasElement("index"))
|
||
|
{
|
||
|
std::cout << "ERROR: couldn't find index element." << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
index = elem->GetElement("index")->Get<unsigned int>();
|
||
|
|
||
|
if (!elem->HasElement("max_torque"))
|
||
|
{
|
||
|
std::cout << "ERROR: couldn't find max_torque element." << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
maxTorque = maxTorqueAdj*elem->GetElement("max_torque")->Get<float>();
|
||
|
|
||
|
if (!elem->HasElement("joint"))
|
||
|
{
|
||
|
std::cout << "ERROR: couldn't find joint element." << std::endl;
|
||
|
return -1;
|
||
|
}
|
||
|
jointName = elem->GetElement("joint")->Get<std::string>();
|
||
|
}
|
||
|
|
||
|
gazebo::physics::JointPtr joint = model->GetJoint(jointName);
|
||
|
if (!joint)
|
||
|
{
|
||
|
std::cout << "Couldn't find joint " << jointName << " for model "
|
||
|
<< modelNames[i] << std::endl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
joints.push_back(joint);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create a data directory
|
||
|
boost::filesystem::path path("../data");
|
||
|
if (!boost::filesystem::exists(path))
|
||
|
{
|
||
|
boost::filesystem::create_directories(path);
|
||
|
}
|
||
|
// Open a file for recording data
|
||
|
std::ofstream fileStream;
|
||
|
fileStream.open((path.string() + "/data.csv").c_str());
|
||
|
// Push initial file headings
|
||
|
fileStream << "actuated_joint_pos\tactuated_joint_vel\t"
|
||
|
<< "actuated_joint_torque\tunactuated_joint_pos\t"
|
||
|
<< "unactuated_joint_vel\tunactuated_joint_torque" << std::endl;
|
||
|
|
||
|
// Run the simulation for a fixed number of iterations.
|
||
|
std::cout << "Collecting data for " << maxIterations << " iterations."
|
||
|
<< std::endl;
|
||
|
|
||
|
for (unsigned int i = 0; i < maxIterations; ++i)
|
||
|
{
|
||
|
for (unsigned int j = 0; j < joints.size(); ++j)
|
||
|
{
|
||
|
if (!joints[j])
|
||
|
{
|
||
|
std::cout << "got NULL joint in actuator example main.cc" << std::endl;
|
||
|
continue;
|
||
|
}
|
||
|
// Command a constant force on each joint.
|
||
|
// This causes the joints to accelerate linearly
|
||
|
// The linear velocity data gives a range of values, allowing us to
|
||
|
// construct a torque vs. velocity graph
|
||
|
// By commanding a torque above the actuator's maximum torque value
|
||
|
// we are forcing the maximum force state of the actuator
|
||
|
joints[j]->SetForce(index, maxTorque);
|
||
|
}
|
||
|
|
||
|
gazebo::runWorld(world, sampleTimesteps);
|
||
|
|
||
|
// Print joint position, velocity and torques for each model to file
|
||
|
for (unsigned int j = 0; j < joints.size(); ++j)
|
||
|
{
|
||
|
fileStream << joints[j]->GetAngle(index) << "\t"
|
||
|
<< joints[j]->GetVelocity(index) << "\t"
|
||
|
<< joints[j]->GetForce(index);
|
||
|
if (j == joints.size() - 1)
|
||
|
{
|
||
|
fileStream << std::endl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fileStream << "\t";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Close everything.
|
||
|
fileStream.close();
|
||
|
gazebo::shutdown();
|
||
|
|
||
|
std::cout << "Finished data collection. Closing Gazebo." << std::endl;
|
||
|
return 0;
|
||
|
}
|