Description
Principaux enseignements
- Learn advanced troubleshooting techniques using the iLogic editor.
- Better understand how to find your way around the Inventor application programming interface (API).
- Explore error-handling techniques.
- Learn about creating a better interface between your iLogic automation and the users who employ them.
Intervenant
- Curtis WaguespackCurtis has used Autodesk Inventor and AutoCAD for over two decades to design a wide range of manufactured products. In addition to his design experience, Curtis has authored and co-authored multiple editions of the Mastering Autodesk Inventor book and has taught Inventor to professionals in the classroom. Currently, Curtis works as an Automation Solutions Consultant, where his focus is on automation within Autodesk Inventor and helping others in the Inventor community understand and utilize iLogic and Inventor API automation. Curtis creates Inventor automation tools that help companies become more efficient with their design efforts, and he teaches iLogic classes as well.
CURTIS WAGUESPACK: Hello, everyone. Welcome to iLogic-- 25 Tips and Tricks to Boost your Octane and Your inventor Automation. My name is Curtis Waguespack.
So a little bit about me-- I've used Inventor in AutoCAD in the real world for over 20 years. A lot of this has included iLogic and creating configurations and that sort of thing within using the iLogic tools. I currently work as an automation solution consultant, where I help professionals automate their designs within Inventor.
I teach AutoCAD-- or I teach iLogic classes. In the past, I've taught Inventor and AutoCAD classes as well. And in the past I authored and co-authored a number of Mastering Autodesk Inventor books. So that's a little bit about me.
Let's talk about you. So the intended audience for this class is really kind of anyone that's interested in iLogic. There will be some things that are relevant to the new user and the experienced user both. But I think all of this material is applicable to everyone so that you can know about the options and what's available when you reach that point with your automation task.
So we've got a lot to cover here. So let's just jump right into it. So very quickly, here are the objectives that we'll try to cover today. So we've got tips and techniques using the iLogic editor. We'll cover the Inventor API. We'll talk about some development error handling tools and techniques. And we'll also touch briefly on some ways to improve your iLogic automation and forms and how to interface with the users of your automation a little bit better.
So let's start with tips and techniques with the iLogic editor. So our first tip is about multiline editing. So when we're authoring a rule, there's kind of a little unknown trick here, where you can place your cursor, push Control, and then select multiple lines. When you have this multicursor up, then you can type in some value, and it'll enter that on every line.
So it's really easy to use. It just takes a little practice of doing it once or twice. But you'll get the hang of it.
So this tip was submitted or presented to me by a colleague of mine named Scott Hallmark. So I want to thank Scott for that too. And we should also mention that it doesn't have to be in line, and we can also do multiple places within the same line. So here we're typing it in, and we see that it adds two places in all three of those lines.
So our next tip is kind of a general idea, and I'm calling it "Extract to be exact!" And we just want to talk about how we get our code. So we can type it in. We can use our snippets in iLogic and that kind of thing. But I think we often overlook the fact that we can use that capture current state to extract the code.
The reasons we might do this, of course, is it's faster. It helps us reduce typos and errors and avoid omissions and eliminate syntax issues. All of those are things I struggle with. I'm not the best typist. And so, by extracting the code, I can eliminate a lot of troubleshooting errors by doing that.
So let's take a look at some examples here. So here's kind of a common place we might do this where we can capture a current state within an assembly. So we're right-clicking on a component, we're choosing Capture Current State, components constraint.add.
And so what this does is it pops in this line for adding a component. And then in this case, that component had three constraints on it. So it extracts the code for placing those constraints-- so constraining that component right in place. So pretty powerful stuff when you stop and think about what that's doing. We'll go through a few more of these, and then we'll kind of show some examples as well later.
So let's talk about how we do this in a drawing environment as well. Here, we can right-click on a line or an edge in our drawing view, and we get an iLogic option in our right-click menu. And then, again, we see that Capture Current State option. And what this allows us to do then is it brings up this little clipboard, and it brings in the code for capturing that sheet name, the view name, and then we also are getting that edge name or the Get Intent Name.
So bottom face is a named face within my model, and that edge is associated with that. You can see there's one called top face too. So if the edges in your drawing view have some named entity associated with it, like top face, it'll show that in the tooltip. If it doesn't, it'll show you just a generic name, and it'll create these names for you.
So once we kind of extract that, in the drawing environment we would open a new rule or existing rule. And then we can just paste our code in. So again, it does all of this for us.
So here's an example of this in action. So we're capturing the current state. So it brings in that bottom face. I click on top face, and you can see it grabbed that as well.
Now, I'm just going to hover around so you can see that there are some named entities, and then there's some entities without names. Again, if I clicked on one of those entities that didn't have a name, it would just name it for me. It would give it a generic name, but it would be usable.
So next we're creating a new iLogic rule, just giving it a name. And when this opens up, we can just paste. So Control-V or right-click and paste, and it brings all that code in.
Now, I'm going to go grab a snippet. We're going to get rid of the duplicate code-- some of that generic boilerplate code that was duplicates of what was brought in. And now I'm just going to replace these variables or place these variables into this add linear dimension. So that's all I needed. It's going to dimension between those two named entities-- so the top face and the bottom face. So again, very quickly it was able to create the code to create this dimension by extracting that, rather than starting from scratch and trying to figure out what the syntax is, what I need to include, what I don't need to include, and that kind of thing.
So let's look at an example of where this pays off. On the left, we're using the extract method. And I click that, and we're done. Sorry, that was the right.
On the left, we are still typing. And as I type, you might have noticed that I used a dash instead of an underscore. So if I ran this code, I would get an error. So again, one of the reasons we would want to extract the code is so that we avoid those syntax errors. And oftentimes, when we're working with Inventor models, some of the naming is a little cryptic. Some of it's kind of hard to understand if we weren't the one that created the model. And so, by extracting it we can just pull it off and skip a lot of those errors.
OK. Let's look at tip number 3. So this is one that I think we often overlook, but this is the format rule option. So oftentimes, as we're editing a rule, we end up with a lot of extra white space, tabs and spaces within our code that make it hard to read. And so, we can use these two buttons up here for indent and unindent to kind of format things line by line, but that can be very time consuming.
So instead of doing all of that, we can just right-click anywhere in the rule and choose this Format Rule option. And what that will do is take out all the extra white space and fix the indents and outdents as needed so that it's more readable. So let's take a quick look at this in action. So you can see this code has some spaces floating around in the middle, some bad indentation. And we just right-click, choose Format Rule, and it fixes all of that for us. So a really quick way to take care of that formatting and make our code much more readable. So don't forget that's there in the right-click.
One thing to know about this, there's a bit of a bug in this dealing with if then statements, particularly with the else if statement. So as far as the code is concerned, as far as the way iLogic compiles and runs the code, there's no difference in else with a space if and else with no space if. So if we use either one of those, those will work.
However, if we use this Format Rule option, unfortunately the case where there's a space doesn't really work. So we can see, in this bottom example, it didn't indent things where there was a space between else and if. So we would typically just kind of want to use the else if with no space because of this. So just be aware that when you use this Format Rule option.
OK, let's talk about adding code structure with subprocedures. This is kind of a big topic. We won't go too deep into this, but it really is a big jump forward into writing iLogic automation with Inventor.
So first, let's talk about what a sub procedure is. So very simply, a subprocedure is something that starts with a substatement and ends with an end substatement. So down here at the bottom, we have a sub called SayHello there starts with sub and ends with end sub. And the code is in the middle.
Now, any time we want to use a subprocedure, we have to add a sub main procedure. So the main body of our code would be up top, and then we call our subprocedure. So that's what's happening in this example. We have a sub called SayHello, we call it from our main rule or main sub, and then it steps down and here runs that code. In this case, it would just show a message box that says "Hello, world."
Now, one thing to note about a subprocedure is it doesn't return anything back up to the calling code. All it does is run whatever is down here, and then it returns back up top. Let's take a look at a little more fleshed out example here.
So here we have a sub main that's looking at the document. This is simply a document. And then it's going through all of the occurrences. And when it finds each occurrence, then it steps down into this subprocedure called GetBinNumber. And it passes this occurrence down to this subprocedure.
So now the sub has the occurrence, and it can do things with that occurrence. In this case, it's getting some iproperties and it's just displaying those iproperties in a message box. So there's a couple of things to know about this. As we pass this occurrence down as an argument, we need to make sure that our sub has that argument defined. In this case, we need to have it defined as a component occurrence so it knows what kind of data you're handing it.
The other thing to note about this is that the call keyword is optional. So I typically like to have the call keyword out in front of my sub just so that I know that that's what's going on when I look back and read this later. But it's completely optional, and you don't need to have that.
So let's take a look at of how this works just in a diagramming sense. So again, up here-- well, let's start down here actually. So down here we've defined it, we've given it a name, and then we've told it what the parameters of this subprocedure are. In this case it just has one, and we've defined the data type as component occurrence.
We've added some code down in here. And then, when we want to use this subprocedure, we just use the call keyword, we provide the name of the procedure, and again we give it the occurrence and pass it in as an argument. So if we would run this, we would see it just do exactly what we're showing here. It gets down here and pops out a message box displaying the iproperty information. Then it would return down here. And because we're using a loop, it would just loop through all of the occurrences in the assembly.
So why would we use these procedures? Well, one of the reasons we do this is because it makes things more readable and maintainable. So just adding some structure and organization to our code or to our iLogic automation makes these things a little more manageable as we look back on them maybe six months later or something like that. We also use these to perform repeated operations or tasks, such as calculation, doing some formatting, doing some data operation, that kind of thing.
And we can think of these as building blocks for our automation for our iLogic rules. So in this example, you can see that there's five different calls for these subs. There's four subs down here. But we're actually stepping into this sub twice. So we do it once at the beginning, we do the other three things, and then we do it again.
Now, if we had not used subprocedures for that, we would have to have repeated code to do whatever this process assembly thing is doing. So by using these subs as kind of these building blocks, it cuts down on the repetitive code and the need to copy and paste code that then needs to be maintained in multiple places and that kind of thing. So it's about efficiency and maintainability, as well as readability.
So similar to our subprocedures, we also have function procedures. So let's look at those and see what the differences are and what the similarities are. So function procedure you can see kind of looks very similar. We start with a function statement, and end with an end function statement, and put the rest of our code in the middle. Just like a subprocedure, in order to use a function we must have a sub main and an end main statement. And then we have to call it from some other statement. It doesn't necessarily have to be the main sub.
So unlike a sub, a function returns some value. So if we look at this code, we see something here called oOffset. So we have a variable here that's capturing whatever the results of this CalculateOffset function is. So this is how we call it, and then it captures it at the same time.
So once we've run this function, you'll see that it creates this offset variable and then it returns it right back up here. And in this case, our sub main is then using that variable to display in a message box. So if we look at this with some helpful arrows here, we can see that that's what's going on, or we can see what's going on I should say.
So we're getting some parameter values, and then we're passing these down to the function as arguments. And then again we've got a variable here that captures whatever is evaluated in this calculate offset function. So we pass these in, we're doing something with this if then statement to figure out our ShimSize, and then we're doing a small calculation. Oops, let me go backwards. Sorry.
And then we do this small calculation. And then we return this offset right back up to here. And then, finally, this message box would pop up and display our offset information.
So again, if we diagram this quickly, we would see that we name the function here. We define the parameters and their data types. So we're going to pass these values in as doubles. Then we do something with our function. So there's our statement code down here-- our function statement code here.
And then we have this return statement, where we return it right back up. We've captured it in this variable. And then we use it in this message box. So we're showing that pop up over here. So very, very similar to a subprocedure. The big difference is this return statement and pushing this back up to the top.
So why would we use function procedures? For a lot of the same reasons we would use subprocedures. Again, the big difference is this return option or return statement.
So on the subject of adding structure to our rules, let's talk about the class rule or the class ThisRule. So when we create a sub main in our rule so that we can use subs and functions, what's actually happening is iLogic immediately takes the form of a standard VBB.net. And so, what does that really mean. Well, it creates a blueprint for an iLogic rule database-- or data type I should say.
And so, that doesn't really mean a lot to us probably, but where this becomes useful is our ability to store variables right up here. So we can store information at the rule level, rather than having to hand information down from subs to other subs-- that kind of thing. So the way we do this is we have to add these manually.
We have to type in class. We give the class a name. In this case, we just called it ThisRule. And then we add an end class statement at the very bottom. So when we do this, now we can hold data at the iLogic rule level and kind of share that throughout the whole rule.
So let's compare a rule that uses an end class statement with one that doesn't have that. So over here we have a sub main and a sub GetBinNumber. And we are doing the same thing we've been doing in these examples, we're passing the occurrence name down. And then we do our thing and display message box.
So on this example, although it may look more complicated, it actually simplifies things a little bit, in that when we call the GetBinNumber subprocedure, we don't have to pass down the argument value. So what it does is it takes this occurrence and it passes it up here because we've defined it at the rule level. And then it just holds on to that. And as we step down from the main procedure into this procedure, it just grabs the occurrence from up here at the iLogic rule level.
So this sub then just takes and evaluates this iproperty value, captures it as a oBinNum variable, and then passes that back up to the top level again and just holds it there. So then what happens in this particular example is we grab another iproperty, and then our message box reaches up at the rule level and pulls down this oBinNumber. So the big difference is that we don't have to pass this back and forth between the subprocedure.
So here's maybe an example of where this might pay off a little better. So you can see here we have a sub main, and we're doing something with this file name. And then we've got these three subprocedures that are getting repeated three times. Now, if we were using just a sub and weren't using the class, we would have to pass this doc name down to these procedures every time. So we'd have to do that nine different times.
In this case, since we've added this variable at the top, it just gets stored up there, and then my subs can just use it. So again, just kind of simplifies the way that we handle those arguments and pass them between subs and functions. One thing to note is we don't need to name the class ThisRule.
We see this in the iLogic community. This is kind of what we normally see. But we could name it anything we want. It doesn't really matter.
So let's continue our discussion about creating some structure in our rules with this idea of creating collapsible code groups. So here we're talking about adding some outlining just using this apostrophe and square brackets. So once we've done that, then we can right-click and we can choose outlining and choose one of these options here. So we could toggle all outlining, which would collapse all of these code groups, or we could choose collapse definition, stop outlines. So there's a few options here that we could use.
So the syntax is pretty easy or pretty simple, in that it is just a apostrophe and then the opening square bracket. And we would put that up top. Generally, we'd give it some descriptive comment here. We don't need to do that, but that's generally what we would do.
And then at the end, we have the apostrophe and closing square bracket. Again, we could put some text down here if we wanted to, but typically we'd just see it at the top. So it creates this outlining structure within our code, and then we can use this-- I guess we'd call it a button-- little minus sign. If we click that, it'll collapse it down. If we click the plus sign, then it would open it back up.
Yeah. And we just kind of covered that in this slide and in the last comments there. But again, here's what that would look like if it was collapsed. And then here's a side-by-side view of the same rule with it collapse. And you can kind of start to see how this could be easier to edit. If we collapse everything down, we don't have to do as much scroll scrolling up and down within the rule editor. And sometimes it can make things just a little bit more readable and usable as we author or edit our iLogic rules.
So there's one thing to note about how we call our sub mains when we're using this outline. So here you can see that we've got parentheses after we use this sub main statement. And you'll notice that it lacks this outlining that connects the sub and the end sub. So we can't collapse our sub main when we've done it this way.
And if we want to be able to collapse it, we just simply leave those off. And which one is the right one to use or when you use one, it doesn't really matter. If I did that right-click option and chose collapse all, and I had it defined like this, the sub main would get collapsed, and that might not be what we want. It might be a little annoying that we keep having to open that back up. So in that case, we might use parentheses instead.
So this tip comes kind of on the back of some of the stuff I was showing earlier, and it's not so much about the iLogic editor, but it's something I think we've all kind of overlooked or a lot of us have overlooked if we've been doing iLogic for a while and have got set in our ways. So it's an important one to know about. So let's take a look at this.
So the way we have created configurations with iLogic in the past is that we would take an assembly and we would add all the components that we might want it to turn on and turn off. In this little example, we have two types of flywheels in our model. And so we put them both in there, and we just turn off the one we don't want and turn on the one we want. And maybe we had 10 versions of that. And so we would have to have nine of those turned off and one of those turned on, and we'd have to have the corresponding code to do all of that.
So when we did that, it created some suppression states. So if we were using bill of materials in the past-- I'm sorry, if we were using the level of details in the past, then we had to kind of manage that. Some folks decided they didn't want to mess with level of detail, so they use visibility to turn things on off instead of suppression. And so, that helped with some things, but we still had [INAUDIBLE] reps to deal with, and we still had to worry about how that showed up in our drawing views and that kind of thing. And then we had to worry about bill of materials materials and how our components showed up or didn't show in our bill of materials.
So it created kind of just an extra level or two of code, just in having to put all of this stuff in one model and then just turn it on and off. In Inventor 2019, they introduced this ability to start with a blank template and then just place components and actually constrain them in place. So this is kind of a new approach for our iLogic automation, and I think a lot of us kind of kept doing the same old approach that we had been doing.
And as far as making more editable code or more maintainable code, this might be a better approach. So let's kind of take a look at this method where we swap things in and out. And we don't have to worry as much about our bill of materials, our drawing views, and that kind of thing.
So here we're using this, and notice we have no models in here. We ran a rule that placed and constrained all those models in place. We're running a couple more rules that are just swapping these out. You notice nothing has changed in our browser. You notice it's a fully functional model. You start actually running, and the constraints we were driving those constraints with this rule.
So all of that was done starting off with a blank assembly. Let's take a look at how we do this. So one of the keys to making this happen is we want to name some geometry. So in our models we would right-click an edge, or a face, or a vertex, and we would choose Assign Entity Name.
We give it a name. And then when we do this the first time, iLogic creates a new tab in our iLogic browser, and then our name shows up here. So the reason this is important is we want to use these names in our code later. Or really we want to extract those.
So the next thing we would do in this process is just constrain our assembly normally. So put your assembly together the way you would want to do that. Typically, we're going to want to use those named edges and faces that we created in the previous step in order to create those relationships or those constraints. And then, once we have our assembly together, we can create a rule, and we can come in, select a component, right-click, and choose Capture Current State Components Constraints Add.
So what this does is it pulls all of that out. So we covered this in an earlier tip, but you can see it. It really gives you exactly what your assembly already has in place. So it puts this part in place, and then it puts all of these constraints in there as well, exactly as they exist.
So typically, the next thing we would do then is maybe copy that rule and change and configure that second rule to use a different component or something like that. In this example, that's what we're doing. We've got one rule that uses flywheel. We've got another rule that uses this other part called flywheel2. And so by doing that, we can run both of those rules at different times to swap those options in and out.
Excuse me. So here's kind of a demo of that. Here we're right-clicking. We're assigning a name to this edge. It's going to put this edge up here. And there was already three other edges up there. Now there's four.
There's an option to turn that edge off, or we can turn them all on. It's not just edges. In this example, we're just using edges. But recall, we can use faces and points as well.
Go over here. We would add a new rule. And then, again, we would right-click on a component, and we're just going to extract out that code.
So in this case, it brings in my constraint information a little bit in a way that's kind of hard to reach. So just for our purposes, I'm going to kind of format that. Right-click, choose Format to get rid of all that extra space. There we go. And now we're going to add link2.ipt here, save it.
And we run it, it's going to swap out this component with link2.ipt. There's one out there on disk that it finds in the project. And it's that easy to create these configurations. Now, again, it doesn't put this extra link in here, it just reuses this long link name in the browser and swaps out a different ipt or a different part file.
So it simplifies the code, in that we don't have to worry about bill of materials, we don't have to worry about levels of details, or view representations-- all those other things we used to have to kind of think about sometimes. And of course we were extracting the code, so we had to do very little typing or entering of information. So let's talk about planning your code.
So tip number 9. So here's an example of two rules that do the exact same thing. The one on the left is over 2,500 lines, and the one on the right is 67 lines. And they do exactly the same thing. So the one on the right uses some code structure like we were talking about-- it uses some subs.
So let's kind of take a look at maybe how we would go from this to this. So typically what we would do is we just start writing some code. So in this case, we start writing a conditional if then statement to look at a range of height. And then, once we've figured out that we're in that range, we set this size parameter, and then we set this count parameter. And then we start doing something with visibility and BOM structure. And then down here we're suppressing a constraint.
And you notice we're doing this for assembly that's NG4 left hand. And we do it for NG4 right hand. Then we come down here and we do it for NG5 left hand and right hand, NG6, and we keep doing this over and over and over. So when we write this out, we might start to realize, boy, we're copying and pasting this block of code a lot and really only changing a couple of things in here. So a pattern starts to emerge.
So we want to kind of think about how to find those patterns in our code. And once we recognize them, then maybe we want to pause and say, OK, how can I plan this out? So once we have this kind of fleshed out a little bit, we can evaluate and outline our code. So it might look something like this.
We say, OK, we have 20 instances of right-hand subassemblies. We have 20 instances of left-hand subassemblies. So we have three subassemblies that we're dealing with in this configuration. And then we say, OK, 1 through 3 are really not changing-- we're leaving those static. But there are 17 other height ranges we have to deal with. So it would be for the cases of 4 through 20.
And then, with each height range we set the size, we set the count, and then we're setting visibility and BOM structure. So that's the basis of our code. And we realize that, based on this example that we started with, where we wrote out the first part of this if statement for just size 4, we ended up with 140 lines. So now that we realize we need to do this for 17 different height ranges, we do a little bit of calculation and realize, oh, wow, that's going to be over 2,000 lines of code. Maybe we better stop and plan this out and think of a better way to optimize this.
So the next step, we just kind of write some pseudocode. So we would maybe get out some scratch paper. But maybe we would do this in Microsoft Word or just do it in the iLogic editor-- whatever works for you.
I would say we're going to need a trigger. The trigger that for this rule is going to be height. I'm going to want to call a sub to set the size. So I would kind of outline what that size sub looks like, which is really just about setting that height. So we're going to pass in the height and then set the size down here.
And we're going to do that 20 times or 17 times-- whatever it was. And then, after we have that, we're going to loop from 4 to 20. And then we're going to set the count. We're going to work with the visibility and the BOM structure.
So I say, OK. Well, if I'm going to do that, I might as well create a sub that deals with visibility. Might as well create a sub that deals with BOM structure. So now I have this pseudocode, and it becomes the outline for what I'm actually going to write.
So if we look at how that turns out, we take 34 different assemblies or 34 different blocks of code dealing with different assemblies, and that would have taken us down to our 2,500 lines of code. And we've reduced that down to just these two little subs. So that's pretty amazing, and we did that just because we did a little bit of planning ahead of time.
So this is what our final rule looked like. And just to give you a little bit kind of better insight into how that worked, we had our sub main, where we're handling those-- well, first what we're doing is we're calling our size sub. And then we're handling those cases 4 through 20 and stepping down into setting visibility for the left hand and the right hand. So here's our sub for setting visibility, here's our sub for setting our BOM structure, and then our biggest sub was setting the size. Now, it ended up down here at the end of the code, but it was actually the first thing we called from our sub main. So all of that, again, was achieved by taking the time to kind of write out some of it in longhand, look for a pattern, pause, kind of outline, write some pseudocode, and then build our rule. Rather than just grind away by copy and paste, and changing numbers and names, and that kind of thing, which is what we often see when we look at iLogic code.
So that last example used loops to pull off a lot of the magic. So let's look at loops really briefly. So here's an example of an unoptimized rule on the left, where we're setting some visibility states, or some active states actually. And we're doing that based off of a parameter-- so a Boolean parameter-- that's called IsRightHand. So if this is true, then we do all this. Otherwise, we do all of this.
So we came out with 26 lines of code. Our optimized version using a loop is down to 12 lines of code. It's not a big advantage there as far as number of lines of code. The biggest advantages is if something changes I just have fewer places to change names and that sort of thing.
So typically, when I teach an iLogic class, we spend a lot of time on loops and kind of go through all the miniloops that we can use. For time we don't really have that option today, but I wanted to mention that you can find examples of these online because iLogic just uses VB.net for its coding. So often you can just type something like VB.net for each into a search engine. You'll probably come across a site like this-- dotnetperls.com-- that has a lot of examples.
So in this website, if you just type in VB.net. It'll filter down for only VB.net examples. And you can see that one of them that shows up here is a for each loop. So again, if you're new to loops, study up on those a little bit. They help you optimize and build stronger code in leaps and bounds.
So in the last example, we used a not operator. So let's talk about Booleans and not operators. So a Boolean, as far as computing is concerned, has two possible values. It can be true or false. So it's just a binary variable. And you're probably most familiar with these in our user parameters, where we can create something like this one that is called IsCustom. And we set that to be a true false parameter.
So where we use this in iLogic and why it becomes very powerful is that we can take something like this, where we create a long conditional statement with an if then, and we can simplify it a great deal. So when we have this Boolean parameter IsCustom, we know that it's going to return true or false. But we have these other iLogic functions that return true or false as well. So rather than having to go through and look at all of the things that are going to be true or false when is custom is true and then do the same thing down here, we could do something like this, which is to set this IsActive to just read in whatever this value is.
And then because it is a Boolean that only has an option of being true or false, we can use the not operator to flip that the other way. So if we look at this code, we can see that really what we were doing is saying that if IsCustom is false, then-- let me try that again. What we were saying is that bolt 3 and 4 would always be the optimal opposite of IsCustom. Bolt 1 and 2 are always the same as IsCustom. And so that's exactly what this is doing. We're just flipping the Boolean value and setting that to be whatever it needs to be for each one of these bolts.
So we've got four bolts in this example. But obviously, in your automation, we end up with lots and lots of opponents doing this sometimes. So we can simplify our code a great deal and really, really reduce the number of lines of code, but also kind of the complexity of naming and that kind of thing by simply using not with the Boolean parameters.
OK. So let's take a look at our next objective, which has to do with the API. So API just means the Application Programming Interface. And we're going to talk about what that is using a bit of an analogy.
So first, let's understand the API using this analogy of a chef, a waiter, and a menu. So if we compare the chef to Inventor source code and the waiter to Inventor's API, then we might think about the fact that the chef knows how to create any dish and has access to all the recipes, the ingredients, all the pots, and pans, and tools, all the techniques, all of that kind of thing that's in the kitchen. So that represents our Autodesk source code for Autodesk Inventor.
We don't have access to that. They don't let us see all that kind of stuff. We don't need access to that. So what we use is Inventor's application programming interface, which are the way we interface with the chef is through the waiters. So our API is like that. We just use that to interface with the source code.
So iLogic is kind of a step removed from that, in that it's just a simplified menu that we use to make API calls and then communicate with the source code. So just kind of keep that analogy in mind, and that will help a little bit as far as what we're going to talk about. Let's look at an example here of an API call or an API function and an iLogic function.
So what we have on the left here is a function that first gets the active document, which is a part document. Then we step into getting the user parameters or the custom parameter-- I'm sorry, custom properties set. And then we need to try to get the value of that. But if it doesn't exist, then we need to create it, otherwise we get an error. And then, finally, we can set the value.
So the API version has to do all of this. And the iLogic version simply defines that we're looking for a custom parameter, again property Custom iproperty, and then it gives the name of that custom iproperty, and then it tries to set the value. Now, they do the exact same thing. Because iLogic works with the active document or the document that it calls the rule from, we don't have to look for the document or define the document.
We just use one word to grab this property set. We pass in the property name. So that's not a whole lot different. The big difference here is that in the API version we had to check and see if it existed first. iLogic just creates the iproperty if it doesn't exist. And then, again, finally, we just set the value of that iproperty. So again, both do the exact same thing, we just have a more concise way to do all of this or more concise way to write all of this in our rule. They're doing the same thing.
So let's talk about this API. So we have an API object model poster here that Autodesk puts out. You can find this online. And it goes through all of our API calls. And these calls, or I should say objects-- all these API objects-- are really just collections and objects within collections. So all of these menus, or these dropdowns, or whatever we want to call this, really just is a bunch of collections and objects within those collections.
So if we think about it like that, let's take a look at this example trying to do something with an extrude feature. So here we have the hierarchy of drilling down to this extrude feature. So let's compare that to what we're familiar with, which is a part feature. Here, we've got everything that makes up the entire part document. Then we have the component definition-- what's specific to this part.
Then we have part features in a collection. Then we have extruded features in a collection. And we have this-- then we might just grab one extrude feature or extrusion feature. So let's compare this to code.
You can see that we can write code to call each one of these. That's what we would have here. Or we could, since we're working with the iLogic, use this document, because that is calling or getting the document this rule is called from. So by doing that we can skip getting the application and the documents collection.
But this is maybe what we see more often, where we kind of do this drill down of the API all in one line. So with that in mind, let's talk about IntelliSense and how declared variables impact that. Because that's what helps us relate our code in one line to our API. So here is an example of using IntelliSense. We're just doing a dot, and it drops down these menus, and then we can drill down and get that next collection or object to get the extrusion one.
So what often happens though, is we end up here. We're going along and we're trying to get the component definition in this case, and we can't find it. So what's going on here? So we can't navigate the API consistently because we're not doing something correctly.
It all comes down to this. So we have to declare our part document in order to be able to get the right stuff to come up with IntelliSense or get to the right place within the API. So often we forget to do this, and it causes us trouble. So keep that in mind. If we're not seeing what we expect or kind of get lost in trying to navigate the API, this is what's going on.
So let's look at how we would fix that. So we would come up here. We would type in dim, which just means dimension or declare. Dim oDoc as PartDocument. And then we can come down here and type dot, and now we get the right stuff. We start getting component definition, and we can drill down and find everything we expected to find. So the reason that works is because of this right here. So we declared this oDoc variable as a PartDocument. And that's what makes the magic happen.
So let's kind of look at why that happens. Well, by default it was just a document-- a generic document. So we're calling inventor. We have drawing documents, and part documents, and assembly documents, and we have just kind of documents as a type by itself that is generic and includes all those others.
So in this case we couldn't find part component definition because we hadn't defined it as a part document. But as soon as we do, then we've moved over from general documents or generic documents to specifically part documents, and suddenly our IntelliSense starts picking up the right thing. So again, make these declarations in your code, and that'll get you to the right place within the API.
Another thing to mention is there are these filters down here at the bottom of our IntelliSense menu that relate to iLogic, Inventor, and Standard.Net. If you accidentally click these buttons, it will filter and you won't see everything. Or if you purposely click it, it'll do the same thing. Just be aware that sometimes we accidentally click those and things won't come up.
Let's quickly talk about accessing the API and programming help files. So we do this by coming up here and choosing this little question mark button, Help, programming API Help. Within here you can search. And so, if I wanted to find extrude features, I would just type that in. It'll take me right to the properties and methods for an extrude feature object.
There's also these samples down below here. So the samples are really useful. They're written for VBA, but you can very easily convert those for iLogic just by taking out set and that kind of thing. So just be aware that there's all of these examples for you out there, and we access those through the help files. So again, remember, we do that right up top here.
OK, let's talk about exploring development and error-handling techniques. So first of all, we want to talk about using the iLogic logger. So when we are in an iLogic rule, we can put these logger lines in, and it will write these out to an iLogic logger tab.
So the old way of doing this might have been just by doing some message box sleuthing. We use a message box, and all these things would pop up, and we'd have to click OK 1,000 times. But it would display that information.
What we probably want to start doing is using the iLogic log whenever we can. we access that by that little plus sign next to the Model tab. We can move this around and park it where we want and dock it to the bottom, or the side, or however we like it. We can even float it on a second screen.
Again, we access this that little plus sign right there and then the iLogic log button there. So within our rules, we have this option here for the level. So we have all these levels here. So what these do for us is we can choose a level. So if we choose trace, when we run this rule it would show all of these levels. If we choose warn, in this case, it would start with warn and go only down.
So it's kind of a cascading menu. So in that case, we would only get these three lines-- warn, error, and fatal. So just keep that in mind. I often just use info for most things and leave it on trace.
There's also this button for detailed trace. Detailed trace allows you to trace when we're stepping into a rule. So oftentimes what happens when we're creating a lot of iLogic rules is we see that the automation is getting triggered by parameters, and a rule might be running multiple times. And it gets hard to tell why that's happening. If we turn on detailed trace and run that, we can start to see when it steps into a rule, and it'll even tell us what triggered it. So if a parameter was what triggered running one of these rules, it would show that down here. So really powerful for helping us figure that stuff out.
Let's talk about writing logger information out to a log. I'll provide example in the handout, but we can do that. We can write it out to a Notepad file. This is really helpful when we need to maybe have a user send us it at a later date. So this example was originally provided by Mike Dick of Autodesk. So thank you to him.
Which brings me to a quick tip, which is to visit the forum, the iLogic and VB.net forum. Ask questions, search solutions, even provide answers. Once you kind of get familiar with these things, you might see something that you can answer. So it's a great community, and I encourage you to go visit that.
Let's talk about using a log monitor. So there's a tool out there called BareTail. It'll allow you to create some highlighting and watching-- some watches I should say. And then, if you have that external iLogic log, it'll follow that, and it'll highlight it. So here it's got an error, and maybe I want to watch for warnings too so.
As I'm stepping through this automation, we'll see it-- oh, there it goes. It highlights a warning. So a great way to be able to kind of keep an eye on your automation, figure out what's going on. And it runs active. You can set it to always be on top. And it allows you some real-time monitoring. So that's baretail.com I think is what is. But something to be aware of. I have no affiliation with that, it's just something I use and find very useful.
Let's talk about using try catch statements with the iLogic logger. So oftentimes we want to kind of figure out what line the error is on. So we also want to use a try catch because it catches the error but doesn't stop the code from running. So this can be useful when we have a large piece of automation and we're trying to figure things out. Or maybe this is something our users are using, and we don't want to interrupt them so we can catch the error. But we do want to watch a log and figure out where the errors are coming from.
So what we can do is we can use this catch ex as exception is what we often see. thus ex could be anything. So we catch that exception. In this case, we're handling it down to this sub. This sub is called error handlers.
And so we hand it down here. We're getting the stack trace. And in this case, we're kind of cutting off part of it so that we're only getting the name of the rule and the line. So this line is the important part, right?
So then we're writing this out to the logger. And that's what we want to see-- we want to see the line that the error happened. So here we're seeing it. It said line six. Really, the error happened at line 4, but we're catching the exception, and so it reports in.
In this case, all this happened because there was no parameter named "Foo". And it also tells us that because we got the exception message. So a really great way to handle errors with our iLogic.
Our next tip is to use a code comparison tool. There's lots of these down here, but one of those is called Beyond Compare. So just be aware of that. In this example here we've got three lines that have changed between this rule and an old version of this rule. And it's a really helpful way to figure out what we changed that broke the code or something like that. Of course, if we're doing this, we're probably using external iLogic rules, and that's important to make that work.
Similarly, we can search within our iLogic rules. So here we might use something like Notepad++ which allows us to search a folder. And then we can search for a some string in all of the rules within that folder. In this case, it found four different rules that had that string. And then I can see it was used for different places in this one rule. So a really great way to kind of look inside a collection of rules.
Again, this would be external rules. If we are using internal rules, we can do this sort of. So when we open a part with internal rules and run those rules or edit those rules, Inventor writes those out to this temp directory. So it's this address. Obviously not my name. It'd be your name or your profile name.
And then we could use this to look in those rules too. So we could use Notepad++ to look at this directory for that same search term or some other search term. So that's helpful with internal rule to some extent.
OK, let's talk about creating a better interface between your iLogic automation. So I submitted an Autodesk University class for just this topic. So it's a big topic. I could do a couple of hours probably just on iLogic forms. We're not going to be able to cover all that, so let's look at a few quick tips.
So one of these is to use timed message boxes. So in this example we're running two rules. Notice that the user's cursor stays right in that circle. It never clicks the OK button in those message boxes. They just time out and go away. It allows us to run multiple rules without interruptions but still provide the user with some information.
So again, there will be an example of this in the handout, but the way we do this is we just call this. In this case, it's calling an external rule. And then there's some code here that has it time out and that kind of thing. This example was originally provided by Mike Deck of Autodesk again. I believe I found that on the forums years ago. I think someone else had asked the question originally, but a big thank you to Mike for that as well.
This is a tip that was shown to me by Andrew Humiston who was in one of my iLogic classes. So he's using these general annotation tools to write information that floats out here in the graphics area. So he does a lot with sheet metal parts and writes his sheet metal information up here as far as materials and that kind of thing. And it just is always there when the user opens up their parts. So they don't have to go digging for the important information-- it's just displayed right in front of them.
So we're just using this annotate general note to float this message right up here. We might tie it to an event trigger. And again, here's kind of an example of that. This will be in the handout as well.
Let's talk about adding buttons to your for your global forms in external rules. So with Inventor 2023, we can do that. It's very simple. So we just go into the Customize menu, go to ribbon, changes to iLogic rules. We find our rules here, and push them over here, and it shows up right up top. So a really powerful new improvement. So just know that that's there as well.
So build better forms. Let's take a look at some of the options here. So one of the things I like to see people do is add buttons on their forms to their rules. We can add a rule here, and it creates a button. But I also like to see you make it visual. So add an icon or a picture to your buttons. And users just tend to kind of understand the form at a glance that way.
So the way we do this, of course, is we just in our form go down to the Properties. In Appearance there's an option for Image. If we click that, we can browse out and find a little icon image and something that we would have downloaded or created for ourselves.
How about we talk about making it more interactive. So here's where we might take some dropdown menus. And rather than having things statically placed in these lists, we have a rule that reads from a folder. In this case, we're reading from this active jobs folder, getting all of these subfolders and populating the list with that name. And likewise, then we go down into that folder and get the job numbers and do the same thing. So this prevents our users from putting something invalid or some name that a folder that doesn't exist or something like that. Again, there's an example of this in the handout.
Another example of making these forms more interactive would be to disallow our users to use buttons until it makes sense within our process. So in this case, we've added a rule to our form, and then we went down to the behavior area and used this Enabling Parameter Name. And we chose this hasBaseModel. So this is just a true false parameter. And we chose this to control when this button shows up or doesn't show up.
So likewise we can do this with picture groups. So we can pull up one of these picture groups into our form, add multiple pictures, and then use a controlling parameter to choose when we display messages or change the icon. So we might go from a green icon that shows that all is well to a warning that tells us something isn't right. The way we do this is we use a parameter here, and this parameter correlates to these three pictures. And I'm just using these names and these names to compare. So if we change this with some code, that picture in our form automatically updates.
OK. So I know that was a lot. Look for the handout for examples in code. Please let me know if you have any questions, and thank you for your time.
Downloads
Étiquettes
Produit | |
Secteurs d'activité | |
Thèmes |