Skip to content

Allow visual and vector observations at the same time #3981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
Closed

Conversation

shakenes
Copy link
Contributor

@shakenes shakenes commented May 16, 2020

Proposed change(s)

Allow vector observations also when visual observations are used. In this case, the array of vector observations are appended to the list of visual observations.
Compatibility should be maintained. If no visual observations are used, this PR changes nothing.

Useful links (Github issues, JIRA tickets, ML-Agents forum threads etc.)

The initial discussion including arguments took place here: #3960

Types of change(s)

  • Bug fix
  • New feature
  • Code refactor
  • Breaking change
  • Documentation update
  • Other (please describe)

Checklist

  • Added tests that prove my fix is effective or that my feature works
  • Updated the changelog (if applicable)
  • Updated the documentation (if applicable)
  • Updated the migration guide (if applicable)

Other comments

@shakenes shakenes changed the title Allow both obs Allow visual and vector observations at the same time May 16, 2020
@shakenes
Copy link
Contributor Author

Sorry for the mess. I forgot about the tests and just learned about pre-commit.

I think adjusting the test in that way is fine, because as discussed in the linked issue, vector observations should not be omitted when visual observations are also used. I added a test where both types of observations are used. In that case the observations are stored in a list with the last element containing the vectors observations.

@awjuliani awjuliani requested a review from vincentpierre May 18, 2020 17:27
Copy link
Contributor

@vincentpierre vincentpierre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, a few minor comments.
Let me know if you want to address some of the comments or if you would rather merge this first.

assert actions.shape[0] == 2
obs, rew, done, info = env.step(actions)
assert isinstance(obs[0], np.ndarray)
assert isinstance(obs[1], np.ndarray)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you do an assert on the shape of the vector_action ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

@@ -40,7 +40,7 @@ def __init__(
"""
Environment initialization
:param unity_env: The Unity BaseEnv to be wrapped in the gym. Will be closed when the UnityToGymWrapper closes.
:param use_visual: Whether to use visual observation or vector observation.
:param use_visual: Whether to use visual observations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is breaking the assumption that if use_visual is enabled, the observation will be a np.array and not a list of np.array.
I think this change is more suited for allow_multiple_visual_obs.
Maybe renaming allow_multiple_visual_obs to allow_multiple_obs and always return a list of (all visual and vector) observations would be better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my point of view your suggestion would be the better and cleaner solution. I tried to keep it as compatible as possible, but the changes one has to make to get his or her code working again would be rather simple. I'll add this to the PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realizing: What exactly should use_visual mean then? Does it mean there are one or more visual observations? That's would the name implies. However, that does not mean that the observation will be a numpy array.

I think it would make more sense to have three parameters here:

use_vector_only: Use only vector observations. Environments returns an np.array
use_single_visual: Use a single visual observation. Environments returns an np.array
allow_multiple_obs: Allows vector and multiple visual observations. Environment returns a list of observations with the last element containing the array of vector observations. 

Let me know what you think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks pretty nice. I wonder if an enum would be more appropriate in that case, a user could do use_vector_only=True, use_visual_only=True by mistake.

I think the simplest would be a single boolean : use_multiple_obs (default false)

  • If true, returns a list of np_array as observations
  • If false, will return a single np_array AND will return the first visual observation if any (over vector observation)

What do you think ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's probably even better. That way you know whether you get a list or an array. I can take care of that tomorrow and commit it here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be awesome, thank you for your contributions !

def test_gym_wrapper_visual_and_vector(use_uint8):
mock_env = mock.MagicMock()
mock_spec = create_mock_group_spec(
number_visual_observations=1, vector_observation_space_size=3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test with multiple visual observations to test this line https://github.com/Unity-Technologies/ml-agents/pull/3981/files#diff-ae209b1396be959a453713c25c947969R196

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok! Makes sense

@shakenes
Copy link
Contributor Author

Done. Let me know what you think.
There are some examples in the gym-unity Readme, that should be tested again. But I don't have the time to setup everything. Maybe someone can check on it who has everything installed already?

@shakenes shakenes requested a review from vincentpierre May 20, 2020 07:25
Copy link
Contributor

@vincentpierre vincentpierre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do some more testing on my end but I like where the PR is right now.

I notice that we never implemented self.observation_shape for the case with multiple observations. I think we will need to implement a Tuple but I think this is out of scope of this PR.

I will try to have it merged into master or onto a develop branch if I want to make edits.

logger.warning(
"The environment contains visual and vector observations. "
"You must define allow_multiple_obs=True to receive them all. "
"Otherwise, please note that only the first visual observations will be provided int the observation. "
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Otherwise, please note that only the first visual observations will be provided int the observation. "
"Otherwise, please note that only the first visual observations will be provided in the observation. "

@@ -120,7 +129,7 @@ def __init__(
high = np.array([1] * self.group_spec.action_shape)
self._action_space = spaces.Box(-high, high, dtype=np.float32)
high = np.array([np.inf] * self._get_vec_obs_size())
if self.use_visual:
if self._get_n_vis_obs() == 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be

Suggested change
if self._get_n_vis_obs() == 1:
if self._get_n_vis_obs() > 0 and not self. _allow_multiple_obs:

Since we return a single visual obs only if allow_multiple_obs=True

@vincentpierre
Copy link
Contributor

I am sure some yamato tests will be failing on master because of lines like this in our CI.
I will make a new branch off master and merge this PR into this new branch and make edits there.

@vincentpierre vincentpierre changed the base branch from master to shakenes-allow_both_obs May 20, 2020 17:50
@vincentpierre
Copy link
Contributor

I will make a new branch off master and merge this PR into this new branch and make edits there.

Correction : After reviewing our guidelines, I duplicated your branch and made an internal pull request for it. You will be marked as co-author on this PR and I will be able to do more tests and changes directly.

@shakenes
Copy link
Contributor Author

Thanks for your help! I'm looking forward to having this feature released :)

@vincentpierre
Copy link
Contributor

Merged #3998 into master

@shakenes shakenes deleted the allow_both_obs branch May 21, 2020 17:48
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants