Reputation: 65
I'm setting up a simple simulation where I want a body (a box) to fall in a gravity field for half a second and then rise up due to a force I apply on it which overcomes gravity.
I've tried implementing this force using three methods, using AddInForce
, AddInForceInWorld
, and AddForceElement
. Since this is called while the simulation is running, AddForceElement
threw an error as expected. With the other two, though, no errors or warnings were thrown, yet the box clearly does not have a new force acting on it.
I've checked for a new force element with num_force_elements()
too but none are added.
Here is my loop for timing this event:
while( current_time < FLAGS_duration && !terminate){
if (current_time > 0.5 && !forced) {
std::cout << "\nAdding Force of type " << FLAGS_box_f << " at 0.5 seconds...\n";
// Add Rising Force to box
auto forces = drake::multibody::MultibodyForces<double>(plant);
drake::multibody::SpatialForce<double> forceup(Vector3d::Zero(), Vector3d(0, 0, 100));
if (FLAGS_box_f == "spring") {
plant.AddForceElement<LinearSpringDamper>(
plant.GetBodyByName("Box"), Vector3d::Zero(),
plant.world_body(), Vector3d(0, 0, 1),
0., 10., 1.);
} else if (FLAGS_box_f == "world") {
plant.GetBodyByName("Box").AddInForceInWorld(
plant_context,
forceup,
&forces);
} else {
plant.GetBodyByName("Box").AddInForce(
plant_context,
Vector3d::Zero(),
forceup,
plant.GetBodyByName("Box").body_frame(),
&forces);
}
plant.CalcForceElementsContribution(plant_context, &forces);
std::cout << "Plant: " << plant.num_force_elements() << " force_elements\n";
forced = true;
}
simulator.StepTo(current_time + time_delta);
current_time = simulator_context.get_time();
}
I'm not sure if I'm going through the motions right, and also still don't understand very well the MultibodyForces object I am storing the forces in the calls to.
Upvotes: 3
Views: 248
Reputation: 1099
@Joaquin Giraldo,
The way to add external forces to your model is with an input force. Everything in Drake are input/output ports. In this case, you must use MultibodyPlant::get_applied_spatial_force_input_port()
.
See the file multibody/plant/test/externally_applied_spatial_force_test.cc
for an example on how to do this.
Upvotes: 2
Reputation: 678
Quick note: what you need is a force element that is always present, but varies its force output based on time. None of the built-in ones behave that way, so you will have to write one.
Upvotes: 1