-
Notifications
You must be signed in to change notification settings - Fork 48
/
Copy pathExternalWrench.cc
173 lines (143 loc) · 6.1 KB
/
ExternalWrench.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include "ExternalWrench.hh"
int ExternalWrench::count = 0;
//Initializing wrench command
ExternalWrench::ExternalWrench()
{
model_has_link = false;
//srand(boost::lexical_cast<float>(std::time(NULL)));
srand(rand()%100);
color[0] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
color[1] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
color[2] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
color[3] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
wrenchPtr->link_name = "world";
wrenchPtr->force.resize(3,0);
wrenchPtr->torque.resize(3,0);
wrenchPtr->duration = 0.0;
count++;
tick = yarp::os::Time::now();
duration_done = false;
}
bool ExternalWrench::getLink()
{
// Get the exact link with only link name instead of full_scoped_link_name
links = this->model->GetLinks();
for(int i=0; i < links.size(); i++)
{
std::string candidate_link_name = links[i]->GetScopedName();
// hasEnding compare ending of the condidate model link name to the given link name, in order to be able to use unscoped names
if(GazeboYarpPlugins::hasEnding(candidate_link_name, wrenchPtr->link_name))
{
link = links[i];
break;
}
}
if(!link)
{
return false;
}
model_has_link = true;
return true;
}
void ExternalWrench::setVisual()
{
//Wrench Visual
m_node = transport::NodePtr(new gazebo::transport::Node());
this->m_node->Init(model->GetWorld()->Name());
m_visPub = this->m_node->Advertise<msgs::Visual>("~/visual",100);
// Set the visual's name. This should be unique.
std::string visual_name = "__" + wrenchPtr->link_name + "__CYLINDER_VISUAL__" + boost::lexical_cast<std::string>(count);
m_visualMsg.set_name (visual_name);
// Set the visual's parent. This visual will be attached to the parent
m_visualMsg.set_parent_name(model->GetScopedName());
// Create a cylinder
msgs::Geometry *geomMsg = m_visualMsg.mutable_geometry();
geomMsg->set_type(msgs::Geometry::CYLINDER);
geomMsg->mutable_cylinder()->set_radius(0.0075);
geomMsg->mutable_cylinder()->set_length(.30);
// Don't cast shadows
m_visualMsg.set_cast_shadows(false);
}
bool ExternalWrench::setWrench(physics::ModelPtr& _model,yarp::os::Bottle& cmd)
{
model = _model;
//get link name from command
wrenchPtr->link_name = cmd.get(0).asString();
if(getLink())
{
setVisual();
wrenchPtr->force[0] = cmd.get(1).asDouble();
wrenchPtr->force[1] = cmd.get(2).asDouble();
wrenchPtr->force[2] = cmd.get(3).asDouble();
wrenchPtr->torque[0] = cmd.get(4).asDouble();
wrenchPtr->torque[1] = cmd.get(5).asDouble();
wrenchPtr->torque[2] = cmd.get(6).asDouble();
wrenchPtr->duration = cmd.get(7).asDouble();
return true;
}
else return false;
}
void ExternalWrench::applyWrench()
{
tock = yarp::os::Time::now();
if((tock-tick) < wrenchPtr->duration)
{
#if GAZEBO_MAJOR_VERSION >= 8
ignition::math::Vector3d force (wrenchPtr->force[0], wrenchPtr->force[1], wrenchPtr->force[2]);
ignition::math::Vector3d torque (wrenchPtr->torque[0], wrenchPtr->torque[1], wrenchPtr->torque[2]);
link->AddForce(force);
link->AddTorque(torque);
ignition::math::Vector3d linkCoGPos = link->WorldCoGPose().Pos(); // Get link's COG position where wrench will be applied
ignition::math::Vector3d newZ = force.Normalize(); // normalized force. I want the z axis of the cylinder's reference frame to coincide with my force vector
ignition::math::Vector3d newX = newZ.Cross (ignition::math::Vector3d::UnitZ);
ignition::math::Vector3d newY = newZ.Cross (newX);
ignition::math::Matrix4d rotation = ignition::math::Matrix4d (newX[0],newY[0],newZ[0],0,newX[1],newY[1],newZ[1],0,newX[2],newY[2],newZ[2],0, 0, 0, 0, 1);
ignition::math::Quaterniond forceOrientation = rotation.Rotation();
ignition::math::Pose3d linkCoGPose (linkCoGPos - rotation*ignition::math::Vector3d ( 0,0,.15 ), forceOrientation);
#else
math::Vector3d force (wrenchPtr->force[0], wrenchPtr->force[1], wrenchPtr->force[2]);
math::Vector3d torque (wrenchPtr->torque[0], wrenchPtr->torque[1], wrenchPtr->torque[2]);
link->AddForce(force);
link->AddTorque(torque);
math::Vector3d linkCoGPos = link->WorldCoGPose().Pos(); // Get link's COG position where wrench will be applied
math::Vector3d newZ = force.Normalize(); // normalized force. I want the z axis of the cylinder's reference frame to coincide with my force vector
math::Vector3d newX = newZ.Cross (ignition::math::Vector3d::UnitZ);
math::Vector3d newY = newZ.Cross (newX);
math::Matrix4d rotation = ignition::math::Matrix4d (newX[0],newY[0],newZ[0],0,newX[1],newY[1],newZ[1],0,newX[2],newY[2],newZ[2],0, 0, 0, 0, 1);
math::Quaterniond forceOrientation = rotation.Rotation();
math::Pose3d linkCoGPose (linkCoGPos - rotation*ignition::math::Vector3d ( 0,0,.15 ), forceOrientation);
#endif
#if GAZEBO_MAJOR_VERSION == 7
msgs::Set(m_visualMsg.mutable_pose(), linkCoGPose.Ign());
#else
msgs::Set(m_visualMsg.mutable_pose(), linkCoGPose);
#endif
#if GAZEBO_MAJOR_VERSION >= 9
msgs::Set(m_visualMsg.mutable_material()->mutable_ambient(), ignition::math::Color(color[0],color[1],color[2],color[3]));
#else
msgs::Set(m_visualMsg.mutable_material()->mutable_ambient(),common::Color(color[0],color[1],color[2],color[3]));
#endif
m_visualMsg.set_visible(1);
m_visPub->Publish(m_visualMsg);
}
else
{
deleteWrench();
}
}
void ExternalWrench::deleteWrench()
{
this->wrenchPtr->link_name.clear();
this->wrenchPtr->force.clear();
this->wrenchPtr->torque.clear();
this->wrenchPtr->duration = 0;
this->m_visualMsg.set_visible(0);
this->m_visualMsg.clear_geometry();
this->m_visualMsg.clear_delete_me();
this->m_visPub->Publish(m_visualMsg);
this->duration_done = true;
}
ExternalWrench::~ExternalWrench()
{
count--;
}