ROS_Lab_2_ECE_470_Krishna_R._pr16
pdf
keyboard_arrow_up
School
University of Illinois, Urbana Champaign *
*We aren’t endorsed by this school
Course
470
Subject
Mechanical Engineering
Date
Apr 3, 2024
Type
Pages
19
Uploaded by AdmiralHamster1144
Pranavkrishna Ramasubramanian pr16 TA: Michelle Zosky Section: Monday 9AM Submitted 3/7/2021 Tower Of Hanoi Lab – ROS
Introduction The objective of this lab was to complete the Tower of Hanoi (ToH) puzzle using the simulated UR3 in the Gazebo. The ToH puzzle is a simple and ancient puzzle that involves a simple recursive algorithm. The original puzzle is series of 3 towers with rings around the starting tower. These 3 rings vary in diameter, such that the largest one is at the bottom, and reduce in diameter until the topmost ring. Figure 1 –
Traditional Tower of Hanoi Problem (Source: Wikimedia Commons) The objective of this puzzle is to move the rings to a goal tower, set to either of the other 2 remaining towers, with the simple rule that a larger ring cannot be placed on top of a smaller ring.
The solution to the puzzle is an algorithm that uses the spare tower and the end goal as stop overs. Figure 2 –
Solution Algorithm to 3 Tier Tower of Hanoi The focus of this lab was to use a feedback control system with the robot and its end effector to solve the ToH problem in virtual space using robot operating system (ROS) in python. ROS is the control interface for control UR3 robots in virtual and real space with hardware abstraction and information processing between multiple parts of low-level hardware. ROS does this using a subscriber –
callback data model, where the information of the robot is passed through nodes that collect information, assign it to a specific topic and message type, and assign that to the current value. The subscriber then calls that data through a callback and uses it to enact the next step of the command.
Figure 3 –
Callback Function Flowchart The pieces we were instructed to focus on were the end effector with feedback control, hardware movement abstraction with the ToH solution, information processing from user input, and edge case handling. To create a simpler version of the ToH, we use cubes in a line, and instead of the Z –
axis fo
r the tower, we use the variance in the y axis as the ‘height’ of the tower. The x axis makes up the ‘towers’ themselves. The goal is for the user to input the starting tower and have the robot follow the ToH algorithm to place the cubes in the correct order to the destination tower they specify. The other goal is for edge testing using the feedback system, where if the gripper tries to move a cube but does not detect a cube with the suction Boolean, the UR3 must also return to home and cancel the rest of the program. ROS Publisher
•
Publishes the latest sensor information
Format
Topic: /(*topic*)
Message Type:/(*type*)
•
This format that ROS uses is accessible inside the Python code, alowing it to be processed
ROS Subscriber
•
This data accessed by the subsriber
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
Method To begin, we were given the instructions to complete the setup of the lab in the VMWare software, using Linux. ROS and the Gazebo were already installed, but we were supposed to download the main program directory and create the p
roject folder to house this lab’s code. Once this part was setup, we were supposed to edit the lab2 python code to solve the ToH problem. Code The code’s problem was broken into 4 pieces: -
Create a subscriber and a callback function for the information given by the ROS running in the background. -
Create a moveBlock function that employed the preexisting moveArm and gripper functions, parametrizing the Q –
matrix information with where the blocks are (with start and destination coordinates), including an edge case for the rejection of a lack of an existing block. -
Obtain user input from the terminal correctly and determine the tower to solve -
Solve the ToH in the main function according to the user input, utilizing the moveBlock function. Approaching Part 1 of Code I started the first part by following the power point on the specific ROS commands that would display the UR3 robot information as the program was running but adapted the commands to be specific for the gripper. Using the $ rosmsg info ur3_driver/gripper_input
command inside the ros terminal, I was able to get the information that the subscriber outputted a 32 - bit DIGIN (digital signal), as a 0 or 1. Using this information, I created the callback as follows: sub_suction = rospy
.
Subscriber
(
'ur3/gripper_input'
, gripper_input
, gripper_callback
)
This rospy.Subscriber function takes the data published in ROS under the gripper_input and feeds the information to the gripper_callback function, at the start of the code: def gripper_callback
(
msg
): global digital_in_0 digital_in_0 = msg
.
DIGIN The parameter “msg” contains the data from the subscriber under the data type DIGIN. I then set the existing variable digital_in_0 to be the same as this variable so it is accessible from a global context for other functions. Approaching Part 2 of Code For the second part, we were supposed to abstract the series of commands required to move a block from point a to point b inside the Q –
Matrix. We were given the general functions to move the arm and activate the gripper with the following function definitions: def gripper
(
pub_cmd
, loop_rate
, io_0
): global SPIN_RATE global thetas global current_io_0 global current_position error = 0 spin_count = 0 at_goal = 0 current_io_0 = io_0 driver_msg = command
() driver_msg
.
destination = current_position driver_msg
.
v = 1.0 driver_msg
.
a = 1.0 driver_msg
.
io_0 = io_0 pub_cmd
.
publish
(
driver_msg
) while
(
at_goal == 0
): if
( abs
(
thetas
[
0
]-
driver_msg
.
destination
[
0
]) < 0.0005 and \ abs
(
thetas
[
1
]-
driver_msg
.
destination
[
1
]) < 0.0005 and \ abs
(
thetas
[
2
]-
driver_msg
.
destination
[
2
]) < 0.0005 and \ abs
(
thetas
[
3
]-
driver_msg
.
destination
[
3
]) < 0.0005 and \
abs
(
thetas
[
4
]-
driver_msg
.
destination
[
4
]) < 0.0005 and \ abs
(
thetas
[
5
]-
driver_msg
.
destination
[
5
]) < 0.0005 ): at_goal = 1 loop_rate
.
sleep
() if
(
spin_count > SPIN_RATE
*
5
): pub_cmd
.
publish
(
driver_msg
) rospy
.
loginfo
(
"Just published again driver_msg"
) spin_count = 0 spin_count = spin_count + 1 return error and def move_arm
(
pub_cmd
, loop_rate
, dest
, vel
, accel
): global thetas global SPIN_RATE error = 0 spin_count = 0 at_goal = 0 driver_msg = command
() driver_msg
.
destination = dest driver_msg
.
v = vel driver_msg
.
a = accel driver_msg
.
io_0 = current_io_0 pub_cmd
.
publish
(
driver_msg
) loop_rate
.
sleep
() while
(
at_goal == 0
): if
( abs
(
thetas
[
0
]-
driver_msg
.
destination
[
0
]) < 0.0005 and \ abs
(
thetas
[
1
]-
driver_msg
.
destination
[
1
]) < 0.0005 and \ abs
(
thetas
[
2
]-
driver_msg
.
destination
[
2
]) < 0.0005 and \ abs
(
thetas
[
3
]-
driver_msg
.
destination
[
3
]) < 0.0005 and \ abs
(
thetas
[
4
]-
driver_msg
.
destination
[
4
]) < 0.0005 and \ abs
(
thetas
[
5
]-
driver_msg
.
destination
[
5
]) < 0.0005 ): at_goal = 1 #rospy.loginfo("Goal is reached!") loop_rate
.
sleep
() if
(
spin_count > SPIN_RATE
*
5
):
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
pub_cmd
.
publish
(
driver_msg
) rospy
.
loginfo
(
"Just published again driver_msg"
) spin_count = 0 spin_count = spin_count + 1 return error Given these and the basic commands to approach a block at a height above the block, then go down to pick it up, I then created the moveBlock function employing this and the failsafe from the callback function, using the larger function input parameters to the lower sub function inputs. I also used the Q –
Matrix again. In doing this, I also slowed down the speed of the arm doing more precise movement as to minimize error, and to maximize time efficiency during imprecise movements with a larger max velocity for the 3D motion profile to follow along. def move_block
(
pub_cmd
, loop_rate
, start_loc
, start_height
, end_loc
, end_height
): global Q error = 0 ### Hint: Use the Q array to map out your towers by location and "height". move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
1
], 4.0
, 4.0
) gripper
(
pub_cmd
, loop_rate
, suction_on
) move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
0
], 1.0
, 4.0
) #at the location of block if digital_in_0 == 0
: gripper
(
pub_cmd
, loop_rate
, suction_off
) move_arm
(
pub_cmd
, loop_rate
, home
, 1.0
, 1.0
) print
(
'error with gripper'
) sys
.
exit
() move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
1
], 1.0
, 4.0
) move_arm
(
pub_cmd
, loop_rate
, Q
[
end_loc
][
end_height
][
1
], 4.0
, 4.0
) move_arm
(
pub_cmd
, loop_rate
, Q
[
end_loc
][
end_height
][
0
], 1.0
, 4.0
) gripper
(
pub_cmd
, loop_rate
, suction_off
) loop_rate
.
sleep
() move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
1
], 4.0
, 4.0
) return error
This portion was not complete until I was able to test the robot in the final working main function. I had messed up the order of one of the move_arm functions, where the robot would not fully pick up a block. This was a small error worked out at the end with a change of a 0 to a 1. Approaching the 3
rd
Portion of Code Obtaining user input and defining the towers was the next part of the challenge. This was vital to the move block commands, which took a final tower and an initial start tower into the parameters of the function. The user input must calculate the spare tower based on the given inputs, as the user might not know how to solve the ToH problem. The user is prompted with 2 questions in the execution terminal –
the start tower and the destination tower, as an input of 1, 2 or 3. 0 Will exit the system. I used the example input/response code and added a second case for the input. I also ensured that the criteria for what inputs were acceptable with an if-else condition. For the input loop to continue until an acceptable input was give, I kept asking until a Boolean was true in a while loop. input_done = 0 start_tower = 0 dest_tower = 0 while
(
not input_done
): input_string1 = raw_input
(
"Enter The Start Tower"
) input_string2 = raw_input
(
"Enter The Destination Tower"
) print
(
"You entered " + input_string1 + 'for starting tower' + "\n" + "You entered " + input_string2 + 'for destination tower'
) if (
int
(
input_string1
) == 0 or int
(
input_string2
) == 0
): print
(
"Quitting... "
) sys
.
exit
() elif (
int
(
input_string1
) > 0 and int
(
input_string1
) < 4
): start_tower = input_string1 dest_tower = input_string2 input_done = 1 else
: print
(
"Please just enter the character 1 2 3 or 0 to quit \n\n"
)
Approaching the last part of the code Solving the ToH problem now needed the spare tower defined, given the start and end towers was needed. Since the order of which was the start and end matters, the if-else statement would require a permutation of (3,2) or 6 conditions to check to determine the spare or “other_tower” in my code. 3 of them would be the same, obviously. starting_tower = int
(
start_tower
) - 1 destination_tower = int
(
dest_tower
) - 1 other_tower = -
1 if starting_tower == 0 and destination_tower == 1
: other_tower = 2 elif starting_tower == 0 and destination_tower == 2
: other_tower = 1 elif starting_tower == 1 and destination_tower == 2
: other_tower = 0 elif starting_tower == 1 and destination_tower == 0
: other_tower = 2 elif starting_tower == 2 and destination_tower == 0
: othe_tower = 1 else
: other_tower = 0 I also subtracted 1 from each of the inputs from the user, since the Q- Matrix starts at 0 instead of 1. Once this was determined, all I had to do was go through the steps of the solution of the ToH problem with the MoveBlock command, using the 3 towers defined here. move_block
(
pub_command
, loop_rate
, starting_tower
, 2
, destination_tower
, 0
) move_block
(
pub_command
, loop_rate
, starting_tower
, 1
, other_tower
, 0
) move_block
(
pub_command
, loop_rate
, destination_tower
, 0
, other_tower
, 1
) move_block
(
pub_command
, loop_rate
, starting_tower
, 0
, destination_tower
, 0
) move_block
(
pub_command
, loop_rate
, other_tower
, 1
, starting_tower
, 0
) move_block
(
pub_command
, loop_rate
, other_tower
, 0
, destination_tower
, 1
) move_block
(
pub_command
, loop_rate
, starting_tower
, 0
, destination_tower
, 2
) This code now takes in the general case of towers and solves the ToH using the predefined towers variables inputted by the user.
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
Results and Real World Assessment The robot was successfully able to complete the ToH problem wherever the blocks spawned, the user inputted, or proceeded to the failsafe if inputted incorrectly. Figure 4 –
Gazebo Simulated UR3 Robot and Spawned Blocks in Q –
Matrix These result parameters are what was expected of the lab. Errors that could arise are if the user were to input the destination tower the same as the input towers. This would be an awkward situation where the algorithm would fail. Another fringe case
is if the user inputs a character that is unrecognizable to the program. This would render the program useless. To better this lab in the future, I would consider cases of larger numbers of cubes, using recursion to solve the ToH problem, and improving time efficiency of the robot movements using more optimal Bezier and Spline curves in 3D motion profiling. Error in the real world would be vastly different as well. The physics of suction, gravity, and even dust could cause positional errors to build up, resulting in the robot’s azimuth be off from the reports from the publisher in ROS from the internal encoders. Perhaps, a camera system that observes the output could be used in a sensor fusion to additional optimize the end effector’s performance. This error could be observed over time and perhaps a PID or PFD be implemented to result a larger time effectiveness with a larger max velocity allowed.
References Lynch, K., & Park, F. C. (2019). Modern robotics: Mechanics, planning, and control
. Cambridge, United Kingdom: Cambridge University Press. Program for Tower of Hanoi. (2021, January 08). Retrieved March 08, 2021, from https://www.geeksforgeeks.org/c-program-for-tower-of-hanoi/ Wiki. (n.d.). Retrieved March 08, 2021, from http://wiki.ros.org/Documentation
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
Appendix A Full Code for Project #!/usr/bin/env python ''' We get inspirations of Tower of Hanoi algorithm from the website below. This is also on the lab manual. Source: https://www.cut-the-knot.org/recurrence/hanoi.shtml ''' import os import argparse import copy import time import rospy import rospkg import numpy as np import yaml import sys from lab2_header import * # 20Hz SPIN_RATE = 20 # UR3 home location home = np
.
radians
([
120
, -
90
, 90
, -
90
, -
90
, 0
]) # UR3 current position, using home position for initialization current_position = copy
.
deepcopy
(
home
) thetas = [
0.0
, 0.0
, 0.0
, 0.0
, 0.0
, 0.0
] digital_in_0 = 1 analog_in_0 = 0 suction_on = True suction_off = False current_io_0 = False current_position_set = False Q = None ############## Your Code Start Here ############## """ TODO: define a ROS topic callback funtion for getting the state of suction cup Whenever ur3/gripper_input publishes info this callback function is called. """ def gripper_callback
(
msg
):
global digital_in_0 digital_in_0 = msg
.
DIGIN ############### Your Code End Here ############### """ Whenever ur3/position publishes info, this callback function is called. """ def position_callback
(
msg
): global thetas global current_position global current_position_set thetas
[
0
] = msg
.
position
[
0
] thetas
[
1
] = msg
.
position
[
1
] thetas
[
2
] = msg
.
position
[
2
] thetas
[
3
] = msg
.
position
[
3
] thetas
[
4
] = msg
.
position
[
4
] thetas
[
5
] = msg
.
position
[
5
] current_position
[
0
] = thetas
[
0
] current_position
[
1
] = thetas
[
1
] current_position
[
2
] = thetas
[
2
] current_position
[
3
] = thetas
[
3
] current_position
[
4
] = thetas
[
4
] current_position
[
5
] = thetas
[
5
] current_position_set = True def gripper
(
pub_cmd
, loop_rate
, io_0
): global SPIN_RATE global thetas global current_io_0 global current_position error = 0 spin_count = 0 at_goal = 0 current_io_0 = io_0 driver_msg = command
() driver_msg
.
destination = current_position driver_msg
.
v = 1.0 driver_msg
.
a = 1.0 driver_msg
.
io_0 = io_0 pub_cmd
.
publish
(
driver_msg
) while
(
at_goal == 0
): if
( abs
(
thetas
[
0
]-
driver_msg
.
destination
[
0
]) < 0.0005 and \ abs
(
thetas
[
1
]-
driver_msg
.
destination
[
1
]) < 0.0005 and \
abs
(
thetas
[
2
]-
driver_msg
.
destination
[
2
]) < 0.0005 and \ abs
(
thetas
[
3
]-
driver_msg
.
destination
[
3
]) < 0.0005 and \ abs
(
thetas
[
4
]-
driver_msg
.
destination
[
4
]) < 0.0005 and \ abs
(
thetas
[
5
]-
driver_msg
.
destination
[
5
]) < 0.0005 ): at_goal = 1 loop_rate
.
sleep
() if
(
spin_count > SPIN_RATE
*
5
): pub_cmd
.
publish
(
driver_msg
) rospy
.
loginfo
(
"Just published again driver_msg"
) spin_count = 0 spin_count = spin_count + 1 return error def move_arm
(
pub_cmd
, loop_rate
, dest
, vel
, accel
): global thetas global SPIN_RATE error = 0 spin_count = 0 at_goal = 0 driver_msg = command
() driver_msg
.
destination = dest driver_msg
.
v = vel driver_msg
.
a = accel driver_msg
.
io_0 = current_io_0 pub_cmd
.
publish
(
driver_msg
) loop_rate
.
sleep
() while
(
at_goal == 0
): if
( abs
(
thetas
[
0
]-
driver_msg
.
destination
[
0
]) < 0.0005 and \ abs
(
thetas
[
1
]-
driver_msg
.
destination
[
1
]) < 0.0005 and \ abs
(
thetas
[
2
]-
driver_msg
.
destination
[
2
]) < 0.0005 and \ abs
(
thetas
[
3
]-
driver_msg
.
destination
[
3
]) < 0.0005 and \ abs
(
thetas
[
4
]-
driver_msg
.
destination
[
4
]) < 0.0005 and \ abs
(
thetas
[
5
]-
driver_msg
.
destination
[
5
]) < 0.0005 ): at_goal = 1 #rospy.loginfo("Goal is reached!") loop_rate
.
sleep
() if
(
spin_count > SPIN_RATE
*
5
): pub_cmd
.
publish
(
driver_msg
) rospy
.
loginfo
(
"Just published again driver_msg"
) spin_count = 0
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
spin_count = spin_count + 1 return error ############## Your Code Start Here ############## def move_block
(
pub_cmd
, loop_rate
, start_loc
, start_height
, end_loc
, end_height
): global Q error = 0 ### Hint: Use the Q array to map out your towers by location and "height". move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
1
], 4.0
, 4.0
) gripper
(
pub_cmd
, loop_rate
, suction_on
) move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
0
], 1.0
, 4.0
) #at the location of bloc if digital_in_0 == 0
: gripper
(
pub_cmd
, loop_rate
, suction_off
) move_arm
(
pub_cmd
, loop_rate
, home
, 1.0
, 1.0
) print
(
'error with gripper'
) sys
.
exit
() move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
1
], 1.0
, 4.0
) move_arm
(
pub_cmd
, loop_rate
, Q
[
end_loc
][
end_height
][
1
], 4.0
, 4.0
) move_arm
(
pub_cmd
, loop_rate
, Q
[
end_loc
][
end_height
][
0
], 1.0
, 4.0
) gripper
(
pub_cmd
, loop_rate
, suction_off
) loop_rate
.
sleep
() move_arm
(
pub_cmd
, loop_rate
, Q
[
start_loc
][
start_height
][
1
], 4.0
, 4.0
) return error ############### Your Code End Here ############### def main
(): global home global Q global SPIN_RATE # Parser parser = argparse
.
ArgumentParser
(
description
=
'Please specify if using simulator or real robot'
) parser
.
add_argument
(
'--simulator'
, type
=
str
, default
=
'True'
) args = parser
.
parse_args
() # Definition of our tower # 2D layers (top view)
# Layer (Above blocks) # | Q[0][2][1] Q[1][2][1] Q[2][2][1] | Above third block # | Q[0][1][1] Q[1][1][1] Q[2][1][1] | Above point of second block # | Q[0][0][1] Q[1][0][1] Q[2][0][1] | Above point of bottom block # Layer (Gripping blocks) # | Q[0][2][0] Q[1][2][0] Q[2][2][0] | Contact point of third block # | Q[0][1][0] Q[1][1][0] Q[2][1][0] | Contact point of second block # | Q[0][0][0] Q[1][0][0] Q[2][0][0] | Contact point of bottom block # First index - From left to right position A, B, C # Second index - From "bottom" to "top" position 1, 2, 3 # Third index - From gripper contact point to "in the air" point # How the arm will move (Suggestions) # 1. Go to the "above (start) block" position from its base position # 2. Drop to the "contact (start) block" position # 3. Rise back to the "above (start) block" position # 4. Move to the destination "above (end) block" position # 5. Drop to the corresponding "contact (end) block" position # 6. Rise back to the "above (end) block" position # Initialize rospack rospack = rospkg
.
RosPack
() # Get path to yaml lab2_path = rospack
.
get_path
(
'lab2pkg_py'
) yamlpath = os
.
path
.
join
(
lab2_path
, 'scripts'
, 'lab2_data.yaml'
) with open
(
yamlpath
, 'r'
) as f
: try
: # Load the data as a dict data = yaml
.
load
(
f
) if args
.
simulator
.
lower
() == 'true'
: Q = data
[
'sim_pos'
] elif args
.
simulator
.
lower
() == 'false'
: Q = data
[
'real_pos'
] else
: print
(
"Invalid simulator argument, enter True or False"
) sys
.
exit
() except
: print
(
"YAML not found"
) sys
.
exit
() # Initialize ROS node rospy
.
init_node
(
'lab2node'
) # Initialize publisher for ur3/command with buffer size of 10 pub_command = rospy
.
Publisher
(
'ur3/command'
, command
, queue_size
=
10
) # Initialize subscriber to ur3/position and callback fuction # each time data is published sub_position = rospy
.
Subscriber
(
'ur3/position'
, position
, position_callback
) ############## Your Code Start Here ##############
# TODO: define a ROS subscriber for ur3/gripper_input message and corresponding callback function sub_suction = rospy
.
Subscriber
(
'ur3/gripper_input'
, gripper_input
, gripper_callback
) ############### Your Code End Here ############### ############## Your Code Start Here ############## # TODO: modify the code below so that program can get user input input_done = 0 start_tower = 0 dest_tower = 0 while
(
not input_done
): input_string1 = raw_input
(
"Enter The Start Tower"
) input_string2 = raw_input
(
"Enter The Destination Tower"
) print
(
"You entered " + input_string1 + 'for starting tower' + "\n" + "You entered " + input_string2 + 'for destination tower'
) if (
int
(
input_string1
) == 0 or int
(
input_string2
) == 0
): print
(
"Quitting... "
) sys
.
exit
() elif (
int
(
input_string1
) > 0 and int
(
input_string1
) < 4
): start_tower = input_string1 dest_tower = input_string2 input_done = 1 else
: print
(
"Please just enter the character 1 2 3 or 0 to quit \n\n"
) ############### Your Code End Here ############### # Check if ROS is ready for operation while
(
rospy
.
is_shutdown
()): print
(
"ROS is shutdown!"
) rospy
.
loginfo
(
"Sending Goals ..."
) loop_rate = rospy
.
Rate
(
SPIN_RATE
) ############## Your Code Start Here ############## # TODO: modify the code so that UR3 can move tower accordingly from user input starting_tower = int
(
start_tower
) - 1 destination_tower = int
(
dest_tower
) - 1 other_tower = -
1
Your preview ends here
Eager to read complete document? Join bartleby learn and gain access to the full version
- Access to all documents
- Unlimited textbook solutions
- 24/7 expert homework help
if starting_tower == 0 and destination_tower == 1
: other_tower = 2 elif starting_tower == 0 and destination_tower == 2
: other_tower = 1 elif starting_tower == 1 and destination_tower == 2
: other_tower = 0 elif starting_tower == 1 and destination_tower == 0
: other_tower = 2 elif starting_tower == 2 and destination_tower == 0
: othe_tower = 1 else
: other_tower = 0 move_block
(
pub_command
, loop_rate
, starting_tower
, 2
, destination_tower
, 0
) move_block
(
pub_command
, loop_rate
, starting_tower
, 1
, other_tower
, 0
) move_block
(
pub_command
, loop_rate
, destination_tower
, 0
, other_tower
, 1
) move_block
(
pub_command
, loop_rate
, starting_tower
, 0
, destination_tower
, 0
) move_block
(
pub_command
, loop_rate
, other_tower
, 1
, starting_tower
, 0
) move_block
(
pub_command
, loop_rate
, other_tower
, 0
, destination_tower
, 1
) move_block
(
pub_command
, loop_rate
, starting_tower
, 0
, destination_tower
, 2
) ############### Your Code End Here ############### if __name__ == '__main__'
: try
: main
() # When Ctrl+C is executed, it catches the exception except rospy
.
ROSInterruptException
: pass
Related Documents
Related Questions
Identify the lines
arrow_forward
Please help solve the question shown. I attempted this problem over five times and it keeps saying my answers are wrong. I typed 11.1hr, 1.11hr, 8.67hr, 6.9384hr, and 7.1152hr but it keeps saying that those are all incorrect. Can you please show how to get the correct answer so I can understand how to solve it? Thank you!
arrow_forward
I need help with the first part and Matlab for this problem
arrow_forward
You are a biomedical engineer working for a small orthopaedic firm that fabricates rectangular shaped fracture
fixation plates from titanium alloy (model = "Ti Fix-It") materials. A recent clinical report documents some problems with the plates
implanted into fractured limbs. Specifically, some plates have become permanently bent while patients are in rehab and doing partial
weight bearing activities.
Your boss asks you to review the technical report that was generated by the previous test engineer (whose job you now have!) and used to
verify the design. The brief report states the following... "Ti Fix-It plates were manufactured from Ti-6Al-4V (grade 5) and machined into
solid 150 mm long beams with a 4 mm thick and 15 mm wide cross section. Each Ti Fix-It plate was loaded in equilibrium in a 4-point bending
test (set-up configuration is provided in drawing below), with an applied load of 1000N. The maximum stress in this set-up was less than the
yield stress for the Ti-6Al-4V…
arrow_forward
Plz solve within 30min I vill give definitely upvote and vill give positive feedback thank you
arrow_forward
Hello tutors, help me. Just answer "Let Us Try"
arrow_forward
Don't Use Chat GPT Will Upvote And Give Handwritten Solution Please
arrow_forward
-The exam is open adopted textbook, open class notes (posted notes and solutions on the class' Canvas site only) and you may use
Matlab's build-in help system, but only to look up Matlab syntax questions;
- no collaboration is allowed; no help, including the tutoring center, may be sought to solve the problems;
- exam questions may only be asked to the instructor via private Ed Discussion posts or during the instructor's office hours;
- for non Matlab Grader problems, document all steps you took to solve the problem. This can be handwritten, but must be legible
for credit. If the problem states 'By hand', do not use any script/function to actually solve the problem, however, you may use a
non-programmable calculator or script/functions coded in this class to help in verifying the numerical results of individual steps;
- on Gradescope associate/select your answer pages with the corresponding problem numbers. Failure to do so may result in
no points given initially and will require a…
arrow_forward
Solve correctly
arrow_forward
Learning Goal:
To use transformation equations to calculate the plane state of stress in a rotated coordinate system.
The normal and shear stresses for a state of stress depend on the orientation of the axes. If the stresses are
given in one coordinate system (Figure 1), the equivalent stresses in a rotated coordinate system (Figure 2) can
be calculated using a set of transformation equations. Both sets of stresses describe the same state of stress.
In order to use the transformation equations, a sign convention must be chosen for the normal stresses, shear
stresses, and the rotation angle. For the equations below, a positive normal stress acts outward on a face. A
positive Try acts in the positive y-direction on the face whose outward normal is in the positive x-direction. The
positive direction for the rotation is also shown in the second figure.
The stresses in the rotated coordinate system are given by the following equations:
στ
σy
+
cos 20+Try sin 20
2
2
σετ συ
=
σy'
cos 20-Try…
arrow_forward
SEE MORE QUESTIONS
Recommended textbooks for you

Principles of Heat Transfer (Activate Learning wi...
Mechanical Engineering
ISBN:9781305387102
Author:Kreith, Frank; Manglik, Raj M.
Publisher:Cengage Learning
Related Questions
- Identify the linesarrow_forwardPlease help solve the question shown. I attempted this problem over five times and it keeps saying my answers are wrong. I typed 11.1hr, 1.11hr, 8.67hr, 6.9384hr, and 7.1152hr but it keeps saying that those are all incorrect. Can you please show how to get the correct answer so I can understand how to solve it? Thank you!arrow_forwardI need help with the first part and Matlab for this problemarrow_forward
- You are a biomedical engineer working for a small orthopaedic firm that fabricates rectangular shaped fracture fixation plates from titanium alloy (model = "Ti Fix-It") materials. A recent clinical report documents some problems with the plates implanted into fractured limbs. Specifically, some plates have become permanently bent while patients are in rehab and doing partial weight bearing activities. Your boss asks you to review the technical report that was generated by the previous test engineer (whose job you now have!) and used to verify the design. The brief report states the following... "Ti Fix-It plates were manufactured from Ti-6Al-4V (grade 5) and machined into solid 150 mm long beams with a 4 mm thick and 15 mm wide cross section. Each Ti Fix-It plate was loaded in equilibrium in a 4-point bending test (set-up configuration is provided in drawing below), with an applied load of 1000N. The maximum stress in this set-up was less than the yield stress for the Ti-6Al-4V…arrow_forwardPlz solve within 30min I vill give definitely upvote and vill give positive feedback thank youarrow_forwardHello tutors, help me. Just answer "Let Us Try"arrow_forward
- Don't Use Chat GPT Will Upvote And Give Handwritten Solution Pleasearrow_forward-The exam is open adopted textbook, open class notes (posted notes and solutions on the class' Canvas site only) and you may use Matlab's build-in help system, but only to look up Matlab syntax questions; - no collaboration is allowed; no help, including the tutoring center, may be sought to solve the problems; - exam questions may only be asked to the instructor via private Ed Discussion posts or during the instructor's office hours; - for non Matlab Grader problems, document all steps you took to solve the problem. This can be handwritten, but must be legible for credit. If the problem states 'By hand', do not use any script/function to actually solve the problem, however, you may use a non-programmable calculator or script/functions coded in this class to help in verifying the numerical results of individual steps; - on Gradescope associate/select your answer pages with the corresponding problem numbers. Failure to do so may result in no points given initially and will require a…arrow_forwardSolve correctlyarrow_forward
arrow_back_ios
arrow_forward_ios
Recommended textbooks for you
- Principles of Heat Transfer (Activate Learning wi...Mechanical EngineeringISBN:9781305387102Author:Kreith, Frank; Manglik, Raj M.Publisher:Cengage Learning

Principles of Heat Transfer (Activate Learning wi...
Mechanical Engineering
ISBN:9781305387102
Author:Kreith, Frank; Manglik, Raj M.
Publisher:Cengage Learning