private IEnumerator TakeGradualAIActionRoutine(float[] vectorAction) { // Interprets the actions as absolute positions // Moves the Lamp's servo positions from their initial positions to their final positions over a duration of 2 seconds int count = Lamp.NumberOfServos; int[] endServoPositions = new int[count]; for (int i = 0; i < count; ++i) { endServoPositions[i] = lamp.GetServo(i).OffsetFromNormalized(Mathf.Clamp(vectorAction[i], -1f, 1f)); } float duration = 2f; float time = 0f; int offset; // Interpolate servo positions from their initial positions to their final (end) positions while (time < duration) { time = Mathf.Min(time + Time.deltaTime, duration); for (int i = 0; i < count; ++i) { offset = (int)Mathf.SmoothStep(initialServoPositions[i], endServoPositions[i], time / duration); lamp.GetServo(i).SetOffset(offset); } yield return(null); } // Servos are now at their final positions, evaluate the action ActionResultFlags resultFlags; float reward = EvaluateAction(vectorAction, out resultFlags); bool success = (resultFlags & ActionResultFlags.Success) != 0; print(success ? "Success" : "Fail"); print("Reward: " + reward); print("-----------\n"); AddReward(reward); if (success) { ++SuccessFulActions; } ++ActionsTaken; ResetAgentIfNotDone(); // agent is automatically reset if its done... so we only reset if not done to avoid double reset ActionWasTaken?.Invoke(); if (requestOnStart) { // requestOnStart should probably be renamed, but basically we just assume movement automation RequestDecision(); } }
public override void AgentAction(float[] vectorAction, string textAction) { // The vectorAction parameter is our "output vector" // Here the Agent decides how to take an action based on its actionType // Instant: Snap the Lamp's servos into the final positions (primarily used during reinforcement learning training sessions) // Gradual: Starts a coroutine that move the Lamp's servos into the final positions over a duration (primarily for viewing trained models and during imitation learning sessions) // Player: Moves the Lamp's servos based on key presses (used to test lamp movement in the editor) ActionResultFlags resultFlags; switch (actionType) { case EActionType.Instant: TakeInstantAIAction(vectorAction); AddReward(EvaluateAction(vectorAction, out resultFlags)); if ((resultFlags & ActionResultFlags.Terminal) != 0) { Done(); } else { ResetAgentIfNotDone(); } ActionWasTaken?.Invoke(); break; case EActionType.Gradual: // Print actions print("Action: " + vectorAction.AsString()); using (System.IO.StreamWriter file = new System.IO.StreamWriter(logFilePath, true)) { file.WriteLine("Action: " + vectorAction.AsString()); } TakeGradualAIAction(vectorAction); break; case EActionType.Player: TakePlayerAction(vectorAction); EvaluateAction(vectorAction, out resultFlags); if ((resultFlags & ActionResultFlags.Success) != 0) { ResetAgentIfNotDone(); } ActionWasTaken?.Invoke(); break; } }