Posts by Seulki

    I'd suggest you using jointTorqueCondition rather than ForceCondition when it's small amount of force/torque you want to detect.

    The noise(not referring sound noise. fluctuation of values) is mainly caused by motions and innate tolerance of torque sensors, which may be eased down when we shrink the number of sensors we use.

    Track the major axis on your approaching motion(I guess it should be #4 or #2 since your motion seems to be toward -Z) and try use jointTorqueCondition for the axis.


    Further and more accurate solution will be using secondary condition with your force/torque condition.

    Commonly force/torque and positions are two major figures we can monitor from a manipulator.

    If you can make your own listener/thread to check the CartesianPosition(keep it focused on Z) of the manipulator as the approaching motion is being delivered as well as your force/torque condition, you will be able to check in combination of conditions such as 'force/torque detected && position merely changed comparing to last few values' which will make your logic more satisfactory.

    Hi, I do not know where you get the code but as you said, it needs a LEDIOGroup class which you do not have now.
    I do not know about LEDIOGroup, but you already have setLEDBlue() method under MediaFlangeIOGroup class.


    green and red LEDs are not mapped by default, and I think that was the reason why someone-who coded the example that you got- made LEDIOGroup class to have them.



    * You need to have MF Touch pneumatic/electric type of flange and select it when you made a Sunrise project to have those LED methods inside of MediaFlangeIOGroup.

    I highly doubt that you may have chosen a wrong type of Robot or a media flange conflicting to the actual manipulator.
    You might want to check the setting of current project installed on the controller comparing to the one on the workbench.
    SmartPAD-System-Information (Robot model, Media Flange type and OS version)


    Plus, if it is MF pneumatic you actually have, since this type of MF has no ditigal I/Os it is normal to have non of generated files.


    If it's first time you do this, maybe it will be easier to get a project from the controller first-which is already well defined- and start based on it.

    Hi, sorry for a silly question, but have you called a stopRecording() method at the end?
    I guess the log file creation should be done inside of this method which means you won't get any unless you call it.

    If the weight value is not that critical as you said, I guess the code below will do the job for you. Or a clue at least.


    Code
    double forceZ = - ( lbr.getExternalForceTorque( tcp, World.Current.getRootFrame() ).getForce().getZ() );
    double weight = forceZ / 9.8;


    * You can get gravity directional force with the first line no matter how your tcp is oriented.
    * 1N = 9.8kgf as far as I know.

    X2 on LBR iiwa MediaFlange is using EtherCAT interface.
    Coupled inside to go to the controller with X650-651 cable.
    If you wish to use this interface, first your device has to provide EtherCAT interface and LBR be compatible with it.
    If so, you can get device description file (.xml) from the device provider and map them with KUKA Workvisual.
    Mapping is quite well explained on your KUKA_SunriseOS_version_SI_lang manual.


    If you want to modify a frame relative to the closest parent (which most of the time is what is preferred) then you have to get or create the parent also so you can transform from the parents coordinate system.


    I'm not really sure if I understood what you mean either. I was thinking about the opposite situation. 'If I want to modify a frame relative to other frames than its parent'
    What I was suggesting is that it might be better to use transformation() method instead of setX/Y/Z/A/B/C() methods.
    using set...() has only capability to transform itself with referring to it's own(parent's) orientation.
    while transformation() has capability to take other frame as its orientation reference.
    -> You can't 'simply; yes it's still possible with setParent()' modify your frame to be placed 50mm upward from its ground(World +z) when its parent is not having an aligned orientation to the world.

    Code
    // to transform 'corner1' 50mm regarding canvas Z+
    corner1.transform( canvas, Transformation.ofTranslation( 0, 0, 50 ) );
    // or
    AbstractFrame formerParent = corner1.getParent();
    corner1.setParent( canvas, true );
    corner1.setZ( corner1.getZ() + 50  );
    corner1.setParent( formerParent, true );


    Of course we can simply use set...() methods when a reference frame is not needed. But in that case as well, I'd personally prefer use transformation().
    With respect, enlighten me if I'm trapped in my way. :smiling_face:

    Hi guys,


    Think it might be a very late answer, but anyways by the brief look of your code, the error you're having might still be caused by initializing issue,

    Code
    Frame canvas = new Frame();
    Frame playGround = new Frame(canvas);
    this.canvas = getApplicationData().getFrame("/canvas").copy();
    Frame point1 = playGround;


    Your former code above,
    doing it in this sequence will never give you desired values to your 'playGround' and 'point1' variables.
    because you passed an instance of canvas to playGround before it actually have some values. -> java is pass by value not pass by reference
    And this is why we are not suggested to initialize field variables(class variables) at the same time we declare it.
    simply, it should be like this,

    Code
    // field variables
    Frame canvas;
    Frame playGround;
    public void initialize() {
    	this.canvas = getApplicationData().getFrame("/canvas").copyWithRedundancy();
    	// I highly recommend you to use copyWithRedundancy() insteady of copy(). Former one copies transformation including redundancy information while later one only copies transformation.
    	playGround = new Frame(canvas);
    }


    I do not know how you fixed it, but if you're seeing the error message saying 'cannot map the command...',
    your target frame is not having a path from the only genuine static frame that is World.
    By the code 'new Frame(AbstractFrame parent)', the frame should have path to the parent frame unless your parent itself is also not having a correct path to World.
    I'm just saying because this is the reason for your former code, and I do not know your revised code.


    Just in case, for you to patch it up, .setParent(canvas) right before you modify transformation values might be a way also.


    And few more tips you might want to know,
    1. Use ObjectFrame for taught frames(points you actually taught), and use Frame for the ones you made in a program.
    2. Use .copyWithRedundancy() to convert your ObjectFrame to a Frame.
    3. Using setX/setY/setZ... will change your frame's value only relatively to the frame itself(which is relative to its parent's transformation/orientation) which means every frames must be set as a child of a frame which you want to use as a base; in your case I think it's Canvas.
    When it comes that you need to transform your frame relatively to other frame or to World frame, refer to the code below instead,

    Code
    point1.transform( World.Current.getRootFrame(), Transformation.ofTranslation( x, y, z ) )
      // point1 will be transformed x/y/z relative to World


    4. Try use arrays(if the number is set) or List(if the number varies) to make your code compact and iterable.

    Hi,
    Once an axis has hit its limit, you might need to master it again.
    Jogging in World/Tool/Base may not work even with KRF, while jogging in Axis will be still working.
    -> because robot can not do its kinematic calculation when one of its axis value is not exact.

    Hi, there was something I tried before, though I can't remember if it worked or not.
    make a static ITaskLogger variable and initialize it on your RoboticsAPIApplication.


    Code
    public static ITaskLogger Logger;
    initialize() {
        this.Logger = getLogger();
    }


    and simply use it on your backgroundTask

    Code
    ITaskLogger logger;
    run() {
        logger = YourApplication.Logger;
    }


    Of course you need to use try-catch or whatever way to prevent your backgroundTask to be jammed when YourApplication's Logger is not yet initialized.
    It will only log when YourApplication is initialized, otherwise it won't.

    I think the reason why someone said 'there's no point of modifying bases' is because
    you do not have to actually change its values.
    Just use transform() in your application without changing the ObjectFrame itself.
    -> Unlike actually changing the base transformation values, -as far as I remember- using transform() method does no effect to its child frames since you are gonna only be able to modify a snapshot(Frame) of an actual base(ObjectFrame). So you might be wanting to look at setParent(newParent, true) method as well for your child frames to be affected.

    One thing to make it clearer,


    KUKA Controller>
    X65(Kuka Extension Bus) : EtherCAT
    X66(Kuka Line Interface) : EtherNet


    PC : EtherNet
    PLC : digital I/O (depends on which interface module to use)


    The reason of using EtherCAT modules like EK1100 is to make a bridge between two different interfaces.
    The easiest sample is to use EK1100+EL1809+EL2809(coupler, pnp input 16, pnp output 16)
    So the connection diagram will be like [KUKA] --(EtherCAT)-- [EK1100/EL..] --(Digital I/O)-- [PLC]
    If you want to change 'digital I/O' part with other interfaces, just assemble a module accordingly, and set it up with WorkVisual.


    You probably used X66 for PC-KUKA socket communication. This time EK1100 module should be connected to X65 using EtherCAT interface.

    Just for your information,
    Motion gets parameter when it starts, and you can't change it in realtime once it is taken into runtime.
    Meaning you need to finish at least one motion to get your changed value effective.


    if you got a loop on your motions, I think you can simplify your code with NullReference's code. Just like refreshing on Windows UI.


    Or, since your background will never stop using resources which is also being accessed by your own application,
    instead, it might be better for you to do the same on a thread inside of your application only while the application is running. Interrupt it on dispose().

    Quote

    AFAIK there's no way to modify frames in the xml file with KUKAs API.


    I guess this is away of the point, but actually, there is.

    Code
    IPersistenceEngine engine = RoboticsAPIApplication.getContext().getEngine(IPersistenceEngine.class);  // RoboticsAPIApplication should be 'this' if you use it in your RoboticsAPIApplication class.
    XmlApplicationDataSource defaultDataSource = (XmlApplicationDataSource) engine.getDefaultDataSource();


    This defaultDataSource is the class of XML file itself.
    you can addFrame, removeFrame, renameFrame, changeFrameTransformation, and manipulate other almost every parameters.


    But yes, it is still tedious to use. You might be in a need of making another class for manipulating this dataSource.

    Hey,


    I've never tried, but I just found something and it might be a suitable solution for you.


    Code
    CartesianImpedanceControlMode cicm = new CartesianImpedanceControlMode();
    JointStopCondition jSc = new JointStopCondition( lBR_iiwa_14_R820_1 );
    jSc.validIfBetween( 1, Math.toRadians(-130), Math.toRadians(130) ).validIfBetween( 2, Math.toRadians(-90), Math.toRadians(90) )/*...*/;
    // if the code above does not work, you need to use ICondition and group all the separate conditions for each axis with or().
    
    
    IMotionContainer mc = lBR_iiwa_14_R820_1.moveAsync( positionHold( cicm, -1, TimeUnit.MILLISECONDS ).breakWhen( jSc ) );
    if ( mc.hasFired( jSc ) ) {
    } else {
    }

    Just in case this might help you out,


    Most of the time that I've experienced the same error, was caused by unstable connection through KLI.
    If you try your RJ45 connector on KLI in and out for few times, you will see that error.
    - I am quite sure it should be categorized as a "bug", anyhow it has been there since Sunrise.OS 1.3, the first version I've worked with.
    So, unless you are getting this error by manually doing what I've described, there might be some cases as below I guess.


    1. Somethings wrong with your background task or especially -if any- network program as NullReference has referred.


    Check your program for anything that you do continuously, also check background tasks. Remove some code and try again until you isolate the class and methods responsible for this


    2. Somethings wrong with your cable or network itself.
    And there goes the 3rd, somethings wrong with your cabinet with its internal network -> ask for KUKA support

    I am sorry but, please be aware that my information could be wrong cause I haven't experienced ROS.
    Few things you might want to check,


    1. KONI is not a port to synchronize with your SunriseWorkbench. You need to use KLI to do it. You might want to think like; KLI for Sunrise, KONI for ROS.
    2. Maybe redirection of KONI to Windows from VxWorks-where it is originally connected- is necessary.
    PLEASE BE SURE THAT YOU WILL BE THE ONE IN CHARGE OF THE CONSEQUENCE OF THE PROCESS BELOW , but, yes I can tell you it works.
    Try review here, https://github.com/IFL-CAMP/iiwa_stack/wiki/cabinet_setup

    Hi Loris,


    I could think of 2 reasons of your problem.
    1. moveAsync is not working because the next move command is not able to taken into a runtime-for it to be able to calculate a new trajectory- because the "evaluation of end motion condition" part is blocking it.
    moveAsync command needs to access to its next motion command before it ends; technically, since moveAsync doesn't wait for its return from finishing the motion but just move on, you will have to prepare next motion right after current motion.
    2. Your FRI client is sending app.step() command slower than a period of FRI server. By looking at your statement "like the motor continuously stop and restart", it seems it is.
    You need to give the robot a new target frame before it actually gets there. Or you will get what you've seen, a stepping motion. you might want to check a calculated cycle time of your client step() method and a set period of your server.


    Plus, I'm not sure if this info can help you or not. Personally I almost always use PositionHold, cause I usually get into a situation that I have to fully control the robot position from an external controller, not only adding an overlay to commanded motions.
    The thing that lets me differentiate PositionHold motion and the others is that if I need a robot to be hold while I still need a motion command to use its functions; a motion command without motion.


    My problem is I'm unable to keep the position and orientation endPoint while using compliant mode.
    With the mode i set, the robot return near the postInit Frame but without a good accuracy : like inside a sphere with a radius of 3cm


    I get it. it is because you have considerably soft stiffness on translation with your mode.
    try set stiffness 5000 for CartDOF.TRANS
    Note that you will still be having a slight inaccuracy; i'll say roughly less than R 3mm with soft pushing.
    I guess it is because of a kinematic calculation inaccuracy caused by 7 individual tolerances of torque sensors; 0.1Nm, and of a small amount of distance you get from a formula [Force=Stiffness*distance] by giving Force inevitably.


    And I am sorry for the confusion, what I meant is 'static relative to World'.
    If you are referring to the comment below,

    Quote


    The transformation of the frames is static. For active tools, e.g. grippers,
    this means that the TCP does not adapt to the current position
    of jaws or fingers


    What is static here is 'transformation of the frame' which is the transformation from the flange frame, not from World frame which is the only genuine static frame.
    World frame is static because it doesn't change at all throughout your application.
    Taught frames are static as well(unless you directly access to .xml file and modify its values) because its transformation is relative to World.
    But Flange frame? it is 'dynamically' being changed throughout your application whenever you move the robot.
    And all TCPs that are to be attached to the Flange frame accordingly.


    Hope my little answer could help you out.

    Adding to LBR_SLAVE,


    Yes, it is because the object you commanded to move() is lbr. By default when you simply use lbr(LBR class) to move() command, it refers to the defaultFrame which is FlangeRoot.
    It needs to be rephrased something like below

    Code
    // tool & tcp must be initialized and attached
    
    
    IMotionContainer positioHoldContainer = tcp.moveAsynch(positionHold(impMode2, -1, TimeUnit.SECONDS));


    or you can simply do something like below,

    Code
    Frame posInit = lbr.getCurrentCartesianPosition( tcp );
    
    
    CartesianImpedanceControlMode impMode2 = new CartesianImpedanceControlMode();
    impMode2.parametrize( CartDOF.TRANSL ).setStiffness( 100 );
    impMode2.parametrize( CartDOF.ROT ).setStiffness( 40 );
    impMode2.setNullSpaceStiffness( 0 );
    impMode2.setReferenceSystem( posInit );


    Remember that you can only use Static frames to setReferenceSystem() method.
    If you set a Dynamic frame (e.g. tcp), you will get an application error.

Advertising from our partners