ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Add fog to gazebo using rospy

asked 2021-12-11 15:08:22 -0500

jdastoor3 gravatar image

updated 2022-02-11 11:17:43 -0500

lucasw gravatar image


I have been trying to create a script that will spawn objects and take images of them for object detection. I would like to simulate difficult conditions where there might be fog present, and have the level of fog vary between each image I am taking. However, I am not sure how to change gazebo world settings using a rospy script. I am aware that I can change the <scene> tag in the .world file, however this is less than ideal as I would like the fog level to update automatically within my script. I have been searching for a while on any solutions to this and have not found any. Any help on this would be appreciated, thanks!

edit retag flag offensive close merge delete


Have you looked into pygazebo?

It’s in Python2 documentation link:

But there is py3gazebo fork:

osilva gravatar image osilva  ( 2021-12-11 15:48:50 -0500 )edit
osilva gravatar image osilva  ( 2021-12-11 15:56:12 -0500 )edit

I tried doing that just now, and I get an error saying "cannot import name 'connect' from partially initialized module 'pygazebo' (most likely due to a circular import)". I pip installed pygazebo.

from pygazebo.msg import fog_pb2

if __name__ == "__main__":
jdastoor3 gravatar image jdastoor3  ( 2021-12-11 16:48:07 -0500 )edit

Just a watch out if you install via pip is Python2 and you need a complimentary library

Check the example in:

osilva gravatar image osilva  ( 2021-12-11 17:04:00 -0500 )edit

I followed the steps at the bottom of py3gazebo to convert the python2 version to the python3 version, yet that still gives me the same error.

jdastoor3 gravatar image jdastoor3  ( 2021-12-11 17:27:14 -0500 )edit

Update: I managed to get a bit further, but now I get another error in line 251,

future = asyncio.async(loop.sock_connect(self.socket, address))
SyntaxError : invalid syntax
jdastoor3 gravatar image jdastoor3  ( 2021-12-11 17:41:50 -0500 )edit

I used it back in Kinetic, there a few errors. I just tried it as well and fixing them

osilva gravatar image osilva  ( 2021-12-11 18:46:13 -0500 )edit

1 Answer

Sort by » oldest newest most voted

answered 2021-12-13 09:21:30 -0500

osilva gravatar image

updated 2021-12-13 09:23:04 -0500

Hi @jdastoor3

Apologies for suggesting pygazebo, I was able to make it work but there are many bugs. Instead, I went over again and I think using Gazebo Services is the way to go:

After you launch gazebo using roslaunch gazebo_ros empty_world.launch in another terminal you can check services available: rosservice list If you look into: rosservice info /gazebo/set_light_properties you will get:

Node: /gazebo

    URI: rosrpc://127....
    Type: gazebo_msgs/SetLightProperties
    Args: light_name cast_shadows diffuse specular attenuation_constant attenuation_linear attenuation_quadratic direction pose

And if you look further into this by rossrv show gazebo_msgs/SetLightProperties

string light_name
bool cast_shadows
std_msgs/ColorRGBA diffuse
  float32 r
  float32 g
  float32 b
  float32 a
std_msgs/ColorRGBA specular
  float32 r
  float32 g
  float32 b
  float32 a
float64 attenuation_constant
float64 attenuation_linear
float64 attenuation_quadratic
geometry_msgs/Vector3 direction
  float64 x
  float64 y
  float64 z
geometry_msgs/Pose pose
  geometry_msgs/Point position
    float64 x
    float64 y
    float64 z
  geometry_msgs/Quaternion orientation
    float64 x
    float64 y
    float64 z
    float64 w
bool success
string status_message

To access with Python, I wrote this script:

#!/usr/bin/env python
import time
import rospy

from gazebo_msgs.srv import SetPhysicsProperties, SetPhysicsPropertiesRequest
from gazebo_msgs.srv import SetLightProperties, SetLightPropertiesRequest
from geometry_msgs.msg import Pose, Quaternion
from geometry_msgs.msg import Vector3
from std_msgs.msg import Float64    
from std_msgs.msg import ColorRGBA  
from std_srvs.srv import Empty 

service_name = '/gazebo/set_light_properties'
rospy.loginfo("Waiting for service " + str(service_name))
rospy.loginfo("Service Found "+str(service_name))

set_light = rospy.ServiceProxy(service_name, SetLightProperties)

light_name = 'sun'
cast_shadows = True

difuse = ColorRGBA()
difuse.r = float(204/255)
difuse.g = float(204/255)
difuse.b = float(204/255)
difuse.a = float(255/255)

specular = ColorRGBA()
specular.r = float(51/255)
specular.g = float(51/255)
specular.b = float(51/255)
specular.a = float(255/255)

attenuation_constant = 0.90
attenuation_linear = 0.01
attenuation_qudratic = 0.00

direction = Vector3()
direction.x = -0.483368
direction.y = 0.096674
direction.z = -0.870063

pose = Pose()
pose.position.x = 0.00
pose.position.y = 0.00
pose.position.z = 10.00

pose.orientation.x = 0.00
pose.orientation.y = 0.00
pose.orientation.z = 0.00
pose.orientation.w = 1.00

response = set_light(light_name, cast_shadows, difuse, specular, attenuation_constant, attenuation_linear, attenuation_qudratic, direction, pose)


I am using the default settings that you can see in Gazebo:

image description

Hope this helps you, then you can change light conditions or other properties to set fog.

edit flag offensive delete link more


There is an example of subsea world that you can use for fog settings:


For ODE Physics you will need as an example:

from gazebo_msgs.msg import ODEPhysics
ode_config = ODEPhysics()
ode_config.auto_disable_bodies = False
ode_config.sor_pgs_precon_iters = 0
ode_config.sor_pgs_iters = 50
ode_config.sor_pgs_w = 1.3
ode_config.sor_pgs_rms_error_tol = 0.0
ode_config.contact_surface_layer = 0.001
ode_config.contact_max_correcting_vel = 0.0
ode_config.cfm = 0.0
ode_config.erp = 0.2
ode_config.max_contacts = 20
osilva gravatar image osilva  ( 2021-12-13 09:40:46 -0500 )edit

Thank you for the response! I tried using SetLightProperties, however the light only seems to have an impact on the land, not on the water, which remains the same color (where I care about the impact the most). I also don't think pygazebo is the best way because I think it only works on Python 3.6, which is why it was not working for me.

jdastoor3 gravatar image jdastoor3  ( 2021-12-13 11:36:26 -0500 )edit

Check the example of subsea. You can change the sky with any material + lights might do the trick

osilva gravatar image osilva  ( 2021-12-13 11:49:53 -0500 )edit

Also you can set this at the .sdf level first:

osilva gravatar image osilva  ( 2021-12-13 11:57:46 -0500 )edit

I want to be able to change the fog level inside my script during each main loop. So I can set the base fog level in the <scene> tag, but I would like a way to do it in Python. The subsea example looks like it's just set in the .world file

jdastoor3 gravatar image jdastoor3  ( 2021-12-13 12:17:24 -0500 )edit

Only way to get at that level that I am aware is thru Gazebo API in C++

osilva gravatar image osilva  ( 2021-12-13 12:19:13 -0500 )edit

Or you could ‘cheat’ and just change the world file with different settings

osilva gravatar image osilva  ( 2021-12-13 12:20:04 -0500 )edit

Using pygazebo, did you have to use python 3.6?

jdastoor3 gravatar image jdastoor3  ( 2021-12-13 14:19:29 -0500 )edit

Question Tools



Asked: 2021-12-11 15:08:22 -0500

Seen: 420 times

Last updated: Dec 13 '21