Skip to content

Commit 2be774d

Browse files
committed
Remainder of changes from #86
1 parent 14d6de1 commit 2be774d

12 files changed

+1482
-146
lines changed

kits/arm/ex_AR_kit.cpp

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "arm/arm.hpp"
1212
#include "util/mobile_io.hpp"
1313
#include <chrono>
14-
#include <iostream>
14+
#include "hebi_util.hpp"
1515

1616
using namespace hebi;
1717
using namespace experimental; // For all things mobileIO
@@ -48,44 +48,48 @@ int main(int argc, char* argv[])
4848
return -1;
4949
}
5050

51+
// For this demo, we need the arm and mobile_io
52+
std::unique_ptr<arm::Arm> arm;
53+
std::unique_ptr<hebi::util::MobileIO> mobile_io;
54+
5155
//////////////////////////
5256
///// Arm Setup //////////
5357
//////////////////////////
5458

55-
// Create the arm object from the configuration, and keep retrying if arm not found
56-
auto arm = arm::Arm::create(*example_config);
59+
// Create the arm object from the configuration
60+
arm = arm::Arm::create(*example_config);
61+
62+
// Keep retrying if arm not found
5763
while (!arm) {
5864
std::cerr << "Failed to create arm, retrying..." << std::endl;
65+
66+
// Retry
5967
arm = arm::Arm::create(*example_config);
6068
}
6169
std::cout << "Arm connected." << std::endl;
6270

63-
6471
//////////////////////////
6572
//// MobileIO Setup //////
6673
//////////////////////////
6774

68-
// Create the MobileIO object
69-
std::unique_ptr<util::MobileIO> mobile_io = util::MobileIO::create("Arm", "mobileIO");
70-
if (!mobile_io)
71-
{
72-
std::cout << "couldn't find mobile IO device!\n";
73-
return 1;
74-
}
75+
// Create the mobile_io object from the configuration
76+
std::cout << "Waiting for Mobile IO device to come online..." << std::endl;
77+
mobile_io = createMobileIOFromConfig(*example_config);
7578

76-
// Clear any garbage on screen
77-
mobile_io->resetUI();
79+
// Keep retrying if Mobile IO not found
80+
while (mobile_io == nullptr) {
81+
std::cout << "Couldn't find Mobile IO. Check name, family, or device status..." << std::endl;
7882

79-
// Setup instructions for display
80-
std::string instructions;
81-
instructions = ("B1 - Home Position\nB3 - AR Control Mode\n"
82-
"B6 - Grav Comp Mode\nB8 - Quit\n");
83+
// Retry
84+
mobile_io = createMobileIOFromConfig(*example_config);
85+
}
86+
std::cout << "Mobile IO connected." << std::endl;
8387

84-
// Display instructions on screen
85-
mobile_io->appendText(instructions);
88+
// Clear any garbage on screen
89+
mobile_io->clearText();
8690

87-
// Setup state variable for mobile device
88-
auto last_mobile_state = mobile_io->update();
91+
// Refresh mobile_io
92+
auto last_state = mobile_io->update();
8993

9094
//////////////////////////
9195
//// Main Control Loop ///
@@ -95,13 +99,15 @@ int main(int argc, char* argv[])
9599
bool softstart = true;
96100
bool ar_mode = false;
97101

98-
// Make sure we softstart the arm first.
102+
// Load user data from config
99103
Eigen::VectorXd home_position(arm -> robotModel().getDoFCount());
100-
home_position << 0, M_PI/3, 2*M_PI/3, 5*M_PI/6, -M_PI/2, 0; // Adjust depending on your DoFs
104+
home_position = Eigen::Map<const Eigen::VectorXd>(example_config->getUserData().getFloatList("home_position").data(), example_config->getUserData().getFloatList("home_position").size());
105+
double soft_start_time = example_config->getUserData().getFloat("homing_duration");
106+
double xyz_scale = example_config->getUserData().getFloat("xyz_scale");
101107

102108
// Command the softstart to home position
103109
arm -> update();
104-
arm -> setGoal(arm::Goal::createFromPosition(4, home_position)); // take 4 seconds
110+
arm -> setGoal(arm::Goal::createFromPosition(soft_start_time, home_position)); // take 4 seconds
105111
arm -> send();
106112

107113
// Get the cartesian position and rotation matrix @ home position
@@ -130,39 +136,36 @@ int main(int argc, char* argv[])
130136

131137
// Stay in softstart, don't do any other behavior
132138
continue;
133-
}
139+
}
134140

135141
// Get latest mobile_state
136142
auto updated_mobile_io = mobile_io->update(0);
137143

