The Replicant can look at a target object or position, and can reset the rotation of its head. The Replicant's head moves continuously over multiple communicate()
calls. The camera attached to the head always matches the rotation of the head.
The look_at(target)
command will tell the Replicant to start looking at a target, which can be an x, y, z dictionary position, an x, y, z numpy array position, or an object ID:
from tdw.controller import Controller
from tdw.tdw_utils import TDWUtils
from tdw.add_ons.replicant import Replicant
from tdw.add_ons.image_capture import ImageCapture
from tdw.replicant.action_status import ActionStatus
from tdw.replicant.image_frequency import ImageFrequency
from tdw.backend.paths import EXAMPLE_CONTROLLER_OUTPUT_PATH
def do_action():
while replicant.action.status == ActionStatus.ongoing:
c.communicate([])
c = Controller()
replicant = Replicant(image_frequency=ImageFrequency.always)
c.add_ons.append(replicant)
object_id = Controller.get_unique_id()
commands = [TDWUtils.create_empty_room(12, 12)]
commands.extend(Controller.get_add_physics_object(model_name="basket_18inx18inx12iin_wicker",
object_id=object_id,
position={"x": -2, "y": 0, "z": 3}))
c.communicate(commands)
path = EXAMPLE_CONTROLLER_OUTPUT_PATH.joinpath("replicant_look_at")
print(f"Images will be saved to: {path}")
capture = ImageCapture(avatar_ids=[replicant.static.avatar_id], path=path)
c.add_ons.append(capture)
c.communicate([])
replicant.look_at(target=object_id)
do_action()
replicant.look_at(target={"x": 2, "y": 0.3, "z": 3})
do_action()
c.communicate({"$type": "terminate"})
Result (these images are captured from the Replicant's camera, as opposed to a third-person camera):
The optional duration
parameter controls the speed in seconds at which the head turns:
from tdw.controller import Controller
from tdw.tdw_utils import TDWUtils
from tdw.add_ons.replicant import Replicant
from tdw.add_ons.image_capture import ImageCapture
from tdw.replicant.action_status import ActionStatus
from tdw.replicant.image_frequency import ImageFrequency
from tdw.backend.paths import EXAMPLE_CONTROLLER_OUTPUT_PATH
def do_action():
while replicant.action.status == ActionStatus.ongoing:
c.communicate([])
c = Controller()
replicant = Replicant(image_frequency=ImageFrequency.always)
c.add_ons.append(replicant)
object_id = Controller.get_unique_id()
commands = [TDWUtils.create_empty_room(12, 12)]
commands.extend(Controller.get_add_physics_object(model_name="basket_18inx18inx12iin_wicker",
object_id=object_id,
position={"x": -2, "y": 0, "z": 3}))
c.communicate(commands)
path = EXAMPLE_CONTROLLER_OUTPUT_PATH.joinpath("replicant_look_at_slow")
print(f"Images will be saved to: {path}")
capture = ImageCapture(avatar_ids=[replicant.static.avatar_id], path=path)
c.add_ons.append(capture)
c.communicate([])
replicant.look_at(target=object_id,
duration=1)
do_action()
replicant.look_at(target={"x": 2, "y": 0.3, "z": 3},
duration=1)
do_action()
c.communicate({"$type": "terminate"})
Result:
duration
is measured in seconds. If the simulation is running faster than real life, this will appear too slow. To handle this, the ReachFor
action dynamically scales the duration
value in proportion to the actual framerate: duration *= 60 / (1 / framerate)
. This is usually desirable, but can be suppressed by setting scale_duration=False
.
replicant.look_at(target)
sets replicant.action
to a LookAt
action.
In addition to the usual Action
initialization commands, LookAt
sends either replicant_look_at_position
or replicant_look_at_object
.
The action ends when the head stops moving (as announced by the build in the output data).
The rotate_head(target)
command will tell the Replicant to start to rotate its head by an angle (in degrees) around an axis. The axis options are: "pitch"
, "yaw"
, "roll"
.
The reset_head
action has the same optional parameters as look_at
:
-
The optional
duration
parameter controls the speed in seconds at which the head turns; it works exactly the same was as it does inrotate_head(target)
. -
The optional
scale_duration
parameter works the same way as it does inrotate_head(target)
.
replicant.rotate_head(angle, axis)
sets replicant.action
to a RotateHead
action.
In addition to the usual Action
initialization commands, RotateHead
sends replicant_rotate_head_by
.
The action ends when the head stops moving (as announced by the build in the output data).
Call reset_head()
to start turning the head back to its neutral position:
from tdw.controller import Controller
from tdw.tdw_utils import TDWUtils
from tdw.add_ons.replicant import Replicant
from tdw.add_ons.image_capture import ImageCapture
from tdw.replicant.action_status import ActionStatus
from tdw.replicant.image_frequency import ImageFrequency
from tdw.backend.paths import EXAMPLE_CONTROLLER_OUTPUT_PATH
def do_action():
while replicant.action.status == ActionStatus.ongoing:
c.communicate([])
c = Controller()
replicant = Replicant(image_frequency=ImageFrequency.always)
c.add_ons.append(replicant)
object_id = Controller.get_unique_id()
commands = [TDWUtils.create_empty_room(12, 12)]
commands.extend(Controller.get_add_physics_object(model_name="basket_18inx18inx12iin_wicker",
object_id=object_id,
position={"x": -2, "y": 0, "z": 3}))
c.communicate(commands)
path = EXAMPLE_CONTROLLER_OUTPUT_PATH.joinpath("replicant_look_at_reset")
print(f"Images will be saved to: {path}")
capture = ImageCapture(avatar_ids=[replicant.static.avatar_id], path=path)
c.add_ons.append(capture)
c.communicate([])
replicant.look_at(target=object_id)
do_action()
replicant.look_at(target={"x": 2, "y": 0.3, "z": 3})
do_action()
replicant.reset_head()
do_action()
c.communicate({"$type": "terminate"})
Result:
The reset_head
action has the same optional parameters as look_at
and rotate_head
:
-
The optional
duration
parameter controls the speed in seconds at which the head turns; it works exactly the same was as it does inreset_head(target)
. -
The optional
scale_duration
parameter works the same way as it does inreset_head(target)
.
replicant.reset_head()
sets replicant.action
to a ResetHead
action.
In addition to the usual Action
initialization commands, ResetHead
sends replicant_reset_head
.
The action ends when the head stops moving (as announced by the build in the output data).
Next: Navigation
Example controllers:
- look_at.py Look at an object and a position, then reset the head.
Command API:
Python API: