Source code for tbp.monty.frameworks.models.motor_system_state

# Copyright 2025 Thousand Brains Project
#
# Copyright may exist in Contributors' modifications
# and/or contributions to the work.
#
# Use of this source code is governed by the MIT
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT.
from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Dict

import numpy as np

from tbp.monty.frameworks.agents import AgentID
from tbp.monty.frameworks.sensors import SensorID


[docs]@dataclass class SensorState: """The proprioceptive state of a sensor.""" position: Any # TODO: Stop using magnum.Vector3 and decide on Monty standard """The sensor's position.""" rotation: Any # TODO: Stop using quaternion.quaternion and decide on Monty standard """The sensor's rotation."""
[docs]@dataclass class AgentState: """The proprioceptive state of an agent.""" sensors: dict[SensorID, SensorState] """The proprioceptive state of the agent's sensors. When part of an AgentState, the SensorState's position and rotation are relative to the agent's position and rotation. """ position: Any # TODO: Stop using magnum.Vector3 and decide on Monty standard """The agent's position.""" rotation: Any # TODO: Stop using quaternion.quaternion and decide on Monty standard """The agent's rotation.""" motor_only_step: bool = False """Control flow parameter. Processing will bypass the learning module if True. TODO: Remove once we refactor Monty main processing loop to no longer need control flow parameters in motor system state. """
[docs]class ProprioceptiveState(Dict[AgentID, AgentState]): """The proprioceptive state of the motor system. When part of a ProprioceptiveState, the AgentState's position and rotation are relative to some global reference frame. """
[docs]class MotorSystemState(Dict[AgentID, AgentState]): """The state of the motor system. TODO: Currently, ProprioceptiveState can be cast to MotorSystemState since MotorSystemState is a generic dictionary. In the future, make ProprioceptiveState a param on MotorSystemState to more clearly distinguish between the two. These are separate from each other because ProprioceptiveState is the information returned from the environment, while MotorSystemState is that, as well as any state that the motor system needs for operation. """
[docs] def convert_motor_state(self) -> dict[AgentID, Any]: """Convert the motor state into something that can be pickled/saved to JSON. i.e. substitute vector and quaternion objects; note e.g. copy.deepcopy does not work. Returns: Copy of the motor state. """ state_copy: dict[AgentID, Any] = {} for agent_id in self.keys(): agent_state = self[agent_id] sensors = {} for sensor_id in agent_state.sensors.keys(): sensor_state = agent_state.sensors[sensor_id] sensors[sensor_id] = { "position": np.array(list(sensor_state.position)), "rotation": [sensor_state.rotation.real] + list(sensor_state.rotation.imag), } state_copy[agent_id] = { "position": np.array(list(agent_state.position)), "rotation": [agent_state.rotation.real] + list(agent_state.rotation.imag), "sensors": sensors, } return state_copy