Chris Elion
5 年前
当前提交
254c7d86
共有 44 个文件被更改,包括 462 次插入 和 1763 次删除
-
1README.md
-
8UnitySDK/Assets/ML-Agents/Editor/Tests/MLAgentsEditModeTest.cs
-
58UnitySDK/Assets/ML-Agents/Scripts/Academy.cs
-
2UnitySDK/Assets/ML-Agents/Scripts/Brain.cs
-
65UnitySDK/Assets/ML-Agents/Scripts/Grpc/RpcCommunicator.cs
-
17UnitySDK/Assets/ML-Agents/Scripts/ICommunicator.cs
-
16UnitySDK/Assets/ML-Agents/Scripts/LearningBrain.cs
-
12docs/Basic-Guide.md
-
7docs/FAQ.md
-
6docs/Getting-Started-with-Balance-Ball.md
-
22docs/Learning-Environment-Create-New.md
-
3docs/Learning-Environment-Design-Academy.md
-
3docs/Learning-Environment-Design-Brains.md
-
2docs/Learning-Environment-Design-Learning-Brains.md
-
4docs/Learning-Environment-Design.md
-
6docs/Learning-Environment-Executable.md
-
27docs/ML-Agents-Overview.md
-
3docs/Migrating.md
-
7docs/Python-API.md
-
2docs/Training-Behavioral-Cloning.md
-
3docs/Training-ML-Agents.md
-
4docs/Training-PPO.md
-
6docs/Training-SAC.md
-
630docs/images/academy.png
-
157docs/images/mlagents-NewTutAcademy.png
-
4markdown-link-check.config.json
-
26ml-agents-envs/mlagents/envs/environment.py
-
1ml-agents-envs/mlagents/envs/rpc_communicator.py
-
28ml-agents/mlagents/trainers/learn.py
-
7ml-agents/mlagents/trainers/sac/models.py
-
1ml-agents/mlagents/trainers/tensorflow_to_barracuda.py
-
9ml-agents/mlagents/trainers/tests/test_learn.py
-
7ml-agents/mlagents/trainers/tests/test_simple_rl.py
-
10ml-agents/mlagents/trainers/tests/test_trainer_controller.py
-
21ml-agents/mlagents/trainers/tests/test_trainer_util.py
-
61ml-agents/mlagents/trainers/trainer_controller.py
-
160ml-agents/mlagents/trainers/trainer_util.py
-
3UnitySDK/Assets/ML-Agents/Editor/BroadcastHubDrawer.cs.meta
-
186UnitySDK/Assets/ML-Agents/Editor/BroadcastHubDrawer.cs
-
3UnitySDK/Assets/ML-Agents/Scripts/BroadcastHub.cs.meta
-
46UnitySDK/Assets/ML-Agents/Scripts/BroadcastHub.cs
-
236docs/images/broadcast.png
-
243docs/images/mlagents-SetBrainToTrain.png
-
102ml-agents-envs/mlagents/envs/socket_communicator.py
|
|||
fileFormatVersion: 2 |
|||
guid: aa1bef9e5833447ab7251fc6f7a3a609 |
|||
timeCreated: 1536852419 |
|
|||
using UnityEngine; |
|||
using UnityEditor; |
|||
using System; |
|||
using UnityEditor.SceneManagement; |
|||
using UnityEngine.SceneManagement; |
|||
|
|||
namespace MLAgents |
|||
{ |
|||
/// <summary>
|
|||
/// PropertyDrawer for BroadcastHub. Used to display the BroadcastHub in the Inspector.
|
|||
/// </summary>
|
|||
[CustomPropertyDrawer(typeof(BroadcastHub))] |
|||
public class BroadcastHubDrawer : PropertyDrawer |
|||
{ |
|||
private BroadcastHub m_Hub; |
|||
// The height of a line in the Unity Inspectors
|
|||
private const float k_LineHeight = 17f; |
|||
// The vertical space left below the BroadcastHub UI.
|
|||
private const float k_ExtraSpaceBelow = 10f; |
|||
|
|||
/// <summary>
|
|||
/// Computes the height of the Drawer depending on the property it is showing
|
|||
/// </summary>
|
|||
/// <param name="property">The property that is being drawn.</param>
|
|||
/// <param name="label">The label of the property being drawn.</param>
|
|||
/// <returns>The vertical space needed to draw the property.</returns>
|
|||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) |
|||
{ |
|||
LazyInitializeHub(property); |
|||
var numLines = m_Hub.Count + 2 + (m_Hub.Count > 0 ? 1 : 0); |
|||
return (numLines) * k_LineHeight + k_ExtraSpaceBelow; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) |
|||
{ |
|||
LazyInitializeHub(property); |
|||
position.height = k_LineHeight; |
|||
EditorGUI.LabelField(position, new GUIContent(label.text, |
|||
"The Broadcast Hub helps you define which Brains you want to expose to " + |
|||
"the external process")); |
|||
position.y += k_LineHeight; |
|||
|
|||
EditorGUI.BeginProperty(position, label, property); |
|||
|
|||
EditorGUI.indentLevel++; |
|||
DrawAddRemoveButtons(position); |
|||
position.y += k_LineHeight; |
|||
|
|||
// This is the labels for each columns
|
|||
var brainWidth = position.width; |
|||
var brainRect = new Rect( |
|||
position.x, position.y, brainWidth, position.height); |
|||
if (m_Hub.Count > 0) |
|||
{ |
|||
EditorGUI.LabelField(brainRect, "Brains"); |
|||
brainRect.y += k_LineHeight; |
|||
} |
|||
DrawBrains(brainRect); |
|||
EditorGUI.indentLevel--; |
|||
EditorGUI.EndProperty(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the Add and Remove buttons.
|
|||
/// </summary>
|
|||
/// <param name="position">The position at which to draw.</param>
|
|||
private void DrawAddRemoveButtons(Rect position) |
|||
{ |
|||
// This is the rectangle for the Add button
|
|||
var addButtonRect = position; |
|||
addButtonRect.x += 20; |
|||
if (m_Hub.Count > 0) |
|||
{ |
|||
addButtonRect.width /= 2; |
|||
addButtonRect.width -= 24; |
|||
var buttonContent = new GUIContent( |
|||
"Add New", "Add a new Brain to the Broadcast Hub"); |
|||
if (GUI.Button(addButtonRect, buttonContent, EditorStyles.miniButton)) |
|||
{ |
|||
MarkSceneAsDirty(); |
|||
AddBrain(); |
|||
} |
|||
// This is the rectangle for the Remove button
|
|||
var removeButtonRect = position; |
|||
removeButtonRect.x = position.width / 2 + 15; |
|||
removeButtonRect.width = addButtonRect.width - 18; |
|||
buttonContent = new GUIContent( |
|||
"Remove Last", "Remove the last Brain from the Broadcast Hub"); |
|||
if (GUI.Button(removeButtonRect, buttonContent, EditorStyles.miniButton)) |
|||
{ |
|||
MarkSceneAsDirty(); |
|||
RemoveLastBrain(); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
addButtonRect.width -= 50; |
|||
var buttonContent = new GUIContent( |
|||
"Add Brain to Broadcast Hub", "Add a new Brain to the Broadcast Hub"); |
|||
if (GUI.Button(addButtonRect, buttonContent, EditorStyles.miniButton)) |
|||
{ |
|||
MarkSceneAsDirty(); |
|||
AddBrain(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the Brain contained in the BroadcastHub.
|
|||
/// </summary>
|
|||
/// <param name="brainRect">The Rect to draw the Brains.</param>
|
|||
private void DrawBrains(Rect brainRect) |
|||
{ |
|||
for (var index = 0; index < m_Hub.Count; index++) |
|||
{ |
|||
var controlledBrains = m_Hub.brainsToControl; |
|||
var brain = controlledBrains[index]; |
|||
// This is the rectangle for the brain
|
|||
EditorGUI.BeginChangeCheck(); |
|||
var newBrain = EditorGUI.ObjectField( |
|||
brainRect, brain, typeof(LearningBrain), true) as LearningBrain; |
|||
brainRect.y += k_LineHeight; |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
MarkSceneAsDirty(); |
|||
m_Hub.brainsToControl.RemoveAt(index); |
|||
var brainToInsert = controlledBrains.Contains(newBrain) ? null : newBrain; |
|||
controlledBrains.Insert(index, brainToInsert); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Lazy initializes the Drawer with the property to be drawn.
|
|||
/// </summary>
|
|||
/// <param name="property">The SerializedProperty of the BroadcastHub
|
|||
/// to make the custom GUI for.</param>
|
|||
private void LazyInitializeHub(SerializedProperty property) |
|||
{ |
|||
if (m_Hub != null) |
|||
{ |
|||
return; |
|||
} |
|||
var target = property.serializedObject.targetObject; |
|||
m_Hub = fieldInfo.GetValue(target) as BroadcastHub; |
|||
if (m_Hub == null) |
|||
{ |
|||
m_Hub = new BroadcastHub(); |
|||
fieldInfo.SetValue(target, m_Hub); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Signals that the property has been modified and requires the scene to be saved for
|
|||
/// the changes to persist. Only works when the Editor is not playing.
|
|||
/// </summary>
|
|||
private static void MarkSceneAsDirty() |
|||
{ |
|||
if (!EditorApplication.isPlaying) |
|||
{ |
|||
EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene()); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the last Brain from the BroadcastHub
|
|||
/// </summary>
|
|||
private void RemoveLastBrain() |
|||
{ |
|||
if (m_Hub.Count > 0) |
|||
{ |
|||
m_Hub.brainsToControl.RemoveAt(m_Hub.brainsToControl.Count - 1); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds a new Brain to the BroadcastHub. The value of this brain will not be initialized.
|
|||
/// </summary>
|
|||
private void AddBrain() |
|||
{ |
|||
m_Hub.brainsToControl.Add(null); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e43fd511c9f147e487d80e0bab3f6c6b |
|||
timeCreated: 1536851538 |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine; |
|||
using UnityEngine.Serialization; |
|||
|
|||
namespace MLAgents |
|||
{ |
|||
/// <summary>
|
|||
/// BroadcastHub holds reference to brains and keeps track wether or not the brain be
|
|||
/// remotely controlled.
|
|||
/// </summary>
|
|||
[System.Serializable] |
|||
public class BroadcastHub |
|||
{ |
|||
[FormerlySerializedAs("_brainsToControl")] |
|||
[SerializeField] |
|||
public List<LearningBrain> brainsToControl = new List<LearningBrain>(); |
|||
|
|||
/// <summary>
|
|||
/// The number of Brains inside the BroadcastingHub.
|
|||
/// </summary>
|
|||
public int Count |
|||
{ |
|||
get { return brainsToControl.Count; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets a brain to controlled.
|
|||
/// </summary>
|
|||
/// <param name="brain"> The Brain that is being set to controlled</param>
|
|||
public void SetControlled(LearningBrain brain) |
|||
{ |
|||
if (!brainsToControl.Contains(brain)) |
|||
{ |
|||
brainsToControl.Add(brain); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes all the Brains of the BroadcastHub
|
|||
/// </summary>
|
|||
public void Clear() |
|||
{ |
|||
brainsToControl.Clear(); |
|||
} |
|||
} |
|||
} |
|
|||
import logging |
|||
import socket |
|||
import struct |
|||
from typing import Optional |
|||
|
|||
from .communicator import Communicator |
|||
from mlagents.envs.communicator_objects.unity_message_pb2 import UnityMessageProto |
|||
from mlagents.envs.communicator_objects.unity_output_pb2 import UnityOutputProto |
|||
from mlagents.envs.communicator_objects.unity_input_pb2 import UnityInputProto |
|||
from .exception import UnityTimeOutException |
|||
|
|||
|
|||
logger = logging.getLogger("mlagents.envs") |
|||
|
|||
|
|||
class SocketCommunicator(Communicator): |
|||
def __init__(self, worker_id=0, base_port=5005): |
|||
""" |
|||
Python side of the socket communication |
|||
|
|||
:int base_port: Baseline port number to connect to Unity environment over. worker_id increments over this. |
|||
:int worker_id: Number to add to communication port (5005) [0]. Used for asynchronous agent scenarios. |
|||
""" |
|||
|
|||
self.port = base_port + worker_id |
|||
self._buffer_size = 12000 |
|||
self.worker_id = worker_id |
|||
self._socket = None |
|||
self._conn = None |
|||
|
|||
def initialize(self, inputs: UnityInputProto) -> UnityOutputProto: |
|||
try: |
|||
# Establish communication socket |
|||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
|||
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
|||
self._socket.bind(("localhost", self.port)) |
|||
except Exception: |
|||
raise UnityTimeOutException( |
|||
"Couldn't start socket communication because worker number {} is still in use. " |
|||
"You may need to manually close a previously opened environment " |
|||
"or use a different worker number.".format(str(self.worker_id)) |
|||
) |
|||
try: |
|||
self._socket.settimeout(30) |
|||
self._socket.listen(1) |
|||
self._conn, _ = self._socket.accept() |
|||
self._conn.settimeout(30) |
|||
except Exception: |
|||
raise UnityTimeOutException( |
|||
"The Unity environment took too long to respond. Make sure that :\n" |
|||
"\t The environment does not need user interaction to launch\n" |
|||
"\t The Academy's Broadcast Hub is configured correctly\n" |
|||
"\t The Agents are linked to the appropriate Brains\n" |
|||
"\t The environment and the Python interface have compatible versions." |
|||
) |
|||
message = UnityMessageProto() |
|||
message.header.status = 200 |
|||
message.unity_input.CopyFrom(inputs) |
|||
self._communicator_send(message.SerializeToString()) |
|||
initialization_output = UnityMessageProto() |
|||
initialization_output.ParseFromString(self._communicator_receive()) |
|||
return initialization_output.unity_output |
|||
|
|||
def _communicator_receive(self): |
|||
try: |
|||
s = self._conn.recv(self._buffer_size) |
|||
message_length = struct.unpack("I", bytearray(s[:4]))[0] |
|||
s = s[4:] |
|||
while len(s) != message_length: |
|||
s += self._conn.recv(self._buffer_size) |
|||
except socket.timeout: |
|||
raise UnityTimeOutException("The environment took too long to respond.") |
|||
return s |
|||
|
|||
def _communicator_send(self, message): |
|||
self._conn.send(struct.pack("I", len(message)) + message) |
|||
|
|||
def exchange(self, inputs: UnityInputProto) -> Optional[UnityOutputProto]: |
|||
message = UnityMessageProto() |
|||
message.header.status = 200 |
|||
message.unity_input.CopyFrom(inputs) |
|||
self._communicator_send(message.SerializeToString()) |
|||
outputs = UnityMessageProto() |
|||
outputs.ParseFromString(self._communicator_receive()) |
|||
if outputs.header.status != 200: |
|||
return None |
|||
return outputs.unity_output |
|||
|
|||
def close(self): |
|||
""" |
|||
Sends a shutdown signal to the unity environment, and closes the socket connection. |
|||
""" |
|||
if self._socket is not None and self._conn is not None: |
|||
message_input = UnityMessageProto() |
|||
message_input.header.status = 400 |
|||
self._communicator_send(message_input.SerializeToString()) |
|||
if self._socket is not None: |
|||
self._socket.close() |
|||
self._socket = None |
|||
if self._socket is not None: |
|||
self._conn.close() |
|||
self._conn = None |
撰写
预览
正在加载...
取消
保存
Reference in new issue