138-
if (!updated_mobile_io)
139-
std::cout << "Failed to get feedback from mobile I/O; check connection!\n";
140-
else
144+
if (updated_mobile_io)
141145
{
142146
// Button B1 - Return to home position
143-
if (mobile_io->getButtonDiff(1) == util::MobileIO::ButtonState::ToOn) {
144-
ar_mode = false;
145-
arm -> setGoal(arm::Goal::createFromPosition(4, home_position));
147+
if (mobile_io->getButtonDiff(1) == hebi::util::MobileIO::ButtonState::ToOn) {
148+
ar_mode = false;
149+
arm -> setGoal(arm::Goal::createFromPosition(soft_start_time, home_position));
146150
}
147151

148152
// Button B3 - Start AR Control
149-
if (mobile_io->getButtonDiff(3) == util::MobileIO::ButtonState::ToOn) {
153+
if (mobile_io->getButtonDiff(3) == hebi::util::MobileIO::ButtonState::ToOn) {
150154
xyz_phone_init << mobile_io -> getLastFeedback().mobile().arPosition().get().getX(),
151155
mobile_io -> getLastFeedback().mobile().arPosition().get().getY(),
152156
mobile_io -> getLastFeedback().mobile().arPosition().get().getZ();
153-
std::cout << xyz_phone_init << std::endl;
154157
rot_phone_init = makeRotationMatrix(mobile_io -> getLastFeedback().mobile().arOrientation().get());
155158
ar_mode = true;
156159
}
157160

158161
// Button B6 - Grav Comp Mode
159-
if (mobile_io->getButtonDiff(6) == util::MobileIO::ButtonState::ToOn) {
162+
if (mobile_io->getButtonDiff(6) == hebi::util::MobileIO::ButtonState::ToOn) {
160163
arm -> cancelGoal();
161164
ar_mode = false;
162165
}
163166

164167
// Button B8 - End Demo
165-
if (mobile_io->getButtonDiff(8) == util::MobileIO::ButtonState::ToOn) {
168+
if (mobile_io->getButtonDiff(8) == hebi::util::MobileIO::ButtonState::ToOn) {
166169
// Clear MobileIO text
167170
mobile_io->resetUI();
168171
return 1;
@@ -178,9 +181,9 @@ int main(int argc, char* argv[])
178181
auto rot_phone = makeRotationMatrix(mobile_io->getLastFeedback().mobile().arOrientation().get());
179182

180183
// Calculate new targets
181-
Eigen::Vector3d xyz_scale;
182-
xyz_scale << 1, 1, 2;
183-
Eigen::Vector3d xyz_target = xyz_home + (0.75 * xyz_scale.array() *
184+
Eigen::Vector3d xyz_scale_vec;
185+
xyz_scale_vec << 1, 1, 2;
186+
Eigen::Vector3d xyz_target = xyz_home + (xyz_scale * xyz_scale_vec.array() *
184187
(rot_phone_init.transpose() * (xyz_phone - xyz_phone_init)).array()).matrix();
185188
Eigen::Matrix3d rot_target = rot_phone_init.transpose() * rot_phone * rot_home;
186189

@@ -190,7 +193,7 @@ int main(int argc, char* argv[])
190193
rot_target);
191194

192195
// Create and send new goal to the arm
193-
arm -> setGoal(arm::Goal::createFromPosition(target_joints));
196+
arm -> setGoal(arm::Goal::createFromPosition(example_config->getUserData().getFloat("latency"), target_joints));
194197
}
195198

196199
// Send latest commands to the arm
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/**
2+
* This file is a barebones skeleton of how to setup an arm for use.
3+
* It demonstrates gravity compensation behavior by commanding torques
4+
* equal to the force from gravity on the links and joints of an arm.
5+
* Note that this only approximately balances out gravity, as imperfections in
6+
* the torque sensing and modeled system can lead to "drift". Also, the
7+
* particular choice of PID control gains can affect the performance of this
8+
* demo.
9+
*/
10+
11+
#include "group_command.hpp"
12+
#include "group_feedback.hpp"
13+
#include "robot_model.hpp"
14+
#include "arm/arm.hpp"
15+
#include "util/mobile_io.hpp"
16+
#include <chrono>
17+
#include "hebi_util.hpp"
18+
19+
using namespace hebi;
20+
using namespace experimental;
21+
22+
int main(int argc, char* argv[])
23+
{
24+
//////////////////////////
25+
///// Config Setup ///////
26+
//////////////////////////
27+
28+
// Config file path
29+
const std::string example_config_file = "config/ex_gravity_compensation_toggle.cfg.yaml";
30+
std::vector<std::string> errors;
31+
32+
// Load the config
33+
const auto example_config = RobotConfig::loadConfig(example_config_file, errors);
34+
for (const auto& error : errors) {
35+
std::cerr << error << std::endl;
36+
}
37+
if (!example_config) {
38+
std::cerr << "Failed to load configuration from: " << example_config_file << std::endl;
39+
return -1;
40+
}
41+
42+
// For this demo, we need the arm and mobile_io
43+
std::unique_ptr<arm::Arm> arm;
44+
std::unique_ptr<hebi::util::MobileIO> mobile_io;
45+
46+
//////////////////////////
47+
///// Arm Setup //////////
48+
//////////////////////////
49+
50+
// Create the arm object from the configuration
51+
arm = arm::Arm::create(*example_config);
52+
53+
// Keep retrying if arm not found
54+
while (!arm) {
55+
std::cerr << "Failed to create arm, retrying..." << std::endl;
56+
57+
// Retry
58+
arm = arm::Arm::create(*example_config);
59+
}
60+
std::cout << "Arm connected." << std::endl;
61+
62+
// Retrieve the gravcomp plugin from the arm
63+
64+
// Get a weak_ptr from the arm API, lock it as a shared_ptr, and then downcast it from a general plugin pointer to a specific plugin pointer
65+
auto plugin_shared_ptr = arm->getPluginByType<arm::plugin::GravityCompensationEffort>().lock();
66+
if (!plugin_shared_ptr) {
67+
std::cerr << "Failed to lock plugin shared_ptr. The plugin may have been destroyed." << std::endl;
68+
return -1;
69+
}
70+
auto gravcomp_plugin_ptr = std::dynamic_pointer_cast<arm::plugin::GravityCompensationEffort>(plugin_shared_ptr);
71+
if (!gravcomp_plugin_ptr) {
72+
std::cerr << "Failed to cast plugin to GravityCompensationEffort." << std::endl;
73+
return -1;
74+
}
75+
76+
//////////////////////////
77+
//// MobileIO Setup //////
78+
//////////////////////////
79+
80+
// Create the mobile_io object from the configuration
81+
std::cout << "Waiting for Mobile IO device to come online..." << std::endl;
82+
mobile_io = createMobileIOFromConfig(*example_config);
83+
84+
// Keep retrying if Mobile IO not found
85+
while (mobile_io == nullptr) {
86+
std::cout << "Couldn't find Mobile IO. Check name, family, or device status..." << std::endl;
87+
88+
// Retry
89+
mobile_io = createMobileIOFromConfig(*example_config);
90+
}
91+
std::cout << "Mobile IO connected." << std::endl;
92+
93+
// Clear any garbage on screen
94+
mobile_io->clearText();
95+
96+
// Refresh mobile_io
97+
auto last_state = mobile_io->update();
98+
99+
std::cout << "Commanded gravity-compensated zero force to the arm.\n"
100+
<< " 🌍 (B2) - Toggles the gravity compensation on/off:\n"
101+
<< " ON - Apply controller \n"
102+
<< " OFF - Disable controller\n"
103+
<< " ❌ (B1) - Exits the demo.\n";
104+
105+
//////////////////////////
106+
//// Main Control Loop ///
107+
//////////////////////////
108+
109+
while(arm->update())
110+
{
111+
auto updated_mobile_io = mobile_io->update(0);
112+
113+
if (updated_mobile_io)
114+
{
115+
/////////////////
116+
// Button Presses
117+
/////////////////
118+
119+
// Buttton B1 - End demo
120+
if (mobile_io->getButtonDiff(1) == hebi::util::MobileIO::ButtonState::ToOn) {
121+
// Clear MobileIO text
122+
mobile_io->resetUI();
123+
return 1;
124+
}
125+
126+
// Button B2 - Set and unset gravcomp mode when button is pressed and released, respectively
127+
if (mobile_io->getButtonDiff(2) == hebi::util::MobileIO::ButtonState::ToOn) {
128+
129+
// Enable gravcomp
130+
gravcomp_plugin_ptr->setEnabled(true);
131+
}
132+
else if (mobile_io->getButtonDiff(2) == hebi::util::MobileIO::ButtonState::ToOff){
133+
134+
// Disable gravcomp
135+
gravcomp_plugin_ptr->setEnabled(false);
136+
}
137+
}
138+
// Send latest commands to the arm
139+
arm->send();
140+
}
141+
142+
return 0;
143+
}
144+
145+
146+

0 commit comments

Comments
 (0)