Grouping issue - Python/Mel

I’m following along part of a tutorial, almost complete, however I’m having an odd issue. Maya is informing me that “More than one object matches name: grp_R_toe”
Here is area of code that’s giving me the grief, it seems to be having trouble with the loop:

#Create the Solvers
	cmds.ikSolver( st='ikRPsolver', n='RHip_ikRPsolver')
	cmds.ikSolver( st='ikSCsolver', n='RBall_ikSCsolver')
	cmds.ikSolver( st='ikSCsolver', n='RToe_ikSCsolver')
        #Set the IK Handles
        cmds.ikHandle(n="hipH_R", sj="hip_R", ee="ankle_R", sol ="RHip_ikRPsolver")
        cmds.ikHandle(n="ballH_R", sj="ankle_R", ee="ball_R", sol ="RBall_ikSCsolver")
        cmds.ikHandle(n="toeH_R", sj="ball_R", ee="toe_R", sol ="RToe_ikSCsolver")
        
        footGroups = ("grp_R_footPivot","grp_R_heel","grp_R_toe","grp_R_ball","grp_R_flap")
	for item in footGroups:
		cmds.group(n=item,empty=True,world=True)
		print item
	#print footGroups
        #Get positions
        hipPos = cmds.xform("hip_R", q=True, ws=True, t=True)
        anklePos = cmds.xform("ankle_R", q=True, ws=True, t=True)
        ballPos = cmds.xform("ball_R", q=True, ws=True, t=True)
        toePos = cmds.xform("toe_R", q=True, ws=True, t=True)
        cmds.xform("grp_R_toe", ws=True, t=toePos)
        cmds.xform("grp_R_ball", ws=True, t=ballPos)
        cmds.xform("grp_R_flap", ws=True, t=ballPos)
        #IK handle and group hierarchy positioning
        cmds.parent('grp_R_heel','grp_R_footPivot')
        cmds.parent('grp_R_toe','grp_R_heel')
        cmds.parent('grp_R_ball','grp_R_toe')
        cmds.parent('grp_R_flap','grp_R_toe')
        cmds.parent('hipH_R','grp_R_ball')
        cmds.parent('ballH_R','grp_R_ball')
        cmds.parent('toeH_R','grp_R_flap')
        cmds.parent('grp_R_footPivot', 'ctrl_R_leg')

The section:

footGroups = ("grp_R_footPivot","grp_R_heel","grp_R_toe","grp_R_ball","grp_R_flap")
	for item in footGroups:
		cmds.group(n=item,empty=True,world=True)

I think is the area giving me grief. Any idea what may be going on? Why two “grp_R_toe” objects seem to be created, although in the outliner, it isn’t indicated that way? Or have I just been staring at this too long and I’m overlooking an obvious typo lol. Thanks in advance :slight_smile:

When you say that the loop is giving you grief, do you mean it’s failing in the creation of the groups? or is it failing down below when you try to access them?

I’m guessing there’s something sneaky hanging around in the scene – like a shape node that somehow got named grp_R_toe so it’s not visible in the outliner. Could even be a material – all maya names must be absolutely unique, not just unique in category .I had a long battle this summer with artists importing test objects and creating namespaces that screwed up things, since the namespace hung around even if it was empty and therefore made it impossible to create something with that name. You should be able to find the evil object with ls(r=True, ‘grp_R_toe’) even if it’s well hidden.

From the design standpoint, it’s often easier to debug these things if you capture the return from commands rather than relying on absolute names being stable. There’s lots of ways the name-on-creation thing can go wrong: namespaces, existing siblings, bad characters, etc


footgroups = {"grp_R_footPivot":None, "grp_R_heel":None, "grp_R_toe":None, "grp_R_ball":None,"grp_R_flap:None}
for item in footGroups:
     footgroups[item] = cmds.group(n=item, empty=True, world=True)
     assert not "|" in footgroups[item]  # fail if we can't get the names we want

which will ensure that the names came back as unique root level names. Nowadays I reflexively get all my name variables in the long form (with ls -l or listRelatives -f or whatever), it’s extra typing and a smidge more memory but many fewer bugs in the end.

Seconding Theodox’s comment about avoiding using hardcoded names anywhere but naming/renaming objects. Capture the return of any commands that create objects and use their output to query them instead. You’ll save yourself a lot of headaches both with debugging and modifying scripts. Once programs get larger and you find yourself chasing down object names across multiple scripts you’ll want to gouge your eyes out.

Right now it’s creating the groups, however when I attempt to access them it’s claiming there are duplicates. Thanks for the reply, trying those solutions out, and seeing if I can nail down what exactly it claims is duplicated

Update - Ran ls on it:
import maya.cmds as cmds
thels = cmds.ls(‘grp_R_toe’)
print thels
[u’ctrl_R_leg|grp_R_footPivot|grp_R_heel|grp_R_toe’, u’|grp_R_toe’]

So it has ‘grp_R_toe’ as that currently. I’ll keep digging.

[QUOTE=TreyAnesi;18332]Update - Ran ls on it:
import maya.cmds as cmds
thels = cmds.ls(‘grp_R_toe’)
print thels
[u’ctrl_R_leg|grp_R_footPivot|grp_R_heel|grp_R_toe’, u’|grp_R_toe’]

So it has ‘grp_R_toe’ as that currently. I’ll keep digging.[/QUOTE]

There’s your problem right there, no? The return has two different objects, one at the root level of the scene and the other parented to grp_R_heel. If you try to refer to grp_R_toe from a command in this sceene you’ll get an error. You could workaround by referring to ctrl_R_leg|grp_R_footPivot|grp_R_heel|grp_R_toe and |grp_R_toe by their full paths, but you probably want to figure out why you get two different grp_R_toes in your scene.

Yeah, thanks for the help! I could reference it using the full paths like you said, but that’s just messy. So digging for the “why” now I guess :slight_smile:

Two bucks says it’s a cut-and-paste line creating something with a hardcoded name you didn’t catch :slight_smile:

Yeah not sure. Took what I wanted from a tutorial and I’m re-purposing it to suit my needs. For now I plugged in ‘|grp_R_toe’ and its happy with that. Just odd that it adds the “|” onto the name. But thanks for the help and the heads up on naming conventions. I’ve certainly been simply using the format “grp_R_toe” instead of “grp_R_toe”:None. Dodging future headaches, always welcomed lol

[QUOTE=TreyAnesi;18337]Yeah not sure. Took what I wanted from a tutorial and I’m re-purposing it to suit my needs. For now I plugged in ‘|grp_R_toe’ and its happy with that. Just odd that it adds the “|” onto the name. But thanks for the help and the heads up on naming conventions. I’ve certainly been simply using the format “grp_R_toe” instead of “grp_R_toe”:None. Dodging future headaches, always welcomed lol[/QUOTE]

That’s just bog-standard maya. Every object is id’d by its name, and the name must be completely unique (unlike max, where names are only cosmetic). The uniqueness requirement is why things do stuff like becoming ‘pCube1’, ‘pCube2’ etc – it’s maya automatically generating ‘safe’ names, and also why we’ve been recommending using variables to get the results of functions, because you never know for sure that maya will call the object by the name you asked it for.

When there are multiple nodes with the same name at different hierarchy levels, maya gives you the shortest unique path name. So if you you have a scene like this:

pCube1

pCube2
… PCube1

and run ‘ls’ you’ll get [“pCube2|pCube1”, “|pCube1”] back. The | char separates path levels, like a slash in a directory name; starting with | means the path is rooted at scene level.

If you run ‘ls -l’ on short names you’ll get back the full names – and as I said earlier, it’s a good habit to always use that to avoid this kind of crap. Other commands like listRelatives have options for returning long paths. If you have to keep a list of objects for a long time while lots of stuff is going on, try making sets or using attribute connections – path names are just strings and they don’t update if the objects are renamed.

This is something in maya that goes back to the original mel API back in 1996, and it’s pretty poopy :frowning:

[QUOTE=Theodox;18328]When you say that the loop is giving you grief, do you mean it’s failing in the creation of the groups? or is it failing down below when you try to access them?

I’m guessing there’s something sneaky hanging around in the scene – like a shape node that somehow got named grp_R_toe so it’s not visible in the outliner. Could even be a material – all maya names must be absolutely unique, not just unique in category .I had a long battle this summer with artists importing test objects and creating namespaces that screwed up things, since the namespace hung around even if it was empty and therefore made it impossible to create something with that name. You should be able to find the evil object with ls(r=True, ‘grp_R_toe’) even if it’s well hidden.

From the design standpoint, it’s often easier to debug these things if you capture the return from commands rather than relying on absolute names being stable. There’s lots of ways the name-on-creation thing can go wrong: namespaces, existing siblings, bad characters, etc


footgroups = {"grp_R_footPivot":None, "grp_R_heel":None, "grp_R_toe":None, "grp_R_ball":None,"grp_R_flap:None}
for item in footGroups:
     footgroups[item] = cmds.group(n=item, empty=True, world=True)
     assert not "|" in footgroups[item]  # fail if we can't get the names we want

which will ensure that the names came back as unique root level names. Nowadays I reflexively get all my name variables in the long form (with ls -l or listRelatives -f or whatever), it’s extra typing and a smidge more memory but many fewer bugs in the end.[/QUOTE]

I was taking a look at your code, since using assert is something new to me and I noticed that I could not get it to error correctly. I realized it was due to what the group command returns; it differs from what sphere() or joint() or many of the other maya creation commands will return, in that it won’t return a path/partial path if there is a naming conflict. To get around this I inserted a ls() on the return of the group command to get the proper behavior from assert. EDIT: you mentioned this off hand actually inf your last post, but I’ll leave this here anyways since it shows an example of application =)


import maya.cmds as cmds

# create a bunch of groups for testing, parent them under the 'root' group
root = cmds.group(empty=True, world=True)
child1 = cmds.group(name='child1', empty=True, parent=root)
child2 = cmds.group(name='child2', empty=True, parent=child1)
child3 = cmds.group(name='grp_R_flap', empty=True, parent=child2)

footGroups = {"grp_R_footPivot":None, "grp_R_heel":None, "grp_R_toe":None, "grp_R_ball":None,"grp_R_flap":None}

for item in footGroups:
    try:
        footGroups[item] = cmds.ls( cmds.group( name=item, empty=True, world=True ) )[0]
        assert not "|" in footGroups [item]  # fail if we can't get the names we want
    except AssertionError:
        cmds.warning('Warning: There is a naming conflict with {conflictingName}'.format(conflictingName=footGroups[item]))
        # add a '|' to item so that the script can continue to run and we store a usable path to the group
        # since the groups are defaulting to world shis shouldn't be an issue
        footGroups[item] = '|{groupName}'.format(groupName=item)

cmds.select(clear=True)
# test to see if selecting the value returned from the loop will result in selecting
# the correct object in maya
cmds.select(footGroups['grp_R_flap'], replace=True)

Now I’m thinking about different contexts in which I might use an assert in my scripts…

Good catch on the assert not firing, I typically use createNode(‘transform’) in preference to group(empty=True) so it didn’t occur to me to look at the returns.

The standard use for asserts is to abort out of a context where you’ve got something seriously wrong. Typically I would not use them as a substitute for a regular if-test, since if you’re gonna handle the error immediately in context it’s not adding any value. I threw that assert in the test code as a form of breakpoint, since it would stop execution at that point and you were still trying to figure out when the error was happening.

The real role of asserts is the same as for any other kind of exception: to enable a low-level function to raise a red flag when it doesn’t know what to do next. That way you don’t waste energy trying to anticipate and react to problems in a zillion places all over your code. When an assert (or other exception) happens, you’re basically saying “WTF? Help!” and hopefully the code that called your low level function will have a better idea what to do. If it doesn’t it will die also, passing the assert up to the function that called originally called it, and so on… eventually somebody will know what to do, or the program crashes – which is what you want, because it means you hit a condition you didn’t know how to deal with.

The sweet thing about exceptions is that they mean you can write the code that deals with emergencies only once, instead of duplicating all over the place.

For example, say have a func that gets color per vert counts from an object… but somebody gives you a nonexistent object as an argument. Maybe they passed in a bad value (like a number instead of an object name) or maybe it was a mis-typed name, or maybe a real object that had been deleted – there’s no way for a humbler vert counting function to know what’s really going on, so it should just say ‘I don’t know how to deal with this’ and let the calling code decided instead: that is to say, it just asserts (or raises something like a ValueError exception) instead of trying to figure it out.

You want to assert because the appropriate response is context-dependent – if the user typed the name manually, you can show them a dialog. If it is in a long list of items to process, maybe you stick it into a list or warnings and move on to the next item – there’s a million possible scenarios, but using exceptions (and asserts) means you only have to deal with the ones you really understand and can just say “help!” when you don’t know what to do.

As it happens, there’s a lot of info on this in the slides I did for the TA bootcamp, which are hosted right here on TAO:

The debugging and exception handling parts are at about the 33% and 66% marks respectively in the file. Unfortunately there’s no audio with the file – you can buy the audio for the whole bootcamp session from the GDC vault for, I think, $5

[QUOTE=TreyAnesi;18335]Yeah, thanks for the help! I could reference it using the full paths like you said, but that’s just messy. So digging for the “why” now I guess :)[/QUOTE]

It is never messy to access objects by their full names. You should always operate on full names. Some commands do not have a flag to return long or full name, so it is necessary to run “ls” with the “long” flag on the result.

[QUOTE=TreyAnesi;18337]Yeah not sure. Took what I wanted from a tutorial and I’m re-purposing it to suit my needs. For now I plugged in ‘|grp_R_toe’ and its happy with that. Just odd that it adds the “|” onto the name. But thanks for the help and the heads up on naming conventions. I’ve certainly been simply using the format “grp_R_toe” instead of “grp_R_toe”:None. Dodging future headaches, always welcomed lol[/QUOTE]

A “|” is used to separate a child from its parent. When an object has no parent, it is parented to the world and this is indicated with a “|”. It’s how you tell Maya I want the node parented to the world, not another node with the same name that has a parent.

Or better yet create/cast all objects into PyNode objects, which have embedded API DagPaths in them. Then you’re not relying on silly strings that can change right underneath you when re-parenting or duplicating.