Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve edge evaluator interface to support compound edge evaluator #26

Conversation

Levi-Armstrong
Copy link
Collaborator

This reduces code duplication between edge evaluators and enables the ability for the compound edge evaluator to work correctly.

Copy link
Collaborator

@marip8 marip8 left a comment

Choose a reason for hiding this comment

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

Nominally I think this is a good change. It's worth thinking about making the two interface function definitions (evaluate and considerEdge) as simple and intuitive as possible.

We really also need to comment these classes and what they're intended to be used for. There is a lot of ambiguity on the types of costs that these evaluators should return (i.e. L1 or L2 distance) and the assumptions they make (i.e. do they consider timing, axis order, etc.). We shouldn't have to dig into the source code to understand what these classes/functions do

@@ -32,13 +32,59 @@ template <typename FloatType>
class EdgeEvaluator
{
public:
using Ptr = typename std::shared_ptr<EdgeEvaluator<FloatType>>;
EdgeEvaluator(std::size_t dof) : dof_(dof) {}
virtual ~EdgeEvaluator() {}

virtual bool evaluate(const Rung_<FloatType>& from,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't really like the function signature here. Why does this function return false if the two rungs aren't connected by any vertices? It's not like the evaluation itself failed. I would propose returning the vector of edge lists instead; then let the user decide what it means to have a vector of edge lists that is empty.

std::vector<typename LadderGraph<FloatType>::EdgeList> evaluate(const Rung_<FloatType>& from, const Rung_<FloatType>& to)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Why does this function return false if the two rungs aren't connected by any vertices? It's not like the evaluation itself failed. I would propose returning the vector of edge lists instead; then let the user decide what it means to have a vector of edge lists that is empty.

This is an interface class that is only to used by the descartes code which keeps the building of the graph cleaner. The user should not directly be calling evaluate or considerEdge.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In this case, the "user" I'm referring to is actually us as developers, not necessarily end-users. I think a change to this interface would clear up the ambiguity with edges resizing we're discussing above. It would be really easy to create a helper function that can look through the output list of edges and determine if it is empty or not to replace the boolean check here. This wouldn't introduce much additional code to the graph construction and would improve the clarity of the edge evaluator interface

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ok, make sense. Lets create an issue on this and make the change in a separate PR. You good with this?

if (!rung.empty())
return true;
FloatType cost = 0.0;
for (std::size_t i = 2; i < this->dof_; ++i)
Copy link
Collaborator

Choose a reason for hiding this comment

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

There are a lot of assumptions being made here:

  • The gantry has two external axes
  • The gantry axes are the first two values in the list
  • The joint distance of the gantry axes is not considered

We need to add these assumptions to the documentation at the very least. Ultimately, we should probably parameterize them with the arguments to the constructor.

Why is the motion of the first two axes of the gantry irrelevant here?

Copy link
Collaborator Author

@Levi-Armstrong Levi-Armstrong Oct 3, 2020

Choose a reason for hiding this comment

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

Based on experience it works better to minimize robot motion and let the gantry do most of the work if it can. Though this is old and not used anymore. I am good with marking it deprecated or removing it completely.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't necessarily need to delete it (unless you really think it needs to go); we just need to document these assumptions on the class definition so we can easily remember how it works

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it has little value since most will likely use there own because MoveIt and Tesseract have there own way of defining kinematics. Tesseract implements its own which allow any number of gantry joints and I would assume if other motion planning libraries would do the same.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I update your Issue #5 to include documentation items that need to be addressed.

@Levi-Armstrong
Copy link
Collaborator Author

Levi-Armstrong commented Oct 3, 2020

@marip8 I made most of the changes but there is a few I commented on to further discuss.

Once the review is finished I will squash everything into a single commit.

@Levi-Armstrong
Copy link
Collaborator Author

Levi-Armstrong commented Oct 3, 2020

@johnwason Do you know how to fix the windows build?

@johnwason
Copy link
Contributor

It looks like you are using the old ROS Windows repository with the azurewebsites url. They have started using a new one recently. You should upgrade to the latest install instructions:

http://wiki.ros.org/Installation/Windows

I also suggest using the github for building Windows, since they are using powershell instead of git bash for the environment. The ROS Windows has build in powershell support.

@Levi-Armstrong
Copy link
Collaborator Author

It looks like you are using the old ROS Windows repository with the azurewebsites url. They have started using a new one recently. You should upgrade to the latest install instructions:

http://wiki.ros.org/Installation/Windows

I also suggest using the github for building Windows, since they are using powershell instead of git bash for the environment. The ROS Windows has build in powershell support.

@johnwason Are you currently using this in any of your repository that I may use as a guide?

@Levi-Armstrong
Copy link
Collaborator Author

@marip8 I believe I have addressed the remaining issues in the latest commit. I removed the timing constraint and simplified the edge evaluator API. I also updated the issue on documentation related to include items that need to be addressed. I may have time in the near future to go through and add documentation to this repository.

@marip8
Copy link
Collaborator

marip8 commented Oct 5, 2020

I think we should handle the timing constraint a little differently. I think we have 3 options:

  1. Make timing a standalone evaluator
    • All other edge evaluator implementations should be independent of timing
  2. Make timing a parameter of the considerEdge interface (with default value = inf)
    • Edge evaluators can choose whether or not they consider timing
    • Con:
      • It's could be unclear to an end-user whether or not timing is being considered if it's not documented well
      • You might need to duplicate edge evaluators such that one considers timing and the second doesn't
  3. Make timing an argument to the constructor of the edge evaluator implementation
    • Cons:
      • You might need to duplicate edge evaluators such that one considers timing and the second doesn't

I prefer option 1 (standalone timing evaluator) because it can be easily combined with any other evaluator with the CompoundEdgeEvaluator and it eliminates ambiguity in the other evaluators about whether or not they consider timing.

Depending on how quickly you need this functionality, we could make this an issue address it in the future. If you're on board with option 1, though, it might be nice to knock it out with this PR

@johnwason
Copy link
Contributor

@Levi-Armstrong Sorry no, I don't have a unit test using ROS Windows.

@Levi-Armstrong
Copy link
Collaborator Author

@marip8 I made the changes per our discussion, let me know if you see any issues.

Comment on lines +46 to +49
Eigen::Matrix<FloatType, Eigen::Dynamic, 1> delta =
Eigen::Map<const Eigen::Matrix<FloatType, Eigen::Dynamic, 1>>(end, static_cast<Eigen::Index>(this->dof_)) -
Eigen::Map<const Eigen::Matrix<FloatType, Eigen::Dynamic, 1>>(start, static_cast<Eigen::Index>(this->dof_));
Eigen::Matrix<FloatType, Eigen::Dynamic, 1> joint_times = delta.cwiseQuotient(velocity_limits_).cwiseAbs();
Copy link
Collaborator

Choose a reason for hiding this comment

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

FYI you can use Eigen::Array instead of Eigen::Matrix to do coefficient-wise operations "natively" without calling cwise...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I assumed they did the same thing under the hood. Is there a benefit for one over the other?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Eigen::Matrix is for linear algebra operations whereas Eigen::Array is for coefficient-wise operations. According to the documentation, you can convert one to the other with no run-time cost. I think it's just more convenient to use one over the other depending on what type of operations you're trying to do

@Levi-Armstrong Levi-Armstrong merged commit 81bd3f0 into swri-robotics:feature/CommandLanguage Oct 5, 2020
@Levi-Armstrong Levi-Armstrong deleted the issue/FixCompoundEvaluator branch October 5, 2020 23:38
@johnwason
Copy link
Contributor

@ooeygui Can you help Levi with his question about CI with the updated ROS install instructions?

@ooeygui
Copy link

ooeygui commented Oct 6, 2020

@johnwason Thanks for loop in - I have an email thread with Levi on the CI.

@johnwason
Copy link
Contributor

@ooeygui I am interested in the solution to this problem as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants