-
Notifications
You must be signed in to change notification settings - Fork 12
Impedance control ex #86
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
Closed
Closed
Changes from 9 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
510709e
Complete impedance control example with documentation
GogiPuttar 4fe2ad7
Complete gimbal example
GogiPuttar 8cce890
Complete cartesian impedance controller example
GogiPuttar cdd7e9a
Created floor and variable damping examples.
GogiPuttar f72675e
All examples are complete now
GogiPuttar f015b5f
Properly used ki and i_clamp terms for fixed example
GogiPuttar b586b2f
Correctly demonstrated how to use i_terms across all examples
GogiPuttar d63877f
Changed prevmode back to -1 also, for consistency
GogiPuttar 88cece2
Added check for mode validity
GogiPuttar cf5717e
- CPP examples now follow config file convention
GogiPuttar 6443fa5
All impedance control examples work
GogiPuttar 89dc779
mobile_io_control example integrated with config files
GogiPuttar 3afe1bf
Refactored repo according to new layout
GogiPuttar 6317ab3
Renamed file paths to acoomaodate new config file layout
GogiPuttar c35092c
gravcomp and new gravcomp_toggle examples also integrated with config
GogiPuttar c6ec868
ex_AR_kit integrated
GogiPuttar b988f08
teach repeat fully integrated
GogiPuttar 551e6ce
Ironed a few things out
GogiPuttar dd264b1
removed instructions from all examples
GogiPuttar 2110d4f
Re-added initial update for reset
GogiPuttar 75a1cd3
standardized namespace declarations
GogiPuttar e5dd48e
removed all sleeps
GogiPuttar 046a221
changed getpluginbyname to getpluginbytype
GogiPuttar 6c75cd8
UserData's getters have been incorporated
GogiPuttar 0e69956
Checked every single example one last time
GogiPuttar 153d9d5
Compatible with config.location_
GogiPuttar ba70958
examples repo compatible with newest API
GogiPuttar f843fbd
removed unnecessary file
GogiPuttar e3c6c74
reflects changes that will be made into config directory
GogiPuttar fe4a230
Introduced latency in AR kit, python also has this now
GogiPuttar e0782fc
Updated the C++ library reference
iamtesch File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| /** | ||
| In these examples we will implement various hybrid motion-force controllers using the impedance control plugin, which can be used for a wide variety of | ||
| applications. | ||
| Impedance control is BEST SUITED for assigning free, rigid and springy behaviour, along/about each different axis. | ||
| While this is perfectly useful for: | ||
| - Having a selectively compliant end-effector, | ||
| - Switching between fixed and free behaviour to simulate (mostly) rigid constraints, and | ||
| - Allowing human intervention for automated operations by separating controls across different axes, | ||
| any applications involving more salient control of the forces (as more complex functions with flexible inputs) should use our force control plugin. See ex_force_control_demoname.cpp. | ||
|
|
||
| This comprises the following demos: | ||
| - Fixed: A task-space pose controller implemented entirely using force control via the (PID) impedance controller. | ||
| - Cartesian: Locks onto a particular end-effector position while having some compliant orientation. | ||
| - Gimbal: A gimbal that locks a specific end-effector orientation, while keeping the rest of the arm compliant. | ||
| - Floor: The end-effector is free to move but can't travel below a virtual floor. To further simulate sliding on the floor, see force_control example. | ||
| - Damping: The end-effector behaves as 3-different damped systems (overdamped, critically damped, and underdamped), at 3 different heights. | ||
|
|
||
| The following example is for the "Cartesian" demo: | ||
| */ | ||
|
|
||
| // #include "lookup.hpp" | ||
| // #include "group.hpp" | ||
| #include "group_command.hpp" | ||
| #include "group_feedback.hpp" | ||
| #include "robot_model.hpp" | ||
| #include "arm/arm.hpp" | ||
| #include "util/mobile_io.hpp" | ||
| #include <chrono> | ||
|
|
||
| using namespace hebi; | ||
| using namespace experimental; | ||
|
|
||
| int main(int argc, char* argv[]) | ||
| { | ||
| ////////////////////////// | ||
| ///// Arm Setup ////////// | ||
| ////////////////////////// | ||
|
|
||
| arm::Arm::Params params; | ||
|
|
||
| // Setup Module Family and Module Names | ||
| params.families_ = {"HEBIArm-T"}; | ||
|
GogiPuttar marked this conversation as resolved.
Outdated
|
||
| params.names_ = {"J1_base", "J2_shoulder", "J3_elbow", "J4_wrist1", "J5_wrist2", "J6_wrist3"}; | ||
|
|
||
| // Read HRDF file to seutp a RobotModel object for the 6-DoF Arm | ||
| // Make sure you are running this from the correct directory! | ||
| params.hrdf_file_ = "kits/arm/hrdf/T-arm.hrdf"; | ||
|
GogiPuttar marked this conversation as resolved.
Outdated
|
||
|
|
||
| // Create the Arm Object | ||
| auto arm = arm::Arm::create(params); | ||
| while (!arm) { | ||
| arm = arm::Arm::create(params); | ||
| } | ||
|
|
||
| // Load the gains file that is approriate to the arm | ||
| arm -> loadGains("kits/arm/gains/T-arm.xml"); | ||
|
|
||
| // Create and configure the ImpedanceController plugin | ||
|
|
||
| // NOTE: Angle wraparound is an unresolved issue which can lead to unstable behaviour for any case involving rotational positional control. | ||
| // Make sure that the rotational gains are high enough to prevent large angular errors (greater than pi/2). The gains provided in these examples are well behaved. | ||
| // Interacting with the end-effector in these examples is perfectly safe. | ||
| // However, ensure that nothing prevents the wrist's actuators from moving, and DO NOT place your fingers between them. | ||
|
|
||
| hebi::experimental::arm::PluginConfig impedance_config("ImpedanceController", "ImpedanceController"); | ||
| impedance_config.float_lists_["kp"] = {300.0, 300.0, 300.0, 0.0, 0.0, 0.0}; | ||
| impedance_config.float_lists_["kd"] = {5.0, 5.0, 5.0, 0.0, 0.0, 0.0}; | ||
| impedance_config.float_lists_["ki"] = {20.0, 20.0, 20.0, 0.0, 0.0, 0.0}; | ||
| impedance_config.float_lists_["i_clamp"] = {10.0, 10.0, 10.0, 0.0, 0.0, 0.0}; // Clamp on the end-effector wrench and NOT on the integral error | ||
| impedance_config.bools_["gains_in_end_effector_frame"] = true; | ||
|
|
||
| auto impedance_plugin = hebi::experimental::arm::plugin::ImpedanceController::create(impedance_config); | ||
| if (!impedance_plugin) { | ||
| std::cerr << "Failed to create ImpedanceController plugin." << std::endl; | ||
| return -1; | ||
| } | ||
|
|
||
| // Initialize variables used to clear the commanded position and velocity in every cycle | ||
| hebi::GroupCommand& command = arm->pendingCommand(); | ||
|
|
||
| auto num_joints = arm->robotModel().getDoFCount(); | ||
| Eigen::VectorXd pos_nan(num_joints), vel_nan(num_joints); | ||
| pos_nan.fill(std::numeric_limits<double>::quiet_NaN()); | ||
| vel_nan.fill(std::numeric_limits<double>::quiet_NaN()); | ||
|
|
||
| // Add the plugin to the arm | ||
| if (!arm->addPlugin(std::move(impedance_plugin))) { | ||
| std::cerr << "Failed to add ImpedanceController plugin to arm." << std::endl; | ||
| return -1; | ||
| } | ||
|
|
||
| ////////////////////////// | ||
| //// MobileIO Setup ////// | ||
| ////////////////////////// | ||
|
|
||
| // Set up MobileIO | ||
| std::unique_ptr<util::MobileIO> mobile = util::MobileIO::create(params.families_[0], "mobileIO"); | ||
| if (!mobile) | ||
| { | ||
| std::cout << "couldn't find mobile IO device!\n"; | ||
| return 1; | ||
| } | ||
| mobile->setButtonMode(1, util::MobileIO::ButtonMode::Momentary); | ||
| mobile->setButtonLabel(1, "❌"); | ||
| mobile->setButtonMode(2, util::MobileIO::ButtonMode::Toggle); | ||
| mobile->setButtonLabel(2, "💪"); | ||
|
|
||
| std::string instructions; | ||
| instructions = " Cartesian demo"; | ||
|
|
||
| // Clear any garbage on screen | ||
| mobile->clearText(); | ||
|
GogiPuttar marked this conversation as resolved.
Outdated
|
||
|
|
||
| // Display instructions on screen | ||
| mobile->appendText(instructions); | ||
|
|
||
| // Setup instructions | ||
| auto last_state = mobile->update(); | ||
|
|
||
| std::cout << "Commanded gravity-compensated zero force to the arm.\n" | ||
| << " 💪 (B2) - Toggles an impedance controller on/off:\n" | ||
| << " ON - Apply controller based on current position\n" | ||
| << " OFF - Go back to gravity-compensated mode\n" | ||
| << " ❌ (B1) - Exits the demo.\n"; | ||
|
|
||
| ///////////////////////////// | ||
| // Control Variables Setup // | ||
| ///////////////////////////// | ||
|
|
||
| // Flag to indicate when impedance controller is on | ||
| bool controller_on = false; | ||
|
|
||
| ////////////////////////// | ||
| //// Main Control Loop /// | ||
| ////////////////////////// | ||
|
|
||
| while(arm->update()) | ||
| { | ||
| auto updated_mobile = mobile->update(0); | ||
|
|
||
| if (updated_mobile) | ||
| { | ||
| ///////////////// | ||
| // Button Presses | ||
| ///////////////// | ||
|
|
||
| // Buttton B1 - End demo | ||
| if (mobile->getButtonDiff(1) == util::MobileIO::ButtonState::ToOn) { | ||
| // Clear MobileIO text | ||
| mobile->resetUI(); | ||
| return 1; | ||
| } | ||
|
|
||
| // Button B2 - Set and unset impedance mode when button is pressed and released, respectively | ||
| if (mobile->getButtonDiff(2) == util::MobileIO::ButtonState::ToOn) { | ||
|
|
||
| controller_on = true; | ||
|
|
||
| arm->setGoal(arm::Goal::createFromPosition(arm->lastFeedback().getPosition())); | ||
| } | ||
| else if (mobile->getButtonDiff(2) == util::MobileIO::ButtonState::ToOff){ | ||
|
|
||
| controller_on = false; | ||
| } | ||
| } | ||
|
|
||
| if (!controller_on) | ||
| { | ||
| arm->cancelGoal(); | ||
| } | ||
|
|
||
| // Clear all position and velocity commands | ||
| command.setPosition(pos_nan); | ||
| command.setVelocity(vel_nan); | ||
|
|
||
| // Send latest commands to the arm | ||
| arm->send(); | ||
| } | ||
|
|
||
| // Clear MobileIO text | ||
| mobile->clearText(); | ||
|
GogiPuttar marked this conversation as resolved.
Outdated
|
||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.