-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeformable_torus.cc
217 lines (188 loc) · 8.94 KB
/
deformable_torus.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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#include <fstream>
#include <iostream>
#include <memory>
#include <gflags/gflags.h>
#include "drake/common/find_resource.h"
#include "drake/geometry/drake_visualizer.h"
#include "drake/geometry/proximity_properties.h"
#include "drake/geometry/scene_graph.h"
#include "drake/math/rigid_transform.h"
#include "drake/multibody/fem/deformable_body_config.h"
#include "drake/multibody/parsing/parser.h"
#include "drake/multibody/plant/deformable_model.h"
#include "drake/multibody/plant/multibody_plant.h"
#include "drake/multibody/plant/multibody_plant_config_functions.h"
#include "drake/multibody/tree/prismatic_joint.h"
#include "drake/systems/analysis/simulator.h"
#include "drake/systems/framework/diagram.h"
#include "drake/systems/framework/diagram_builder.h"
DEFINE_double(simulation_time, 8.0, "Desired duration of the simulation [s].");
DEFINE_double(realtime_rate, 1.0, "Desired real time rate.");
DEFINE_double(time_step, 5e-4,
"Discrete time step for the system [s]. Must be positive.");
DEFINE_double(E, 5e3, "Young's modulus of the deformable body [Pa].");
DEFINE_double(nu, 0.4, "Poisson's ratio of the deformable body, unitless.");
DEFINE_double(density, 8e2, "Mass density of the deformable body [kg/m³].");
DEFINE_double(beta, 0.01,
"Stiffness damping coefficient for the deformable body [1/s].");
using drake::geometry::AddContactMaterial;
using drake::geometry::Box;
using drake::geometry::GeometryId;
using drake::geometry::GeometryInstance;
using drake::geometry::IllustrationProperties;
using drake::geometry::KinematicsVector;
using drake::geometry::Mesh;
using drake::geometry::ProximityProperties;
using drake::math::RigidTransformd;
using drake::multibody::AddMultibodyPlant;
using drake::multibody::Body;
using drake::multibody::CoulombFriction;
using drake::multibody::DeformableBodyId;
using drake::multibody::DeformableModel;
using drake::multibody::MultibodyPlantConfig;
using drake::multibody::Parser;
using drake::multibody::PrismaticJoint;
using drake::multibody::fem::DeformableBodyConfig;
using drake::systems::BasicVector;
using drake::systems::Context;
using Eigen::Vector2d;
using Eigen::Vector4d;
using Eigen::VectorXd;
namespace drake {
namespace examples {
namespace {
/* We create a leaf system that uses PD control to output a force signal to
a gripper to follow a close-lift-open motion sequence. The signal is
2-dimensional with the first element corresponding to the wrist degree of
freedom and the second element corresponding to the left finger degree of
freedom. This control is a time-based state machine, where forces change based
on the context time. This is strictly for demo purposes and is not intended to
generalize to other cases. There are four states: 0. The fingers are open in
the initial state.
1. The fingers are closed to secure a grasp.
2. The gripper is lifted to a prescribed final height.
3. The fingers are open to loosen a grasp.
The desired state is interpolated between these states. */
int do_main() {
systems::DiagramBuilder<double> builder;
MultibodyPlantConfig plant_config;
plant_config.time_step = FLAGS_time_step;
/* Deformable simulation only works with SAP solver. */
plant_config.discrete_contact_solver = "sap";
auto [plant, scene_graph] = AddMultibodyPlant(plant_config, &builder);
/* Minimum required proximity properties for rigid bodies to interact with
deformable bodies.
1. A valid Coulomb friction coefficient, and
2. A resolution hint. (Rigid bodies need to be tesselated so that collision
queries can be performed against deformable geometries.) */
ProximityProperties rigid_proximity_props;
/* Set the friction coefficient close to that of rubber against rubber. */
const CoulombFriction<double> surface_friction(1.15, 1.15);
AddContactMaterial({}, {}, surface_friction, &rigid_proximity_props);
rigid_proximity_props.AddProperty(geometry::internal::kHydroGroup,
geometry::internal::kRezHint, 1.0);
/* Set up a ground. */
Box ground{4, 4, 4};
const RigidTransformd X_WG(Eigen::Vector3d{0, 0, -2});
plant.RegisterCollisionGeometry(plant.world_body(), X_WG, ground,
"ground_collision", rigid_proximity_props);
IllustrationProperties illustration_props;
illustration_props.AddProperty("phong", "diffuse",
Vector4d(0.7, 0.5, 0.4, 0.8));
plant.RegisterVisualGeometry(plant.world_body(), X_WG, ground,
"ground_visual", std::move(illustration_props));
// TODO(xuchenhan-tri): Consider using a schunk gripper from the manipulation
// station instead.
/* Set up a simple gripper. */
Parser parser(&plant);
/* Set up a deformable torus. */
auto owned_deformable_model =
std::make_unique<DeformableModel<double>>(&plant);
DeformableBodyConfig<double> deformable_config;
deformable_config.set_youngs_modulus(FLAGS_E);
deformable_config.set_poissons_ratio(FLAGS_nu);
deformable_config.set_mass_density(FLAGS_density);
deformable_config.set_stiffness_damping_coefficient(FLAGS_beta);
const std::string torus_vtk = FindResourceOrThrow(
"drake/examples/multibody/deformable_torus/bunny.vtk");
/* Load the geometry and scale it down to 65% (to showcase the scaling
capability and to make the torus suitable for grasping by the gripper). */
const double scale = 0.80;
auto torus_mesh = std::make_unique<Mesh>(torus_vtk, scale);
/* Minor diameter of the torus inferred from the vtk file. */
// const double kL = 0.09 * scale;
/* Set the initial pose of the torus such that its bottom face is touching the
ground. */
const RigidTransformd X_WB(Vector3<double>(0.0, 0.0, 0.005));
auto torus_instance = std::make_unique<GeometryInstance>(
X_WB, std::move(torus_mesh), "deformable_torus");
/* Minimumly required proximity properties for deformable bodies: A valid
Coulomb friction coefficient. */
ProximityProperties deformable_proximity_props;
AddContactMaterial({}, {}, surface_friction, &deformable_proximity_props);
torus_instance->set_proximity_properties(deformable_proximity_props);
/* Registration of all deformable geometries ostensibly requires a resolution
hint parameter that dictates how the shape is tesselated. In the case of a
`Mesh` shape, the resolution hint is unused because the shape is already
tessellated. */
// TODO(xuchenhan-tri): Though unused, we still asserts the resolution hint is
// positive. Remove the requirement of a resolution hint for meshed shapes.
const double unused_resolution_hint = 1.0;
// DeformableBodyId torus_id =
// owned_deformable_model->RegisterDeformableBody(
owned_deformable_model->RegisterDeformableBody(
std::move(torus_instance), deformable_config, unused_resolution_hint);
const DeformableModel<double>* deformable_model =
owned_deformable_model.get();
plant.AddPhysicalModel(std::move(owned_deformable_model));
/* All rigid and deformable models have been added. Finalize the plant. */
plant.Finalize();
/* It's essential to connect the vertex position port in DeformableModel to
the source configuration port in SceneGraph when deformable bodies are
present in the plant. */
builder.Connect(
deformable_model->vertex_positions_port(),
scene_graph.get_source_configuration_port(plant.get_source_id().value()));
/* Add a visualizer that emits LCM messages for visualization. */
geometry::DrakeVisualizerd::AddToBuilder(&builder, scene_graph);
auto diagram = builder.Build();
std::unique_ptr<Context<double>> diagram_context =
diagram->CreateDefaultContext();
/* Build the simulator and run! */
systems::Simulator<double> simulator(*diagram, std::move(diagram_context));
simulator.Initialize();
simulator.set_target_realtime_rate(1.0);
simulator.set_publish_every_time_step(true);
simulator.AdvanceTo(FLAGS_simulation_time);
// const Context<double>& context =
// diagram->GetSubsystemContext(plant, simulator.get_context());
// double t = 0.0;
// double tstep = 0.01;
// std::ofstream file;
// file.open("/tmp/results.csv");
// while (t < FLAGS_simulation_time) {
// simulator.AdvanceTo(t);
// t += tstep;
// auto vals = deformable_model->vertex_positions_port().Eval<KinematicsVector<GeometryId, VectorXd>>(context);
// for (auto val : vals.value(vals.ids()[0])) {
// // std::cout << val;
// file << val << ",";
// }
// file << std::endl;
// }
// file.close();
return 0;
}
} // namespace
} // namespace examples
} // namespace drake
int main(int argc, char* argv[]) {
gflags::SetUsageMessage(
"This is a demo used to showcase deformable body simulations in Drake. "
"A simple parallel gripper grasps a deformable torus on the ground, "
"lifts it up, and then drops it back on the ground. "
"Launch meldis before running this example. "
"Refer to README for instructions on meldis as well as optional flags.");
gflags::ParseCommandLineFlags(&argc, &argv, true);
return drake::examples::do_main();
}