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

Adding an abstract BarrettHandPositionCommandExecutor class #166

Merged
merged 25 commits into from
Apr 17, 2017
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8feb924
Renaming, adding an abstract BarretHandPositionCommandExecutor class
gilwoolee Apr 12, 2017
811a63b
Adding -override
gilwoolee Apr 12, 2017
dd96c10
Merge branch 'master' into SimBarrettHandCommandExecutor
gilwoolee Apr 12, 2017
83f69dd
Exposing step
gilwoolee Apr 13, 2017
cf8f104
Merge branch 'SimBarrettHandCommandExecutor' of https://github.com/pe…
gilwoolee Apr 13, 2017
9d9fb3d
Renaiming PositionCommandExecutor
gilwoolee Apr 13, 2017
648c2bf
Changing header files
gilwoolee Apr 13, 2017
a38c65a
Changing names and step function.
gilwoolee Apr 14, 2017
06dad13
Merge branch 'master' into SimBarrettHandCommandExecutor
gilwoolee Apr 14, 2017
c6462db
Update simulation speed constants and matrix->vector methods.
brianhou Apr 14, 2017
e16880e
Add collisionDetector argument. Make collideWith an optional argument.
brianhou Apr 15, 2017
ce86f93
Don't reset mCollideWith every time.
brianhou Apr 15, 2017
c90cd8d
Simplify logic of optional collision detector and collision groups.
brianhou Apr 15, 2017
2d3a5bc
Add ShapeFrames of original collision group to new collision group.
brianhou Apr 15, 2017
d9d36fc
Make collisionDetector, collideWith optional.
brianhou Apr 15, 2017
3af8671
Instantiate FingerPositionCommandExecutors and FingerSpreadCommandExe…
brianhou Apr 15, 2017
2174930
Clean up some documentation.
brianhou Apr 15, 2017
6ecb30e
Remove parameter from step.
brianhou Apr 15, 2017
c3eb6f3
Set mCollisionDetector when setting mCollideWith.
brianhou Apr 15, 2017
47a9852
Make FingerCommandExecutors implement PositionCommandExecutor.
brianhou Apr 15, 2017
bebb761
Swap argument order in HandPositionExecutor.
brianhou Apr 16, 2017
f1d805f
Partial test fixes.
brianhou Apr 16, 2017
fc7cd1c
Adding time-reset when a new execute command is given.
gilwoolee Apr 16, 2017
1eba53b
Update expected values in test to make them pass.
brianhou Apr 16, 2017
fa23b68
Merge branch 'master' into SimBarrettHandCommandExecutor
brianhou Apr 16, 2017
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef AIKIDO_CONTROL_BARRETFINGERPOSITIONCOMMANDEXECUTOR_HPP_
#define AIKIDO_CONTROL_BARRETFINGERPOSITIONCOMMANDEXECUTOR_HPP_
#ifndef AIKIDO_CONTROL_BARRETFINGERKINEMATICSIMULATIONPOSITIONCOMMANDEXECUTOR_HPP_
#define AIKIDO_CONTROL_BARRETFINGERKINEMATICSIMULATIONPOSITIONCOMMANDEXECUTOR_HPP_
#include <dart/collision/CollisionDetector.hpp>
#include <dart/collision/CollisionOption.hpp>
#include <dart/collision/CollisionGroup.hpp>
Expand All @@ -8,67 +8,74 @@
#include <future>
#include <mutex>
#include <condition_variable>
#include <chrono>

