Example #1
0
	def interaction_control(self, position_only = False, orientation_only = False, plane_horizontal = False,
		plane_vertical_xz = False, plane_vertical_yz = False, nullspace_only = False,
		position_x = False, position_y = False, position_z = False,
		orientation_x = False, orientation_y = False, orientation_z = False,
		constrained_axes = [1, 1, 1, 1, 1, 1], in_endpoint_frame = False, interaction_frame = [0, 0, 0, 1, 0, 0, 0], 
		K_nullspace = [10.0, 10.0, 7.0, 0.0, 0.0, 0.0, 0.0], rate = 10):

		try:
			rospy.Subscriber('zeroG_topic', String, self.zeroG_callback)
			self.zeroG = True
			rospy.sleep(0.5)

			if rate > 0:
				rate = rospy.Rate(rate)
			elif rate == 0:
				rospy.logwarn('Interaction control options will be set only once!')
			elif rate < 0:
				rospy.logerr('Invalid publish rate!')

			# set the interaction control options in the current configuration
			interaction_options = InteractionOptions()

			# if one of the options is set
			unconstrained_axes_default = [0, 0, 0, 0, 0, 0]
			unconstrained_axes = unconstrained_axes_default

			# create a list of the constrained zero G modes
			sum_mode_list = sum(bool2int([position_only, orientation_only, plane_horizontal, plane_vertical_xz, plane_vertical_yz, nullspace_only]))

			# create a list of the free axis options
			free_axis_list = bool2int([position_x, position_y, position_z, orientation_x, orientation_y, orientation_z])
			sum_free_axis_list = sum(free_axis_list)

			zero_stiffness_axes = boolToggle(constrained_axes)
			sum_zero_stiffness_axes = sum(zero_stiffness_axes)

			if (sum_mode_list==0 and sum_zero_stiffness_axes==0 and sum_free_axis_list==0):
				rospy.loginfo('Constrained in all directions')

			if (sum_mode_list>1 and sum_zero_stiffness_axes==0 and sum_free_axis_list==0):
				rospy.logerr('You can set only one of the options among "pos_only", "ori_only", "plane_hor", and "plane_ver"! The movement of endpoint will be constrained in all directions!')

			# give an error if the mode options as well as the individual axis options are set
			if (sum_mode_list==1 and sum_zero_stiffness_axes==0 and sum_free_axis_list>0):
				rospy.logerr('The individual axis options cannot be used together with the mode options! The movement of endpoint will be constrained in all directions!')

			# give an error when the axes are specified by more than one method
			if (sum_mode_list==0 and sum_zero_stiffness_axes>0 and sum_free_axis_list>0):
				rospy.logerr('You can only set the axes either by an array or individual options! The movement of endpoint will be constrained in all directions!')

			if (sum_mode_list==1 and sum_zero_stiffness_axes==0 and sum_free_axis_list>=0):
				if position_only:
					unconstrained_axes = [1, 1, 1, 0, 0, 0]
				if orientation_only:
					unconstrained_axes = [0, 0, 0, 1, 1, 1]
				if plane_horizontal:
					unconstrained_axes = [1, 1, 0, 0, 0, 0]
				if plane_vertical_xz:
					unconstrained_axes = [1, 0, 1, 0, 0, 0]
				if plane_vertical_yz:
					unconstrained_axes = [0, 1, 1, 0, 0, 0]
				if nullspace_only:
					unconstrained_axes = [0, 0, 0, 0, 0, 0]

			# if the axes are specified by an array
			if (sum_mode_list==0 and sum_zero_stiffness_axes>0 and sum_free_axis_list==0):
				unconstrained_axes = zero_stiffness_axes

			# if the axes are specified by individual options
			if (sum_mode_list==0 and sum_zero_stiffness_axes==0 and sum_free_axis_list>0):
				unconstrained_axes = free_axis_list

			# set the stiffness to zero by default
			interaction_options.set_K_impedance([0, 0, 0, 0, 0, 0])

			# set the axes with maximum stiffness
			interaction_options.set_max_impedance(boolToggle(int2bool(unconstrained_axes)))

			interaction_options.set_in_endpoint_frame(in_endpoint_frame)

			# set nullspace stiffness to zero if nullspace_only option is provided
			if nullspace_only:
				K_nullspace = [0, 0, 0, 0, 0, 0, 0]

			interaction_options.set_K_nullspace(K_nullspace)

			if len(interaction_frame) < 7:
				rospy.logerr('The number of elements must be 7!')
			elif len(interaction_frame) == 7:
				quat_sum_square = interaction_frame[3]*interaction_frame[3] + interaction_frame[4]*interaction_frame[4]
				+ interaction_frame[5]*interaction_frame[5] + interaction_frame[6]*interaction_frame[6]
				if quat_sum_square  < 1.0 + 1e-7 and quat_sum_square > 1.0 - 1e-7:
					interaction_frame_pose = Pose()
					interaction_frame_pose.position.x = interaction_frame[0]
					interaction_frame_pose.position.y = interaction_frame[1]
					interaction_frame_pose.position.z = interaction_frame[2]
					interaction_frame_pose.orientation.w = interaction_frame[3]
					interaction_frame_pose.orientation.x = interaction_frame[4]
					interaction_frame_pose.orientation.y = interaction_frame[5]
					interaction_frame_pose.orientation.z = interaction_frame[6]
					interaction_options.set_interaction_frame(interaction_frame_pose)
				else:
					rospy.logerr('Invalid input to quaternion! The quaternion must be a unit quaternion!')
			else:
				rospy.logerr('Invalid input to interaction_frame!')

			# always enable the rotations for constrained zero-G
			interaction_options.set_rotations_for_constrained_zeroG(True)

			msg = interaction_options.to_msg()

			# print the resultant interaction options once
			#rospy.loginfo(msg)
			self.icc_pub.publish(msg)

			rs = intera_interface.RobotEnable(CHECK_VERSION)

		except rospy.ROSInterruptException:
			rospy.logerr('Keyboard interrupt detected from the user. %s',
						 'Exiting the node...')

		if not rs.state().enabled:
			self.position_mode()
