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.