Tracking contact of Ant-v2

Discussion in 'Support requests' started by Cedric, Jul 31, 2019.

  1. Hello,

    I'm trying to get the fraction of the episode where each of the Ant-v2 feet touch the floor. I'm getting the list of contacts at each time step using sim.data.contact, I check the first sim.data.ncon then i go through the ncon contacts and check whether they correspond to one of the ankles by comparing sim.model.geom_id2name(c.geom2) to the list of strings corresponding to the ankles.
    However, I find that in the list of ncon first contacts for a given time step, I sometimes have twice the same contact (e.g. geom1 floor, geom2 third_ankle_geom, twice). Leading to results like third_ankle_geom touched the floor in 140 % of the steps.

    Am I missing something here? I'd expect maximum one contact per ankle at a given time step. Also for a whole episode, it sometimes say that only two ankles touched the floor, which does not seem to be the case when I render that episode. I must do something wrong.

    Below is the code to reproduce this. I fixed a particular seed where this happen but it might be that different versions of numpy and gym make the seeding different. In that case you can just run a few different seeds, it happens pretty often (1/5 maybe).



    Code:
    import gym
    import numpy as np
    
    env = gym.make('Ant-v2')
    sim = env.unwrapped.sim
    seed = 1
    np.random.seed(seed)
    env.seed(seed)
    env.reset()
    
    contact_info = []
    for i in range(1000):
        obs = env.step(np.random.uniform(-0.1, 0.1, 8))
        contact_info.append((sim.data.contact, sim.data.ncon))
    
    def get_bc(contact_info):
        scores = np.zeros([4])
        for contacts, ncon in contact_info:
            print(ncon)
            for c in contacts[:ncon]:
                print(sim.model.geom_id2name(c.geom1))
                print(sim.model.geom_id2name(c.geom2))
                if sim.model.geom_id2name(c.geom2) == 'left_ankle_geom':
                    scores[0] += 1
                elif  sim.model.geom_id2name(c.geom2) == 'right_ankle_geom':
                    scores[1] += 1
                elif sim.model.geom_id2name(c.geom2) == 'third_ankle_geom':
                    scores[2] += 1
                elif sim.model.geom_id2name(c.geom2) == 'fourth_ankle_geom':
                    scores[3] += 1
        return scores / len(contact_info)
    
    print(get_bc(contact_info))

    Thanks
    Cedric
     
  2. Emo Todorov

    Emo Todorov Administrator Staff Member

    Depending on the geom shapes, you can have multiple contacts per geom pair. Capsule-plane can generate 2 contacts, while cylinder-plane can generate 3 contacts. Capsule-capsule can also generate 2 contacts.

    The good news is that multiple contacts for the same geom pair will always appear next to each other, so your code can simply check if the geom pair for the previous contact is different from the geom pair for the current contact. That way you can detect a group of contacts belonging to the same geom pair.
     
  3. Thank you for your quick reply !