Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ add_library(
# Implementations
src/plugins/multiplicative_evaluator.cpp
src/plugins/point_cloud_target_pose_generator.cpp
src/plugins/yaml_target_pose_generator.cpp
src/plugins/console_logger.cpp
src/plugins/boost_progress_console_logger.cpp
src/plugins/no_op.cpp)
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,47 @@ The `reach` package also provides the interface definition for the required reac
- Generates Cartesian target poses that the robot should attempt to reach during the reach study
- These target poses are expected to be relative to the kinematic base frame of the robot
- The z-axis of the target poses is expected to oppose the z-axis of the robot kinematic tip frame

Currently two pose generators are supported:

- **PointCloudTargetPoseGenerator**: This pose generator accepts a point cloud file (`.pcd`) with normals as input and calculates the reachability for each point + normal in the file. Syntax for the `reach_study.yaml`:
```
target_pose_generator:
name: PointCloudTargetPoseGenerator
pcd_file: package://reach/test/part.pcd
```

- **YAMLTargetPoseGenerator**: This pose generator directly accepts a `.yaml` file containing poses and evaluates reachability of each pose in the file. Syntax of `poses.yaml`:

```
poses:
- position:
x: 0.3629872500896454
y: -0.06363007426261902
z: -0.0005234468844719231
orientation:
x: 0.09166051483190088
y: -0.0017855572788278349
z: 0.9957755116009193
w: 0.005127601962168693
- position:
x: 0.3251079320907593
y: -0.0632486343383789
z: 0.006282307207584381
orientation:
x: 0.07515697809440232
y: -0.002977202008927411
z: 0.9971538575858108
w: 0.005171964196712022
Comment on lines +53 to +71
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to align with suggested serialization method

Suggested change
poses:
- position:
x: 0.3629872500896454
y: -0.06363007426261902
z: -0.0005234468844719231
orientation:
x: 0.09166051483190088
y: -0.0017855572788278349
z: 0.9957755116009193
w: 0.005127601962168693
- position:
x: 0.3251079320907593
y: -0.0632486343383789
z: 0.006282307207584381
orientation:
x: 0.07515697809440232
y: -0.002977202008927411
z: 0.9971538575858108
w: 0.005171964196712022
- x: 0.3629872500896454
y: -0.06363007426261902
z: -0.0005234468844719231
qw: 0.005127601962168693
qx: 0.09166051483190088
qy: -0.0017855572788278349
qz: 0.9957755116009193
- x: 0.3251079320907593
y: -0.0632486343383789
z: 0.006282307207584381
qw: 0.005171964196712022
qx: 0.07515697809440232
qy: -0.002977202008927411
qz: 0.9971538575858108

```

Syntax for reach_study.yaml
```
```
target_pose_generator:
name: PointCloudTargetPoseGenerator
poses: /path/to/poses.yaml

1. [`IKSolver`](include/reach/interfaces/ik_solver.h)
- Calculates the inverse kinematics solution for the robot at an input 6 degree-of-freedom Cartesian target
1. [`Evaluator`](include/reach/interfaces/evaluator.h)
Expand Down
42 changes: 42 additions & 0 deletions include/reach/plugins/yaml_target_pose_generator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2019 Southwest Research Institute
*
* 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.
*/
#ifndef REACH_PLUGINS_YAML_TARGET_POSE_GENERATOR_H
#define REACH_PLUGINS_YAML_TARGET_POSE_GENERATOR_H

#include <reach/interfaces/target_pose_generator.h>

namespace reach
{
class YAMLTargetPoseGenerator : public TargetPoseGenerator
{
public:
YAMLTargetPoseGenerator(std::string filename);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoids an unnecessary copy

Suggested change
YAMLTargetPoseGenerator(std::string filename);
YAMLTargetPoseGenerator(const std::string& filename);


VectorIsometry3d generate() const override;

private:
std::string filename_;
};

struct YAMLTargetPoseGeneratorFactory : public TargetPoseGeneratorFactory
{
using TargetPoseGeneratorFactory::TargetPoseGeneratorFactory;
TargetPoseGenerator::ConstPtr create(const YAML::Node& config) const override;
};

} // namespace reach

#endif // REACH_PLUGINS_YAML_TARGET_POSE_GENERATOR_H
2 changes: 2 additions & 0 deletions src/plugins/plugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <reach/plugins/multiplicative_evaluator.h>
#include <reach/plugins/no_op.h>
#include <reach/plugins/point_cloud_target_pose_generator.h>
#include <reach/plugins/yaml_target_pose_generator.h>

#include <reach/plugin_utils.h>
EXPORT_LOGGER_PLUGIN(reach::BoostProgressConsoleLoggerFactory, BoostProgressConsoleLogger)
Expand All @@ -12,3 +13,4 @@ EXPORT_EVALUATOR_PLUGIN(reach::NoOpEvaluatorFactory, NoOpEvaluator)
EXPORT_IK_SOLVER_PLUGIN(reach::NoOpIKSolverFactory, NoOpIKSolver)
EXPORT_DISPLAY_PLUGIN(reach::NoOpDisplayFactory, NoOpDisplay)
EXPORT_TARGET_POSE_GENERATOR_PLUGIN(reach::PointCloudTargetPoseGeneratorFactory, PointCloudTargetPoseGenerator)
EXPORT_TARGET_POSE_GENERATOR_PLUGIN(reach::YAMLTargetPoseGeneratorFactory, YAMLTargetPoseGenerator)
55 changes: 55 additions & 0 deletions src/plugins/yaml_target_pose_generator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <reach/plugins/yaml_target_pose_generator.h>
#include <reach/plugin_utils.h>
#include <reach/types.h>

#include <pcl/io/pcd_io.h>
#include <pcl/PCLPointField.h>
Comment on lines +5 to +6
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PCL includes shouldn't be necessary if we're not dealing with point clouds

Suggested change
#include <pcl/io/pcd_io.h>
#include <pcl/PCLPointField.h>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad. Copy paste :p

#include <yaml-cpp/yaml.h>
using namespace reach;

static VectorIsometry3d parseYAML(YAML::Node pose_file)
{
VectorIsometry3d target_poses;
for (const auto& pose : pose_file["poses"])
{
auto position = pose["position"];
auto orientation = pose["orientation"];

Eigen::Isometry3d target_pose;
target_pose.translation() =
Eigen::Vector3d(position['x'].as<double>(), position['y'].as<double>(), position['z'].as<double>());
target_pose.linear() = Eigen::Quaterniond(orientation['w'].as<double>(), orientation['x'].as<double>(),
orientation['y'].as<double>(), orientation['z'].as<double>())
.toRotationMatrix();
target_poses.push_back(target_pose);
}
return target_poses;
}
Comment on lines +10 to +27
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use the YAML serialization structs here, and flatten the serialization keys to [x, y, z, qw, qx, qy, qz].

Suggested change
static VectorIsometry3d parseYAML(YAML::Node pose_file)
{
VectorIsometry3d target_poses;
for (const auto& pose : pose_file["poses"])
{
auto position = pose["position"];
auto orientation = pose["orientation"];
Eigen::Isometry3d target_pose;
target_pose.translation() =
Eigen::Vector3d(position['x'].as<double>(), position['y'].as<double>(), position['z'].as<double>());
target_pose.linear() = Eigen::Quaterniond(orientation['w'].as<double>(), orientation['x'].as<double>(),
orientation['y'].as<double>(), orientation['z'].as<double>())
.toRotationMatrix();
target_poses.push_back(target_pose);
}
return target_poses;
}
namespace YAML
{
template <typename FloatT>
struct convert<Eigen::Transform<FloatT, 3, Eigen::Isometry>>
{
using T = Eigen::Transform<FloatT, 3, Eigen::Isometry>;
static bool decode(const Node& node, T& val)
{
Eigen::Matrix<FloatT, 3, 1> trans;
trans.x() = get<FloatT>(node, "x");
trans.y() = get<FloatT>(node, "y");
trans.z() = get<FloatT>(node, "z");
Eigen::Quaternion<FloatT> quat;
quat.w() = get<FloatT>(node, "qw");
quat.x() = get<FloatT>(node, "qx");
quat.y() = get<FloatT>(node, "qy");
quat.z() = get<FloatT>(node, "qz");
val = Eigen::Translation<FloatT, 3>(trans) * quat;
return true;
}
};
// Serialization for std::vectors with Eigen-specific allocators
template <typename T>
struct convert<std::vector<T, Eigen::aligned_allocator<T>>>
{
static bool decode(const Node& node, std::vector<T, Eigen::aligned_allocator<T>>& v)
{
if (!node.IsSequence())
return false;
v.clear();
for (const auto& elem : node)
v.push_back(elem.as<T>());
return true;
}
};
} // namespace YAML