namespace aikido {
namespace control {

/// This executor mimics the behavior of BarretFinger.
/// It moves a finger to a desired point; it may stop early if
/// This executor mimics the behavior of BarretFinger.
/// It moves a finger to a desired point; it may stop early if
/// joint limit is reached or collision is detected.
/// Only the proximal joint is actuated; the distal joint moves with mimic ratio.
/// When collision is detected on the distal link, the finger stops.
/// When collision is detected on the proximal link, the distal link moves
/// until it reaches joint limit or until distal collision is detected.
class BarrettFingerPositionCommandExecutor
class BarrettFingerKinematicSimulationPositionCommandExecutor
{
public:
/// Constructor.
/// \param _finger Finger to be controlled by this Executor.
/// \param _proximal Index of proximal dof
/// \param _distal Index of distal dof
/// \param _collisionDetector CollisionDetector for detecting self collision
/// and collision with objects.
/// \param _collisionOptions Default is (enableContact=false, binaryCheck=true,
/// maxNumContacts = 1.)
/// See dart/collison/Option.h for more information
BarrettFingerPositionCommandExecutor(
::dart::dynamics::ChainPtr _finger, int _proximal, int _distal,
::dart::collision::CollisionDetectorPtr _collisionDetector,
::dart::collision::CollisionOption _collisionOptions
/// \param[in] finger Finger to be controlled by this Executor.
/// \param[in] proximal Index of proximal dof
/// \param[in] distal Index of distal dof
/// \param[in] collisionDetector CollisionDetector to check collision with fingers.
/// If nullptr, default to FCLCollisionDetector.
/// \param[in] collideWith CollisionGroup to check collision with fingers.
/// If nullptr, default to empty CollisionGroup.
/// \param[in] collisionOptions Default is (enableContact=false, binaryCheck=true,
/// maxNumContacts = 1.)
/// See dart/collison/Option.h for more information
BarrettFingerKinematicSimulationPositionCommandExecutor(
::dart::dynamics::ChainPtr finger, size_t proximal, size_t distal,
::dart::collision::CollisionDetectorPtr collisionDetector = nullptr,
::dart::collision::CollisionGroupPtr collideWith = nullptr,
::dart::collision::CollisionOption collisionOptions
= ::dart::collision::CollisionOption(false, 1));

/// Sets variables to move the finger joints.
/// proximal dof moves to _goalPosition, joint limit, or until collision.
/// proximal dof moves to goalPosition, joint limit, or until collision.
/// Step method should be called multiple times until future returns.
/// Distal dof follows with mimic ratio.
/// \param _goalPosition Desired angle of proximal joint.
/// \param _collideWith CollisionGroup to check collision with fingers.
/// Distal dof follows with mimic ratio.
/// \param goalPosition Desired angle of proximal joint.
/// \return future Becomes available when the execution completes.
std::future<void> execute(double _goalPosition,
::dart::collision::CollisionGroupPtr _collideWith);
std::future<void> execute(double goalPosition);

/// Returns mimic ratio, i.e. how much the distal joint moves relative to
/// Returns mimic ratio, i.e. how much the distal joint moves relative to
/// the proximal joint. The joint movements follow
/// this ratio only when both joints are moving.
/// \return mimic ratio.
static double getMimicRatio();
constexpr static double getMimicRatio() { return kMimicRatio; }
Copy link
Member

Choose a reason for hiding this comment

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

Nit: We could nix this function and just use kMimicRatio directly.

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems that the only time that getMimicRatio is used is in tests, but kMimicRatio is private so getting rid of this function wouldn't work.

Copy link
Member

Choose a reason for hiding this comment

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

Understood. Let's leave it as it is.


/// Moves the joints of the finger by dofVelocity*_timeSIncePreviousCall
/// Moves the joints of the finger by dofVelocity*timeSincePreviousCall
/// until execute's goalPosition by primary dof or collision is detected.
/// If proximal link is in collision, distal link moves until
/// If proximal link is in collision, distal link moves until
/// mimicRatio*goalPosition. If distal link is in collision, execution stops.
/// If multiple threads are accessing this function or skeleton associated
/// with this executor, it is necessary to lock the skeleton before
/// calling this method.
/// \param _timeSincePreviousCall Time since previous call.
void step(double _timeSincePreviousCall);
/// \param[in] timeSincePreviousCall Time interval to take.
void step(const std::chrono::milliseconds& timeSincePreviousCall);

/// Resets CollisionGroup to check collision with fingers.
/// \param _collideWith CollisionGroup to check collision with fingers.
/// \return false if fails to change collideWith (during execution).
bool setCollideWith(::dart::collision::CollisionGroupPtr collideWith);

private:
constexpr static double kMimicRatio = 0.333;
constexpr static double kProximalVelocity = 0.01;
constexpr static double kDistalVelocity = kProximalVelocity*kMimicRatio;
private:
constexpr static double kMimicRatio = 0.333;
constexpr static double kProximalSpeed = 1;
Copy link
Member

Choose a reason for hiding this comment

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

Why did kProximalSpeed change from 0.01 to 1? 🤔 Do we know which (if either) of these is correct for the BarrettHand?

Copy link
Contributor

Choose a reason for hiding this comment

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

This was because the hand was moving really slowly when we were visualizing it in sim. I don't know if either is correct. How would we check that?

Copy link
Member

Choose a reason for hiding this comment

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

I suspect we arbitrarily chose a value for testing, then. 😢

  1. Our controller calls the trapezoidalMove() function to move the hand:

  2. That function sets the E Puck property to the desired position, then the MODE property to MODE_TRAPEZOIDAL to execute the action.

  3. Here is a snippet of the description of the behavior of the hand in MODE_TRAPEZOIDAL (the full description goes into much more detail):

    [...] The BarrettHand will generate its own trapezoidal velocity profile to accelerate from its present position (using ACCEL) until it reaches max velocity (MV), then it will decelerate to reach the target endpoint position at zero velocity. [...]

So the correct way to get this value is to query the MV property on the four pucks in the BarrettHand, then use the transmission ratio to convert the motor velocity to a joint velocity. We should do this at some point (maybe file an issue?), but it's not urgent to get this right.

In the meantime, we can estimate a value by timing how long it takes the hand to close. This is all an approximation, anyway, since we are assuming the finger immediately accelerates to its maximum velocity.

From watching a YouTube video of HERB, I estimate around 1 s. Since the joint range is 140 degrees, this is around 2.4 rad/s. 🔬

Copy link
Member

Choose a reason for hiding this comment

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

On second thought, I am not sure why this value is hardcoded at all. We should use the velocity limits that are stored in the DART Skeleton. Those are currently set to 2 rad/s in herb_description, which is already in the correct ballpark. 👍

@brianhou Are you up for making that change? 😁

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, it seems like making this change would require kProximalSpeed and kDistalSpeed to not be static, right? I'm not sure why they're static now and whether that's necessary though.

constexpr static double kDistalSpeed = kProximalSpeed*kMimicRatio;

/// If (current dof - goalPosition) execution terminates.
/// If (current dof - goalPosition) execution terminates.
constexpr static double kTolerance = 1e-3;

::dart::dynamics::ChainPtr mFinger;
Expand All @@ -81,34 +88,34 @@ class BarrettFingerPositionCommandExecutor
std::pair<double, double> mProximalLimits, mDistalLimits;

::dart::collision::CollisionDetectorPtr mCollisionDetector;
::dart::collision::CollisionGroupPtr mCollideWith;
::dart::collision::CollisionOption mCollisionOptions;

::dart::collision::CollisionGroupPtr mProximalCollisionGroup;
::dart::collision::CollisionGroupPtr mDistalCollisionGroup;

std::unique_ptr<std::promise<void>> mPromise;

/// Flag for indicating execution of a command.
bool mInExecution;

/// Control access to mPromise, mInExecution, mGoalPosition, mDistalOnly,
/// mCollideWith
/// mCollideWith
std::mutex mMutex;

/// Flag for indicating execution of a command.
bool mInExecution;

/// Desired end-position of proximal dof.
double mProximalGoalPosition;

/// Indicator that only distal finger is to be moved.
bool mDistalOnly;

::dart::collision::CollisionGroupPtr mCollideWith;

/// Helper method for step() to set variables for terminating an execution.
void terminate();

};

using BarrettFingerPositionCommandExecutorPtr = std::shared_ptr<BarrettFingerPositionCommandExecutor>;
using BarrettFingerKinematicSimulationPositionCommandExecutorPtr
= std::shared_ptr<BarrettFingerKinematicSimulationPositionCommandExecutor>;


} // control
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#ifndef AIKIDO_CONTROL_BARRETFINGERKINEMATICSIMULATIONSPREADCOMMANDEXECUTOR_HPP_
#define AIKIDO_CONTROL_BARRETFINGERKINEMATICSIMULATIONSPREADCOMMANDEXECUTOR_HPP_
#include <dart/collision/CollisionDetector.hpp>
#include <dart/collision/CollisionOption.hpp>
#include <dart/collision/CollisionGroup.hpp>
#include <dart/collision/CollisionFilter.hpp>
#include <dart/dynamics/dynamics.hpp>
#include <future>
#include <mutex>
#include <condition_variable>
#include <chrono>

namespace aikido {
namespace control {

/// This executor mimics the spread behavior of BarretFinger.
/// It moves two finger spreads simultaneously to certain goal value;
/// it will stop prematurely if joint limit is reached or collision is detected.
class BarrettFingerKinematicSimulationSpreadCommandExecutor
{
public:
/// Constructor.
/// \param[in] fingers 2 fingers to be controlled by this Executor.
/// \param[in] spread Index of spread dof
/// \param[in] collideWith CollisionGroup to check collision with fingers.
/// \param[in] collisionOptions Default is (enableContact=false, binaryCheck=true,
/// maxNumContacts = 1.)
BarrettFingerKinematicSimulationSpreadCommandExecutor(
std::array<::dart::dynamics::ChainPtr, 2> fingers, size_t spread,
::dart::collision::CollisionGroupPtr collideWith,
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Make collideWith optional.

::dart::collision::CollisionOption collisionOptions
= ::dart::collision::CollisionOption(false, 1));

/// Sets variables to move the spread joint by goalPosition,
/// joint limit has reached, or until collision is detected.
/// Must call step function after this for actual execution.
/// \param goalPosition Desired angle of spread joint.
/// \return future which becomes available when the execution completes.
std::future<void> execute(double goalPosition);

/// Moves the joint of the finger by fixed speed*timeSincePreviousCall
/// until execute's goalPosition by spread dof or collision is detected.
/// If multiple threads are accessing this function or the skeleton associated
/// with this executor, it is necessary to lock the skeleton before
/// calling this method.
/// \param[in] timeSincePreviousCall Time interval to take.
void step(const std::chrono::milliseconds& timeSincePreviousCall);
Copy link
Member

@jslee02 jslee02 Apr 14, 2017

Choose a reason for hiding this comment

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

Please ignore if this is already discussed: Wouldn't there be a reasonable default interval time here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This call would always be called by BarrettHandKinematicSimulationPositionCommandExecutor::step() method, so I am not sure whether a default is necessary. We can set it to something I guess... :)

Copy link
Member

Choose a reason for hiding this comment

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

If that's the case, I'm fine with not setting a default value here.



/// Resets CollisionGroup to check collision.
/// \param collideWith CollisionGroup to check collision with fingers.
/// \return false if fails to change collideWith (during execution).
bool setCollideWith(::dart::collision::CollisionGroupPtr collideWith);

private:
constexpr static double kDofSpeed = 1;

/// If (current dof - goalPosition) execution terminates.
constexpr static double kTolerance = 1e-3;

/// All fingers dof values should be the same (approx. within this tolerance).
constexpr static double kDofTolerance = 1e-3;

constexpr static int kNumFingers = 2;

std::array<::dart::dynamics::ChainPtr, 2> mFingers;

std::vector<::dart::dynamics::DegreeOfFreedom*> mSpreadDofs;

std::pair<double, double> mDofLimits;

::dart::collision::CollisionDetectorPtr mCollisionDetector;
::dart::collision::CollisionGroupPtr mCollideWith;
::dart::collision::CollisionOption mCollisionOptions;

::dart::collision::CollisionGroupPtr mSpreadCollisionGroup;

std::unique_ptr<std::promise<void>> mPromise;

/// Controls access to mPromise, mInExecution, mGoalPosition, mCollideWith
std::mutex mMutex;

/// True if a command is in execution
bool mInExecution;

/// Desired end spread value
double mGoalPosition;
};

using BarrettFingerKinematicSimulationSpreadCommandExecutorPtr
= std::shared_ptr<BarrettFingerKinematicSimulationSpreadCommandExecutor>;

} // control
} // aikido

#endif
94 changes: 0 additions & 94 deletions include/aikido/control/BarrettFingerSpreadCommandExecutor.hpp

This file was deleted.

Loading