My teams are new to coding (and robotics). I am familiar with basic coding and am trying to assist them. We are running into an issue with encoders. I am attaching screenshots of the blocks to help clarify what we are trying to accomplish.
An explanation of what I think the code is doing and should be doing is below the image.
The main method is at the top. /it attempts to call [move to distance, velocity with] two times; both times it is called with a value of 50.
The [move to distance, velocity with] block receives the value [cm], then uses the [CurrentPosition] function to get the current position. On the first run, that is assumed to be 0. The current position is passed to [position to cm with] so that the current position can be converted to centimeters. That total is added to the current desired movement amount and stored in the [targetPosition] variable.
This variable is used to set the desired motor [TargetPosition].
When setting the desired target position, using the [TargetPosition] command, [move n centimeters with: centimeters] is called with the [targetPosition] value. [move n centimeters with: centimeters] returns the number of ticks.
For a single move, all block works as desired. We have tested it from 12 to 120cm; but it can only be called once.
If it is called more than once in a row, it appears to move the longer of the two distances.
We have been testing by calling it twice in a row to move straight. Obviously if we just move straight twice, we can set the move to the cumulative amount. But we want to be able to move and turn, then move again. That will require separate moves.
I tested it an it was inconsistent. For the most part, it didn’t work as intended. When pasting the photo I realized I only set my condition based on the left wheel, but it seems that that shouldn’t matter. It should still reset the position and power of both motors.
For a single move, all block works as desired. We have tested it from 12 to 120cm; but it can only be called once. If it is called more than once in a row, it appears to move the longer of the two distances.
Yes, this makes perfect sense (to me). Let me explain.
What you’re doing when you issue a RUN_TO_POSITION command is asking the firmware in the Control Hub to “take the wheel” and move a motor to a given position from the current “zero” position (wherever the motor was last set in the “STOP_AND_RESET_ENCODER” mode). Think of this as someone at a restaurant and they’re asking the waiter for a drink. You ask the waiter for a glass of Lemonade, and then you immediately ask the waiter for a glass of Sweet Tea. The waiter hasn’t even had a chance to really do anything, and you’re then immediately asking him for something else. He’s logically going to do whatever you told him last.
Understand that when you set the target destination, set the mode to “RUN_TO_POSITION”, and then provide the speed, that’s in effect asking the “waiter” to perform the action. You are free to continue eating chips and salsa at the table, or talk with your friends, or whatever - asking the waiter to do something isn’t a “blocking” event, meaning you don’t stop everything you’re doing until the waiter comes back. “RUN_TO_POSITION” is the same way. You’re asking the subsystem to carry out your commands, and then you can do other stuff on the side. This might be unintuitive, but it allows you to move across the field and raise/lower an arm and other stuff at the same time. But if you want to wait until your drink has been delivered before doing anything else, you have to wait until the action has completed.
So let’s take a look at what your code COULD look like:
In my example I have two motors, one plugged into MotorPort0 on the Control Hub (MotorPort0CH) and one plugged into MotorPort1 on the Control Hub (MotorPort1CH). In my main runOpMode function I:
Set one of them to reverse
I waitForStart.
When I start the program (to move past waitForStart), I call the MoveToDistanceFromCurrentPosition() function and I pass in the number of ticks my motors need to rotate and the speed at which they need to rotate (this function moves the robot in a straight line).
I then have to wait until the motors are done moving, which I can know by monitoring the isBusy block. While I’m waiting, I call the ShowTelemetry function to show me what’s currently going on.
Then I repeat steps 3 and 4 to move to a new position (based on the new location).
When it’s done, the program is done.
Hope this makes sense. if there’s anything you don’t understand let me know!
Thank you. That made perfect sense. Basically, the process is running in it’s own thread so once it starts, code execution continues. Adding a wait in the method isn’t helpful, because it becomes part of the process. Adding the wait after the method causes the wait to execute until the process stops.
We got forward and backward working perfectly; we also built a block that would allow it to turn left and right. That one may need a little tweaking, but it works great.
One followup question. For now we only plan to turn left and right, so we created a method called turn that takes an argument “left” for left turns or “right” for right turns. Is there a way to create a list for a custom block? Like some of the existing blocks have?
Is there a way to create a list for a custom block? Like some of the existing blocks have?
What you’re asking for (rightfully so) is the concept of an enumerated type, and unfortunately the version of Blocks we’re using doesn’t support the concept of user-defined enumerated types. The enumerations you see in other blocks are actually lists of instances of classes (behind the scenes), and not exactly an enumeration list.
The closest I’ve seen to creating enumerated types was recently done by REV in their starter bot code. They used variables and variable names to create a super close approximation to enumerations. Here’s a simple example of how you can use this for enumeration: