-
Notifications
You must be signed in to change notification settings - Fork 302
How to change material of model in system plugin? #842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That functionality hasn't been implemented yet. The implementation would be similar to how we update lights, see #482 as a reference. |
Hi, Sorry to reopen - @chapulina do you know if there has been any progress on this since 2021? I'm on gazebo fortress (ignition/gazebo6 i think). Kind of assumed this was working and made a plugin for students to work with in 2 weeks time then saw this issue when it wasnt... To be more specific, you can manually change the material properties in the gazebo GUI, and the changes are reflected in the live simulation. However it seems that changing the material properties in a plugin as described above does not make any differences. |
This was implemented as part of #1123. You can change material attributes using a gz-sim/src/systems/user_commands/UserCommands.cc Lines 1865 to 1912 in 9d6230a
|
Hi @azeey I finally got back to working on this - apologies a couple of questions as I'm still not used to the component model As far as I understand, VisualCommand is updated via an ign topic exposed by the UserCommands component. How exactly do I enable the UserCommands component so that the VisualCommands topic is created?
Observing my empty.sdf we have the following which does enable the UserCommands plugin, but when running <?xml version="1.0"?>
<sdf version="1.6">
<world name="empty_delivery">
<physics name="4ms" type="ignored">
<max_step_size>0.004</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>
<plugin
filename="ignition-gazebo-physics-system"
name="ignition::gazebo::systems::Physics">
</plugin>
<plugin
filename="ignition-gazebo-scene-broadcaster-system"
name="ignition::gazebo::systems::SceneBroadcaster">
</plugin>
<plugin
filename="ignition-gazebo-user-commands-system"
name="ignition::gazebo::systems::UserCommands">
</plugin>
<plugin
filename="ignition-gazebo-sensors-system"
name="ignition::gazebo::systems::Sensors">
<render_engine>ogre2</render_engine>
</plugin>
<!-- Uncomment this if you want to use SuctionGripper model -->
<!-- <plugin
filename="ignition-gazebo-contact-system"
name="ignition::gazebo::systems::Contact">
</plugin> -->
<light type="directional"
name="sun">
<cast_shadows>true</cast_shadows>
<pose>0 0 10 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>1000</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>
{% if use_origin -%}
<spherical_coordinates>
<surface_model>EARTH_WGS84</surface_model>
<latitude_deg>{{ origin.latitude }}</latitude_deg>
<longitude_deg>{{ origin.longitude }}</longitude_deg>
<elevation>{{ origin.altitude }}</elevation>
<heading_deg>0.0</heading_deg><!-- Temporary fix for issue
https://bitbucket.org/osrf/gazebo/issues/2022/default-sphericalcoordinates-frame-should -->
</spherical_coordinates>
{% endif -%}
<include>
<uri>model://ground_plane</uri>
</include>
</world>
</sdf> Sorry to reopen and thanks in advance! |
So just to add on, I have created a publisher to visual_config within my plugin and can see the echos when running
I have double checked that the entity ids match what the Visuals I'm trying to change in the gazebo Tree. A weirdness is that there doesn't seem to be any subscribers on this topic which is concerning. I would have expected there to be at least one subscriber from UserCommands if I have understood the code corectly: For more information, here is the entity I am creating: // Create a visual
sdf::Visual sdfVisual;
sdfVisual.SetName("led" + std::to_string(i));
sdfVisual.SetPoseRelativeTo("base_frame");
// Calculate x, y position
float x = this->ring_radius * std::cos(angle_delta * i);
float y = this->ring_radius * std::sin(angle_delta * i);
sdfVisual.SetRawPose(gz::math::Pose3d(x, y, this->ring_z_offset, 0.0, 0.0, 0.0));
// Set cylinder geometry
sdf::Cylinder cyl;
cyl.SetRadius(0.015);
cyl.SetLength(0.015);
sdf::Geometry sdfGeom;
sdfGeom.SetType(sdf::GeometryType::CYLINDER);
sdfGeom.SetCylinderShape(cyl);
sdfVisual.SetGeom(sdfGeom);
float r = this->led_colours[i * 3 + 0];
float b = this->led_colours[i * 3 + 1];
float g = this->led_colours[i * 3 + 2];
// Set material
sdf::Material sdfMaterial;
// Set the diffuse color to match the LED's body color
sdfMaterial.SetDiffuse(gz::math::Color(r,g,b, 1.0));
// Set the emissive color to simulate light emission
sdfMaterial.SetEmissive(gz::math::Color(r,g,b, 1.0)); // Bright red
// Set the specular color to simulate glossy reflection
sdfMaterial.SetSpecular(gz::math::Color(0.8, 0.8, 0.8, 1.0)); // Near-white for strong highlights
// Optionally add transparency for a translucent effect
sdfVisual.SetTransparency(0.1); // Slightly translucent
sdfVisual.SetMaterial(sdfMaterial);
// Add the visual to the link
sdfLink.AddVisual(sdfVisual);
// Assuming `entityCreator` is already being used to create the entity
auto visualEntity = entityCreator.CreateEntities(&sdfVisual);
if (visualEntity == gz::sim::kNullEntity) {
ignerr << "Failed to create visual entity" << std::endl;
continue;
}
// Ensure it's marked as a Visual in Gazebo
_ecm.CreateComponent(visualEntity, gz::sim::components::Visual());
_ecm.CreateComponent(visualEntity, gz::sim::components::Material());
this->led_id_entity_map[i] = visualEntity;
entityCreator.SetParent(visualEntity, linkEntity); And here is how I'm calling the topic: gz::msgs::Visual msg;
gz::sim::Entity visual_entity = this->led_id_entity_map[i];
msg.set_id(visual_entity);
// msg.set_name("drone0::leds_link::led0");
// Modify the material color (RGBA format)
gz::msgs::Material *mat = msg.mutable_material();
gz::msgs::Set(mat->mutable_diffuse(), gz::math::Color(r, g, b, 1.0)); // Red color
gz::msgs::Set(mat->mutable_emissive(), gz::math::Color(r, g, b, 1.0)); // Red color
gz::msgs::Set(mat->mutable_specular(), gz::math::Color(0.8, 0.8, 0.8, 1.0)); // Red color
gz::msgs::Set(mat->mutable_ambient(), gz::math::Color(0.8, 0.8, 0.8, 1.0)); // Red color
msg.set_transparency(0.5);
msg.set_type(gz::msgs::Visual::VISUAL);
this->visual_config_pub.Publish(msg);
ignerr << "Published Diffusive and Emmisive to " << visual_entity << std::endl; For greater context here is gazebo visuals. I am trying to create a programmable ring of lights for this crazyflie drone model to match the real light rings. Unfortunately despite sending the above messages to gazebo, the "lights" remain grey. They still change if I manually change the materials within the gazebo gui (though I cannot see any messages from the gui changes in the visuals_config topic) p.s. I have verified that UserCommand is loading as we get the printouts X service on [...] matching whats in the source code |
Hi all, I finally figured out the sticking point which is that visual_config is a service! Hence it needs a service call! gz::msgs::Visual msg;
gz::sim::Entity visual_entity = this->led_id_entity_map[i];
msg.set_id(visual_entity);
// Modify the material color (RGBA format)
gz::msgs::Material *mat = msg.mutable_material();
gz::msgs::Set(mat->mutable_diffuse(), gz::math::Color(r, g, b, 1.0)); // Red color
gz::msgs::Set(mat->mutable_emissive(), gz::math::Color(r, g, b, 1.0)); // Red color
std::function<void(const ignition::msgs::Boolean &, const bool)> cb =
[](const ignition::msgs::Boolean &/*_rep*/, const bool _result)
{
if (!_result)
ignerr << "Error setting material color configuration"
<< " on visual" << std::endl;
};
this->node.Request(this->visual_config_service_name, msg, cb);
ignerr << "Sent Service Call Diffusive and Emmisive to " << visual_entity << std::endl;
this->visual_config_pub.Publish(msg); Where I set the // Set World here as ECM is not fully initialised
this->world = gz::sim::World(gz::sim::worldEntity(_ecm));
// Create Subscriber to the visual_config with world
std::string world_name = *this->world.Name(_ecm);
this->visual_config_service_name = "/world/"+world_name+"/visual_config";
ignerr << "Materials Service Call Sent To " << this->visual_config_service_name << std::endl; With that fixed, the whole stack works amazing. Hope this thread helps others! :) |
ah didn't get a chance to respond earlier, but glad you're able to figure it out. Thanks for posting back the code snippet! |
I want to change color of model dynamically by using plugin. Then I modify component
Material
in componentVisual
by usingSetComponentData()
inPreUpdate()
, but there is no effect.So, Does anyone know how to change material of model in system plugin? Thank you!
The text was updated successfully, but these errors were encountered: