Skip to content

Commit d4c2ea4

Browse files
authored
added Light class. (#287)
* added Light class. * reverted test_scene.ttt back to version 4.1 instead of 4.2. * fixed failing test test_get_objects_in_tree. * removed warnings assertion from test_get_objects_in_tree.
1 parent 9bcf2c1 commit d4c2ea4

File tree

7 files changed

+253
-8
lines changed

7 files changed

+253
-8
lines changed

pyrep/backend/sim.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,21 @@ def simAddForce(shapeHandle, position, force):
14741474

14751475
def simAddForceAndTorque(shapeHandle, force, torque):
14761476
ret = lib.simAddForceAndTorque(shapeHandle,
1477-
ffi.NULL if force is None else force,
1478-
ffi.NULL if torque is None else torque)
1477+
ffi.NULL if force is None else force,
1478+
ffi.NULL if torque is None else torque)
14791479
_check_return(ret)
1480+
1481+
1482+
def simSetLightParameters(shapeHandle, state, diffusePart=None, specularPart=None):
1483+
ret = lib.simSetLightParameters(shapeHandle, state, ffi.NULL,
1484+
ffi.NULL if diffusePart is None else diffusePart,
1485+
ffi.NULL if specularPart is None else specularPart)
1486+
_check_return(ret)
1487+
1488+
1489+
def simGetLightParameters(shapeHandle):
1490+
diffusePart = ffi.new('float[3]')
1491+
specularPart = ffi.new('float[3]')
1492+
ret = lib.simGetLightParameters(shapeHandle, ffi.NULL, diffusePart, specularPart)
1493+
_check_return(ret)
1494+
return ret, list(diffusePart), list(specularPart)

pyrep/objects/light.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import warnings
2+
import numpy as np
3+
from typing import Union
4+
from pyrep.backend import sim
5+
from pyrep.const import ObjectType
6+
from pyrep.objects.object import Object, object_type_to_class
7+
8+
9+
class Light(Object):
10+
"""A light.
11+
"""
12+
13+
def __init__(self, name_or_handle: Union[str, int]):
14+
super().__init__(name_or_handle)
15+
16+
def _get_requested_type(self) -> ObjectType:
17+
return ObjectType.LIGHT
18+
19+
# On and Off
20+
21+
def turn_on(self):
22+
""" Turn the light on.
23+
"""
24+
sim.simSetLightParameters(self._handle, True)
25+
26+
def turn_off(self):
27+
""" Turn the light off.
28+
"""
29+
sim.simSetLightParameters(self._handle, False)
30+
31+
def is_on(self):
32+
""" Determines whether the light is on.
33+
return: Boolean
34+
"""
35+
return sim.simGetLightParameters(self._handle)[0]
36+
37+
def is_off(self):
38+
""" Determines whether the light is off.
39+
return: Boolean
40+
"""
41+
return not sim.simGetLightParameters(self._handle)[0]
42+
43+
# Get and Set Color
44+
45+
def get_diffuse(self):
46+
""" Get the diffuse colors of the light.
47+
return: 3-vector np.array of diffuse colors
48+
"""
49+
return np.asarray(sim.simGetLightParameters(self._handle)[1])
50+
51+
def set_diffuse(self, diffuse):
52+
""" Set the diffuse colors of the light.
53+
"""
54+
sim.simSetLightParameters(self._handle, self.is_on(), list(diffuse))
55+
56+
def get_specular(self):
57+
""" Get the specular colors of the light.
58+
return: 3-vector np.array of specular colors
59+
"""
60+
return np.asarray(sim.simGetLightParameters(self._handle)[2])
61+
62+
def set_specular(self, specular):
63+
""" Set the specular colors of the light.
64+
"""
65+
sim.simSetLightParameters(self._handle, self.is_on(), specularPart=list(specular))
66+
67+
# Intensity Properties
68+
69+
def get_intensity_properties(self):
70+
""" Gets light intensity properties.
71+
72+
:return: The light intensity properties cast_shadows, spot_exponent, spot_cutoff, const_atten_factor,
73+
linear_atten_factor, quad_atten_factor
74+
"""
75+
cast_shadows = sim.simGetObjectInt32Parameter(self._handle, sim.sim_lightintparam_pov_casts_shadows)
76+
spot_exponent = sim.simGetObjectFloatParameter(self._handle, sim.sim_lightfloatparam_spot_exponent)
77+
spot_cutoff = sim.simGetObjectFloatParameter(self._handle, sim.sim_lightfloatparam_spot_cutoff)
78+
const_atten_factor = sim.simGetObjectFloatParameter(self._handle, sim.sim_lightfloatparam_const_attenuation)
79+
linear_atten_factor = sim.simGetObjectFloatParameter(self._handle, sim.sim_lightfloatparam_lin_attenuation)
80+
quad_atten_factor = sim.simGetObjectFloatParameter(self._handle, sim.sim_lightfloatparam_quad_attenuation)
81+
return bool(cast_shadows), spot_exponent, spot_cutoff, const_atten_factor, linear_atten_factor,\
82+
quad_atten_factor
83+
84+
def set_intensity_properties(self, cast_shadows=None, spot_exponent=None, spot_cutoff=None, const_atten_factor=None,
85+
linear_atten_factor=None, quad_atten_factor=None):
86+
""" Set light intensity properties.
87+
88+
:param cast_shadows: POV-Ray light casts shadows
89+
:param spot_exponent: light spot exponent
90+
:param spot_cutoff: light spot cutoff
91+
:param const_atten_factor: light constant attenuation factor, currently not supported
92+
:param linear_atten_factor: light linear attenuation factor, currently not supported
93+
:param quad_atten_factor: light quadratic attenuation factor, currently not supported
94+
"""
95+
if cast_shadows is not None:
96+
sim.simSetObjectInt32Parameter(
97+
self._handle, sim.sim_lightintparam_pov_casts_shadows, int(cast_shadows))
98+
if spot_exponent is not None:
99+
if spot_exponent % 1 != 0:
100+
warnings.warn('spot exponent must be an integer, rounding input of {} to {}'.format(
101+
spot_exponent, round(spot_exponent)))
102+
sim.simSetObjectFloatParameter(
103+
self._handle, sim.sim_lightfloatparam_spot_exponent, float(round(spot_exponent)))
104+
if spot_cutoff is not None:
105+
spot_cutoff = float(spot_cutoff)
106+
if spot_cutoff > np.pi/2:
107+
warnings.warn('Tried to set spot_cutoff to {}, but the maximum allowed value is pi/2,'
108+
'therefore setting to pi/2'.format(spot_cutoff))
109+
sim.simSetObjectFloatParameter(
110+
self._handle, sim.sim_lightfloatparam_spot_cutoff, float(spot_cutoff))
111+
if const_atten_factor is not None:
112+
raise Exception('CoppeliaSim currently does not support setting attenuation factors')
113+
# sim.simSetObjectFloatParameter(
114+
# self._handle, sim.sim_lightfloatparam_const_attenuation, float(const_atten_factor))
115+
if linear_atten_factor is not None:
116+
raise Exception('CoppeliaSim currently does not support setting attenuation factors')
117+
# sim.simSetObjectFloatParameter(
118+
# self._handle, sim.sim_lightfloatparam_lin_attenuation, float(linear_atten_factor))
119+
if quad_atten_factor is not None:
120+
raise Exception('CoppeliaSim currently does not support setting attenuation factors')
121+
# sim.simSetObjectFloatParameter(
122+
# self._handle, sim.sim_lightfloatparam_quad_attenuation, float(quad_atten_factor))
123+
124+
125+
object_type_to_class[ObjectType.LIGHT] = Light

pyrep/objects/object.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,6 @@ def _get_objects_in_tree(root_object=None, object_type=ObjectType.ALL,
661661
try:
662662
objects.append(Object.get_object(handle))
663663
except KeyError:
664-
# e.g., CAMERA and LIGHT are not officially supported
665664
name = Object.get_object_name(handle)
666665
type = Object.get_object_type(name)
667666
warnings.warn(

tests/assets/test_scene.ttt

3.03 KB
Binary file not shown.

tests/test_lights.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import unittest
2+
import numpy as np
3+
from tests.core import TestCore
4+
from pyrep.objects.light import Light
5+
6+
7+
class TestLights(TestCore):
8+
9+
def setUp(self):
10+
super().setUp()
11+
[self.pyrep.step() for _ in range(10)]
12+
self.spot_light = Light('spot_light')
13+
self.omni_light = Light('omni_light')
14+
self.directed_light = Light('directed_light')
15+
self.lights = [self.spot_light, self.omni_light, self.directed_light]
16+
self.light_types = [1, 2, 3]
17+
18+
# turn on and off
19+
20+
def test_turn_on_and_off(self):
21+
for light in self.lights:
22+
light.turn_on()
23+
self.assertTrue(light.is_on())
24+
light.turn_off()
25+
self.assertTrue(light.is_off())
26+
27+
# light color
28+
29+
def test_get_set_light_diffuse(self):
30+
for light in self.lights:
31+
orig_diffuse = light.get_diffuse()
32+
new_diffuse = np.array([0.2, 0.5, 0.9])
33+
light.set_diffuse(new_diffuse)
34+
self.assertTrue(np.allclose(light.get_diffuse(), new_diffuse))
35+
light.set_diffuse(orig_diffuse)
36+
self.assertTrue(np.allclose(light.get_diffuse(), orig_diffuse))
37+
38+
def test_get_set_light_specular(self):
39+
for light in self.lights:
40+
orig_specular = light.get_specular()
41+
new_specular = np.array([0.2, 0.5, 0.9])
42+
light.set_specular(new_specular)
43+
self.assertTrue(np.allclose(light.get_specular(), new_specular))
44+
light.set_specular(orig_specular)
45+
self.assertTrue(np.allclose(light.get_specular(), orig_specular))
46+
47+
# light intensity properties
48+
49+
def test_get_set_cast_shadows(self):
50+
for light in self.lights:
51+
orig = light.get_intensity_properties()[0]
52+
new = not orig
53+
light.set_intensity_properties(cast_shadows=new)
54+
self.assertTrue(light.get_intensity_properties()[0] is new)
55+
light.set_intensity_properties(cast_shadows=orig)
56+
self.assertTrue(np.allclose(light.get_intensity_properties()[0], orig))
57+
58+
def test_get_set_spot_exponent(self):
59+
for light in self.lights:
60+
orig = light.get_intensity_properties()[1]
61+
new = orig + 2
62+
light.set_intensity_properties(spot_exponent=new)
63+
self.assertEqual(light.get_intensity_properties()[1], new)
64+
light.set_intensity_properties(spot_exponent=orig)
65+
self.assertEqual(light.get_intensity_properties()[1], orig)
66+
67+
def test_get_set_spot_cutoff(self):
68+
for light in self.lights:
69+
orig = light.get_intensity_properties()[2]
70+
new = orig - 0.5
71+
light.set_intensity_properties(spot_cutoff=new)
72+
self.assertEqual(light.get_intensity_properties()[2], new)
73+
light.set_intensity_properties(spot_cutoff=orig)
74+
self.assertEqual(light.get_intensity_properties()[2], orig)
75+
76+
# ToDo: re-add these tests once attenuation factor setting is supported in CoppeliaSim.
77+
# setObjectFloatParams() does not change the properties of the light even with in-scene lua code.
78+
'''
79+
def test_get_set_const_atten_factor(self):
80+
for light in self.lights:
81+
orig = light.get_intensity_properties()[3]
82+
new = orig + 1.5
83+
light.set_intensity_properties(const_atten_factor=new)
84+
assert light.get_intensity_properties()[3] == new
85+
light.set_intensity_properties(const_atten_factor=orig)
86+
assert light.get_intensity_properties()[3] == orig
87+
88+
def test_get_set_linear_atten_factor(self):
89+
for light in self.lights:
90+
orig = light.get_intensity_properties()[4]
91+
new = orig + 1.5
92+
light.set_intensity_properties(linear_atten_factor=new)
93+
assert light.get_intensity_properties()[4] == new
94+
light.set_intensity_properties(linear_atten_factor=orig)
95+
assert light.get_intensity_properties()[4] == orig
96+
97+
def test_get_set_quad_atten_factor(self):
98+
for light in self.lights:
99+
orig = light.get_intensity_properties()[5]
100+
new = orig + 1.5
101+
light.set_intensity_properties(quad_atten_factor=new)
102+
assert light.get_intensity_properties()[5] == new
103+
light.set_intensity_properties(quad_atten_factor=orig)
104+
assert light.get_intensity_properties()[5] == orig
105+
'''
106+
107+
108+
if __name__ == '__main__':
109+
unittest.main()

tests/test_pyrep.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,7 @@ def test_create_texture_and_get_texture(self):
9595
plane.get_texture().get_texture_id())
9696

9797
def test_get_objects_in_tree(self):
98-
with warnings.catch_warnings(record=True) as w:
99-
warnings.simplefilter('always')
100-
objects = self.pyrep.get_objects_in_tree()
101-
self.assertNotEqual(len(w), 0)
98+
objects = self.pyrep.get_objects_in_tree()
10299
for obj in objects:
103100
self.assertIsInstance(obj, Object)
104101

tests/test_spherical_vision_sensors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22
from tests.core import TestCore
3+
from pyrep.const import RenderMode
34
from pyrep.sensors.spherical_vision_sensor import SphericalVisionSensor
4-
from pyrep.const import RenderMode, PerspectiveMode
55

66

77
class TestSphericalVisionSensors(TestCore):

0 commit comments

Comments
 (0)