namespace reach
{
YAMLTargetPoseGenerator::YAMLTargetPoseGenerator(std::string filename) : filename_(resolveURI(filename))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
YAMLTargetPoseGenerator::YAMLTargetPoseGenerator(std::string filename) : filename_(resolveURI(filename))
YAMLTargetPoseGenerator::YAMLTargetPoseGenerator(const std::string& filename) : filename_(resolveURI(filename))

{
}

VectorIsometry3d YAMLTargetPoseGenerator::generate() const
{
// Check if file exists
if (!boost::filesystem::exists(filename_))
throw std::runtime_error("File '" + filename_ + "' does not exist");

YAML::Node poses = YAML::LoadFile(filename_);
VectorIsometry3d target_poses = parseYAML(poses);

std::transform(target_poses.begin(), target_poses.end(), std::back_inserter(target_poses),
[](const Eigen::Isometry3d& pose) { return createFrame(pose.translation().cast<float>(),
pose.rotation().cast<float>() * Eigen::Vector3f::UnitZ()); });
return target_poses;
Comment on lines +41 to +47
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the transformation using createFrame is not necessary because we already have a list of fully defined poses from the YAML file. The purpose of createFrame was to create a fully defined pose from just a position vector and a normal vector (e.g., from a point cloud point and normal). Also, unless I'm mistaken, using std::back_inserter(target_poses) is adding all of the outputs of createFrame to the existing list of poses, effectively doubling the number of reach poses. This seems like it might have been unintentional, but was there a reason this was set up this way?

Suggested change
YAML::Node poses = YAML::LoadFile(filename_);
VectorIsometry3d target_poses = parseYAML(poses);
std::transform(target_poses.begin(), target_poses.end(), std::back_inserter(target_poses),
[](const Eigen::Isometry3d& pose) { return createFrame(pose.translation().cast<float>(),
pose.rotation().cast<float>() * Eigen::Vector3f::UnitZ()); });
return target_poses;
YAML::Node poses = YAML::LoadFile(filename_);
return poses.as<VectorIsometry3d>();

}

TargetPoseGenerator::ConstPtr YAMLTargetPoseGeneratorFactory::create(const YAML::Node& config) const
{
return std::make_shared<YAMLTargetPoseGenerator>(get<std::string>(config, "poses"));
}

} // namespace reach
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ install(
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)

install(FILES part.pcd reach_study.yaml DESTINATION share/${PROJECT_NAME}/test)
install(FILES part.pcd reach_study.yaml test_target_poses.yaml DESTINATION share/${PROJECT_NAME}/test)
3 changes: 3 additions & 0 deletions test/reach_study.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ evaluator:
target_pose_generator:
name: PointCloudTargetPoseGenerator
pcd_file: package://reach/test/part.pcd
# Uncomment to test YAML target pose generator
# name: YAMLTargetPoseGenerator
# poses: package://reach/test/test_target_poses.yaml

display:
name: NoOpDisplay
Expand Down
19 changes: 19 additions & 0 deletions test/test_target_poses.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
poses:
- position:
x: 1.0
y: 2.0
z: 3.0
orientation:
x: 0.0
y: 0.0
z: 0.0
w: 1.0
- position:
x: 4.0
y: 5.0
z: 6.0
orientation:
x: 0.0
y: 0.0
z: 0.0
w: 1.0
Comment on lines +1 to +19
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes/simplifies the format to align with the suggested YAML serialization changes

Suggested change
poses:
- position:
x: 1.0
y: 2.0
z: 3.0
orientation:
x: 0.0
y: 0.0
z: 0.0
w: 1.0
- position:
x: 4.0
y: 5.0
z: 6.0
orientation:
x: 0.0
y: 0.0
z: 0.0
w: 1.0
- x: 1.0
y: 2.0
z: 3.0
qw: 1.0
qx: 0.0
qy: 0.0
qz: 0.0
- x: 4.0
y: 5.0
z: 6.0
qw: 1.0
qx: 0.0
qy: 0.0
qz: 0.0