Example #2
0
def main():
    """
    Initiate constrained zero-G with a desired behavior from the current pose.
    The desired behavior can be specified by the optional arguments. By default,
    all directions will be set unconstrained when no options are provided.
    Note that the arm is not commanded to move but it will have the specified
    interaction control behavior.

    If publish the rate is 0, the interaction control command is only published
    once; otherwise a last position command will be sent when the script exits.
    For non-zero publishing rates, the arm will go back into constrained zero-G
    if the arm's zero-g button is pressed and relased. Future motion commands
    will use the interaction parameters set in the trajectory options.

    Call using:
    $ rosrun intera_examples constrained_zeroG.py  [arguments: see below]

    -p
    --> Allow for arbitrary endpoint position with fixed orientation

    -o
    --> Allow for arbitrary endpoint orientation with fixed position

    -ph
    --> Allow for arbitrary endpoint position on a horizontal plane (XY plane) with fixed orientation

    -yz
    --> Allow for arbitrary endpoint position on a vertical YZ plane with fixed orientation

    -px
    --> Allow for arbitrary endpoint position along x-axis

    -px -oy
    --> Allow for arbitrary endpoint position along x-axis as well as arbitrary endpoint orientation about y-axis

    -ca 1 1 0 1 1 1
    --> Allow for arbitrary translational movement along z-axis only

    -ca 1 1 1 0 1 1
    --> Allow for arbitrary rotational movement about x-axis only

    -fr 0.1 0.2 0.3 1 0 0 0
    --> Set the pose of the interaction_frame -- position: (0.1, 0.2, 0.3) and orientation (1, 0, 0, 0)

    -ef
    --> Set in_endpoint_frame to True in the current configuration (use TCP frame as reference frame)

    -kn 5.0 3.0 5.0 4.0 6.0 4.0 6.0
    --> Set K_nullspace to [5.0 3.0 5.0 4.0 6.0 4.0 6.0] in the current configuration

    -kn 0.0
    --> Set K_nullspace to [0 0 0 0 0 0 0] in the current configuration

    -r 20
    --> Set desired publish rate (Hz)

    -r 0
    --> The interaction command is published once and exits. The arm can remain
        in interaction control after this script.
    """

    arg_fmt = argparse.RawDescriptionHelpFormatter
    parser = argparse.ArgumentParser(formatter_class=arg_fmt,
                                     description=main.__doc__)
    parser.add_argument(
        "-p",
        "--position_only",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint position with fixed orientation")
    parser.add_argument(
        "-o",
        "--orientation_only",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint orientation with fixed position")
    parser.add_argument(
        "-ph",
        "--plane_horizontal",
        action='store_true',
        default=False,
        help=
        "Allow for arbitrary endpoint position on a horizontal plane (XY plane) with fixed orientation"
    )
    parser.add_argument(
        "-xz",
        "--plane_vertical_xz",
        action='store_true',
        default=False,
        help=
        "Allow for arbitrary endpoint position on a vertical plane (XZ plane) with fixed orientation"
    )
    parser.add_argument(
        "-yz",
        "--plane_vertical_yz",
        action='store_true',
        default=False,
        help=
        "Allow for arbitrary endpoint position on a vertical plane (YZ plane) with fixed orientation"
    )
    parser.add_argument(
        "-ns",
        "--nullspace_only",
        action='store_true',
        default=False,
        help=
        "Allow for arbitrary movement only in the nullspace of the configuration with fixed endpoint pose"
    )
    parser.add_argument(
        "-px",
        "--position_x",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint position along x-axis")
    parser.add_argument(
        "-py",
        "--position_y",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint position along y-axis")
    parser.add_argument(
        "-pz",
        "--position_z",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint position along z-axis")
    parser.add_argument(
        "-ox",
        "--orientation_x",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint orientation about x-axis")
    parser.add_argument(
        "-oy",
        "--orientation_y",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint orientation about y-axis")
    parser.add_argument(
        "-oz",
        "--orientation_z",
        action='store_true',
        default=False,
        help="Allow for arbitrary endpoint orientation about z-axis")
    parser.add_argument(
        "-ca",
        "--constrained_axes",
        type=int,
        nargs=6,
        default=[1, 1, 1, 1, 1, 1],
        choices=[0, 1],
        help=
        "A list of Cartesian axes with maximum stiffness, 0 (zero stiffness) or 1 (maximum stiffness) for each of the 6 directions (3 translational directions followed by 3 rotational directions)"
    )
    parser.add_argument(
        "-ef",
        "--in_endpoint_frame",
        action='store_true',
        default=False,
        help=
        "Set the desired reference frame to endpoint frame ('right_hand'); otherwise, it is base frame by default"
    )
    parser.add_argument(
        "-fr",
        "--interaction_frame",
        type=float,
        nargs='+',
        default=[0, 0, 0, 1, 0, 0, 0],
        help=
        "Specify the reference frame for the interaction controller -- first 3 values are positions [m] and last 4 values are orientation in quaternion (w, x, y, z) which has to be normalized values"
    )
    parser.add_argument(
        "-kn",
        "--K_nullspace",
        type=float,
        nargs='+',
        default=[10.0, 10.0, 7.0, 0.0, 0.0, 0.0, 0.0],
        help=
        "A list of desired nullspace stiffnesses, one for each of the 7 joints (a single value can be provided to apply the same value to all the directions) -- units are in (Nm/rad)"
    )
    parser.add_argument(
        "-r",
        "--rate",
        type=int,
        default=10,
        help=
        "A desired publish rate for updating interaction control commands (10Hz by default) -- a rate 0 publish once and exits which can cause the arm to remain in interaction control."
    )

    args = parser.parse_args(rospy.myargv()[1:])
    rospy.init_node('constrained_zeroG')

    # set the interaction control options in the current configuration
    interaction_options = InteractionOptions()

    # if one of the options is set
    unconstrained_axes_default = [0, 0, 0, 0, 0, 0]
    unconstrained_axes = unconstrained_axes_default

    # create a list of the constrained zero G modes
    sum_mode_list = sum(
        bool2int([
            args.position_only, args.orientation_only, args.plane_horizontal,
            args.plane_vertical_xz, args.plane_vertical_yz, args.nullspace_only
        ]))

    # create a list of the free axis options
    free_axis_list = bool2int([
        args.position_x, args.position_y, args.position_z, args.orientation_x,
        args.orientation_y, args.orientation_z
    ])
    sum_free_axis_list = sum(free_axis_list)

    zero_stiffness_axes = boolToggle(args.constrained_axes)
    sum_zero_stiffness_axes = sum(zero_stiffness_axes)

    if (sum_mode_list == 0 and sum_zero_stiffness_axes == 0
            and sum_free_axis_list == 0):
        rospy.logerr('You need to either set one of the options or specify the ' \
                     'desired axes of arbitrary movement!')
        rospy.logerr(
            'The movement of endpoint will be constrained in all directions!')

    if (sum_mode_list > 1 and sum_zero_stiffness_axes == 0
            and sum_free_axis_list == 0):
        rospy.logerr('You can set only one of the options among "pos_only", "ori_only", ' \
                     '"plane_hor", and "plane_ver"!')
        rospy.logerr(
            'The movement of endpoint will be constrained in all directions!')

    # give an error if the mode options as well as the individual axis options are set
    if (sum_mode_list == 1 and sum_zero_stiffness_axes == 0
            and sum_free_axis_list > 0):
        rospy.logerr(
            'The individual axis options cannot be used together with the mode options!'
        )
        rospy.logerr(
            'The movement of endpoint will be constrained in all directions!')

    # give an error when the axes are specified by more than one method
    if (sum_mode_list == 0 and sum_zero_stiffness_axes > 0
            and sum_free_axis_list > 0):
        rospy.logerr(
            'You can only set the axes either by an array or individual options!'
        )
        rospy.logerr(
            'The movement of endpoint will be constrained in all directions!')

    if (sum_mode_list == 1 and sum_zero_stiffness_axes == 0
            and sum_free_axis_list >= 0):
        if args.position_only:
            unconstrained_axes = [1, 1, 1, 0, 0, 0]
        if args.orientation_only:
            unconstrained_axes = [0, 0, 0, 1, 1, 1]
        if args.plane_horizontal:
            unconstrained_axes = [1, 1, 0, 0, 0, 0]
        if args.plane_vertical_xz:
            unconstrained_axes = [1, 0, 1, 0, 0, 0]
        if args.plane_vertical_yz:
            unconstrained_axes = [0, 1, 1, 0, 0, 0]
        if args.nullspace_only:
            unconstrained_axes = [0, 0, 0, 0, 0, 0]

    # if the axes are specified by an array
    if (sum_mode_list == 0 and sum_zero_stiffness_axes > 0
            and sum_free_axis_list == 0):
        unconstrained_axes = zero_stiffness_axes

    # if the axes are specified by individual options
    if (sum_mode_list == 0 and sum_zero_stiffness_axes == 0
            and sum_free_axis_list > 0):
        unconstrained_axes = free_axis_list

    # set the stiffness to zero by default
    interaction_options.set_K_impedance([0, 0, 0, 0, 0, 0])

    # set the axes with maximum stiffness
    interaction_options.set_max_impedance(
        boolToggle(int2bool(unconstrained_axes)))

    interaction_options.set_in_endpoint_frame(args.in_endpoint_frame)

    # set nullspace stiffness to zero if nullspace_only option is provided
    if args.nullspace_only:
        K_nullspace = [0, 0, 0, 0, 0, 0, 0]
    else:
        K_nullspace = args.K_nullspace

    interaction_options.set_K_nullspace(K_nullspace)

    if len(args.interaction_frame) == 7:
        interaction_frame = Pose()
        interaction_frame.position.x = args.interaction_frame[0]
        interaction_frame.position.y = args.interaction_frame[1]
        interaction_frame.position.z = args.interaction_frame[2]
        interaction_frame.orientation.w = args.interaction_frame[3]
        interaction_frame.orientation.x = args.interaction_frame[4]
        interaction_frame.orientation.y = args.interaction_frame[5]
        interaction_frame.orientation.z = args.interaction_frame[6]
        interaction_options.set_interaction_frame(interaction_frame)
    else:
        rospy.logerr('Invalid input to interaction_frame. Must be 7 elements.')

    # always enable the rotations for constrained zero-G
    interaction_options.set_rotations_for_constrained_zeroG(True)

    # print the resultant interaction options once
    rospy.loginfo(interaction_options.to_msg())

    ic_pub = InteractionPublisher()
    rospy.sleep(0.5)
    if args.rate != 0:
        rospy.on_shutdown(ic_pub.send_position_mode_cmd)
    ic_pub.send_command(interaction_options, args.rate)
    if args.rate == 0:
        rospy.sleep(0.5)
Example #3
0
def main():
    """
    Initiate constrained zero-G with a desired behavior from the current pose.
    The desired behavior can be specified by the optional arguments. By default,
    all directions will be set unconstrained when no options are provided.
    Note that the arm is not commanded to move but it will have the specified
    interaction control behavior. If publish rate is 0 where the interaction
    control command is only published once, after entering and exiting regular
    zero-G, the arm will return to normal position mode. Also, regardless of
    the publish rate, the regular zero-G behavior will not be affected by this.

    Call using:
    $ rosrun intera_examples constrained_zeroG.py  [arguments: see below]

    -p
    --> Allow for arbitrary endpoint position with fixed orientation

    -o
    --> Allow for arbitrary endpoint orientation with fixed position

    -ph
    --> Allow for arbitrary endpoint position on a horizontal plane (XY plane) with fixed orientation

    -yz
    --> Allow for arbitrary endpoint position on a vertical YZ plane with fixed orientation

    -px
    --> Allow for arbitrary endpoint position along x-axis

    -px -oy
    --> Allow for arbitrary endpoint position along x-axis as well as arbitrary endpoint orientation about y-axis

    -ca 1 1 0 1 1 1
    --> Allow for arbitrary translational movement along z-axis only

    -ca 1 1 1 0 1 1
    --> Allow for arbitrary rotational movement about x-axis only

    -fr 0.1 0.2 0.3 1 0 0 0
    --> Set the pose of the interaction_frame -- position: (0.1, 0.2, 0.3) and orientation (1, 0, 0, 0)

    -ef
    --> Set in_endpoint_frame to True in the current configuration (use TCP frame as reference frame)

    -kn 5.0 3.0 5.0 4.0 6.0 4.0 6.0
    --> Set K_nullspace to [5.0 3.0 5.0 4.0 6.0 4.0 6.0] in the current configuration

    -kn 0.0
    --> Set K_nullspace to [0 0 0 0 0 0 0] in the current configuration

    -r 20
    --> Set desired publish rate (Hz)
    """

    arg_fmt = argparse.RawDescriptionHelpFormatter
    parser = argparse.ArgumentParser(formatter_class=arg_fmt,
                                     description=main.__doc__)
    parser.add_argument(
        "-p",  "--position_only", action='store_true', default=False,
        help="Allow for arbitrary endpoint position with fixed orientation")
    parser.add_argument(
        "-o",  "--orientation_only", action='store_true', default=False,
        help="Allow for arbitrary endpoint orientation with fixed position")
    parser.add_argument(
        "-ph",  "--plane_horizontal", action='store_true', default=False,
        help="Allow for arbitrary endpoint position on a horizontal plane (XY plane) with fixed orientation")
    parser.add_argument(
        "-xz",  "--plane_vertical_xz", action='store_true', default=False,
        help="Allow for arbitrary endpoint position on a vertical plane (XZ plane) with fixed orientation")
    parser.add_argument(
        "-yz",  "--plane_vertical_yz", action='store_true', default=False,
        help="Allow for arbitrary endpoint position on a vertical plane (YZ plane) with fixed orientation")
    parser.add_argument(
        "-ns",  "--nullspace_only", action='store_true', default=False,
        help="Allow for arbitrary movement only in the nullspace of the configuration with fixed endpoint pose")
    parser.add_argument(
        "-px",  "--position_x", action='store_true', default=False,
        help="Allow for arbitrary endpoint position along x-axis")
    parser.add_argument(
        "-py",  "--position_y", action='store_true', default=False,
        help="Allow for arbitrary endpoint position along y-axis")
    parser.add_argument(
        "-pz",  "--position_z", action='store_true', default=False,
        help="Allow for arbitrary endpoint position along z-axis")
    parser.add_argument(
        "-ox",  "--orientation_x", action='store_true', default=False,
        help="Allow for arbitrary endpoint orientation about x-axis")
    parser.add_argument(
        "-oy",  "--orientation_y", action='store_true', default=False,
        help="Allow for arbitrary endpoint orientation about y-axis")
    parser.add_argument(
        "-oz",  "--orientation_z", action='store_true', default=False,
        help="Allow for arbitrary endpoint orientation about z-axis")
    parser.add_argument(
        "-ca", "--constrained_axes", type=int,
        nargs=6, default=[1, 1, 1, 1, 1, 1], choices = [0, 1],
        help="A list of Cartesian axes with maximum stiffness, 0 (zero stiffness) or 1 (maximum stiffness) for each of the 6 directions (3 translational directions followed by 3 rotational directions)")
    parser.add_argument(
        "-ef",  "--in_endpoint_frame", action='store_true', default=False,
        help="Set the desired reference frame to endpoint frame ('right_hand'); otherwise, it is base frame by default")
    parser.add_argument(
        "-fr", "--interaction_frame", type=float,
        nargs='+', default=[0, 0, 0, 1, 0, 0, 0],
        help="Specify the reference frame for the interaction controller -- first 3 values are positions [m] and last 4 values are orientation in quaternion (w, x, y, z) which has to be normalized values")
    parser.add_argument(
        "-kn", "--K_nullspace", type=float,
        nargs='+', default=[10.0, 10.0, 7.0, 0.0, 0.0, 0.0, 0.0],
        help="A list of desired nullspace stiffnesses, one for each of the 7 joints (a single value can be provided to apply the same value to all the directions) -- units are in (Nm/rad)")
    parser.add_argument(
        "-r",  "--rate", type=int, default=10,
        help="A desired publish rate for updating interaction control commands (10Hz by default) -- 0 if we want to publish it only once")
    args = parser.parse_args(rospy.myargv()[1:])

    try:
        rospy.init_node('set_interaction_options_py')
        pub = rospy.Publisher('/robot/limb/right/interaction_control_command', InteractionControlCommand, queue_size = 1)
        rospy.sleep(0.5)

        if args.rate > 0:
            rate = rospy.Rate(args.rate)
        elif args.rate == 0:
            rospy.logwarn('Interaction control options will be set only once!')
        elif args.rate < 0:
            rospy.logerr('Invalid publish rate!')

        # set the interaction control options in the current configuration
        interaction_options = InteractionOptions()

        # if one of the options is set
        unconstrained_axes_default = [0, 0, 0, 0, 0, 0]
        unconstrained_axes = unconstrained_axes_default

        # create a list of the constrained zero G modes
        sum_mode_list = sum(bool2int([args.position_only, args.orientation_only, args.plane_horizontal, args.plane_vertical_xz, args.plane_vertical_yz, args.nullspace_only]))

        # create a list of the free axis options
        free_axis_list = bool2int([args.position_x, args.position_y, args.position_z, args.orientation_x, args.orientation_y, args.orientation_z])
        sum_free_axis_list = sum(free_axis_list)

        zero_stiffness_axes = boolToggle(args.constrained_axes)
        sum_zero_stiffness_axes = sum(zero_stiffness_axes)

        if (sum_mode_list==0 and sum_zero_stiffness_axes==0 and sum_free_axis_list==0):
            rospy.logerr('You need to either set one of the options or specify the desired axes of arbitrary movement! The movement of endpoint will be constrained in all directions!')

        if (sum_mode_list>1 and sum_zero_stiffness_axes==0 and sum_free_axis_list==0):
            rospy.logerr('You can set only one of the options among "pos_only", "ori_only", "plane_hor", and "plane_ver"! The movement of endpoint will be constrained in all directions!')

        # give an error if the mode options as well as the individual axis options are set
        if (sum_mode_list==1 and sum_zero_stiffness_axes==0 and sum_free_axis_list>0):
            rospy.logerr('The individual axis options cannot be used together with the mode options! The movement of endpoint will be constrained in all directions!')

        # give an error when the axes are specified by more than one method
        if (sum_mode_list==0 and sum_zero_stiffness_axes>0 and sum_free_axis_list>0):
            rospy.logerr('You can only set the axes either by an array or individual options! The movement of endpoint will be constrained in all directions!')

        if (sum_mode_list==1 and sum_zero_stiffness_axes==0 and sum_free_axis_list>=0):
            if args.position_only:
                unconstrained_axes = [1, 1, 1, 0, 0, 0]
            if args.orientation_only:
                unconstrained_axes = [0, 0, 0, 1, 1, 1]
            if args.plane_horizontal:
                unconstrained_axes = [1, 1, 0, 0, 0, 0]
            if args.plane_vertical_xz:
                unconstrained_axes = [1, 0, 1, 0, 0, 0]
            if args.plane_vertical_yz:
                unconstrained_axes = [0, 1, 1, 0, 0, 0]
            if args.nullspace_only:
                unconstrained_axes = [0, 0, 0, 0, 0, 0]

        # if the axes are specified by an array
        if (sum_mode_list==0 and sum_zero_stiffness_axes>0 and sum_free_axis_list==0):
            unconstrained_axes = zero_stiffness_axes

        # if the axes are specified by individual options
        if (sum_mode_list==0 and sum_zero_stiffness_axes==0 and sum_free_axis_list>0):
            unconstrained_axes = free_axis_list

        # set the stiffness to zero by default
        interaction_options.set_K_impedance([0, 0, 0, 0, 0, 0])

        # set the axes with maximum stiffness
        interaction_options.set_max_impedance(boolToggle(int2bool(unconstrained_axes)))

        interaction_options.set_in_endpoint_frame(args.in_endpoint_frame)

        # set nullspace stiffness to zero if nullspace_only option is provided
        if args.nullspace_only:
            K_nullspace = [0, 0, 0, 0, 0, 0, 0]
        else:
            K_nullspace = args.K_nullspace

        interaction_options.set_K_nullspace(K_nullspace)

        if len(args.interaction_frame) < 7:
            rospy.logerr('The number of elements must be 7!')
        elif len(args.interaction_frame) == 7:
            quat_sum_square = args.interaction_frame[3]*args.interaction_frame[3] + args.interaction_frame[4]*args.interaction_frame[4]
            + args.interaction_frame[5]*args.interaction_frame[5] + args.interaction_frame[6]*args.interaction_frame[6]
            if quat_sum_square  < 1.0 + 1e-7 and quat_sum_square > 1.0 - 1e-7:
                interaction_frame = Pose()
                interaction_frame.position.x = args.interaction_frame[0]
                interaction_frame.position.y = args.interaction_frame[1]
                interaction_frame.position.z = args.interaction_frame[2]
                interaction_frame.orientation.w = args.interaction_frame[3]
                interaction_frame.orientation.x = args.interaction_frame[4]
                interaction_frame.orientation.y = args.interaction_frame[5]
                interaction_frame.orientation.z = args.interaction_frame[6]
                interaction_options.set_interaction_frame(interaction_frame)
            else:
                rospy.logerr('Invalid input to quaternion! The quaternion must be a unit quaternion!')
        else:
            rospy.logerr('Invalid input to interaction_frame!')

        # always enable the rotations for constrained zero-G
        interaction_options.set_rotations_for_constrained_zeroG(True)

        msg = interaction_options.to_msg()

        # print the resultant interaction options once
        rospy.loginfo(msg)
        pub.publish(msg)

        rs = intera_interface.RobotEnable(CHECK_VERSION)
        if args.rate > 0:
            while not rospy.is_shutdown() and rs.state().enabled:
                rate.sleep()
                pub.publish(msg)

    except rospy.ROSInterruptException:
        rospy.logerr('Keyboard interrupt detected from the user. %s',
                     'Exiting the node...')

    if not rs.state().enabled:
        # send a message to put the robot back into position mode
        position_mode = InteractionOptions()
        position_mode.set_interaction_control_active(False)
        pub.publish(position_mode.to_msg())
        rospy.sleep(0.5)