├── .assets ├── arm_platform.png ├── platform.png └── platform_examples.png ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs ├── README.md ├── digit-plexus-digit-v1.pdf └── digit-plexus.pdf ├── firmware ├── README.md ├── can │ ├── README.md │ └── digit_plexus_can_fw_v1_1_0.bin ├── ctrl │ ├── README.md │ └── digit_plexus_ctrl_v1_2_usb.bin └── usb │ ├── README.md │ └── digit_plexus_usb_hub_v1_1_1.bin ├── hardware ├── README.md ├── ecad │ └── basic │ │ ├── hand_logic │ │ ├── ALLEGRO_CONNECTOR.SchDoc │ │ ├── FINGER_CONNECTORS.SchDoc │ │ ├── FINGER_MCU.SchDoc │ │ ├── FINGER_USB_HUB.SchDoc │ │ ├── HAND_CAN_MCU.SchDoc │ │ ├── ISP_CONNECTORS.SchDoc │ │ ├── PALM_CONNECTOR.SchDoc │ │ ├── THUMB_CONNECTOR.SchDoc │ │ ├── USB_CONNECTOR.SchDoc │ │ ├── USB_HUB.SchDoc │ │ ├── USB_HUB_6CH.SchDoc │ │ ├── USB_HUB_SUPPORT.SchDoc │ │ ├── USB_PD_POWER.SchDoc │ │ ├── USB_POWER.SchDoc │ │ ├── USD_PD.SchDoc │ │ ├── WALL_POWER.SchDoc │ │ ├── hand_logic.BomDoc │ │ ├── hand_logic.PCBDwf │ │ ├── hand_logic.PcbDoc │ │ ├── hand_logic.PrjPcb │ │ ├── hand_logic.PrjPcbStructure │ │ └── hand_logic.PrjPcbVariants │ │ ├── hand_sense │ │ ├── CONNECTOR.SchDoc │ │ ├── LOGIC.SchDoc │ │ ├── SENSE.SchDoc │ │ ├── hand_sense.BomDoc │ │ ├── hand_sense.PCBDwf │ │ ├── hand_sense.PcbDoc │ │ ├── hand_sense.PrjPcb │ │ └── hand_sense.PrjPcbStructure │ │ ├── sense_logic │ │ ├── AUX_CONNECTOR.SchDoc │ │ ├── LOGIC.SchDoc │ │ ├── LOGIC_CONNECTOR.SchDoc │ │ ├── SPINE_CONNECTOR.SchDoc │ │ ├── USB_CONNECTOR.SchDoc │ │ ├── sense_logic.BomDoc │ │ ├── sense_logic.PcbDoc │ │ ├── sense_logic.PrjPcb │ │ └── sense_logic.PrjPcbStructure │ │ └── sense_patch │ │ ├── CONNECTOR.SchDoc │ │ ├── SENSE.SchDoc │ │ ├── sense_patch.BomDoc │ │ ├── sense_patch.PcbDoc │ │ ├── sense_patch.PrjPcb │ │ └── sense_patch.PrjPcbStructure ├── schematics │ ├── advanced │ │ ├── plexus_hand_logic_guidelines.pdf │ │ ├── plexus_hand_logic_sch.pdf │ │ ├── plexus_hand_sense_guidelines.pdf │ │ ├── plexus_hand_sense_sch.pdf │ │ ├── plexus_sense_logic_guidelines.pdf │ │ ├── plexus_sense_logic_sch.pdf │ │ ├── plexus_sense_patch_guidelines.pdf │ │ └── plexus_sense_patch_sch.pdf │ └── basic │ │ ├── plexus_hand_logic_sch.pdf │ │ ├── plexus_hand_sense_sch.pdf │ │ ├── plexus_sense_patch_logic_sch.pdf │ │ └── plexus_sense_patch_sch.pdf └── templates │ ├── README.md │ ├── advanced │ ├── hand_sense_template │ │ ├── CONNECTOR.SchDoc │ │ ├── SENSE.SchDoc │ │ ├── SENSE_LOWER.SchDoc │ │ ├── plexus_hand_sense_template.PcbDoc │ │ └── plexus_hand_sense_template.PrjPcb │ └── sense_template │ │ ├── CONNECTOR.SchDoc │ │ ├── SENSE.SchDoc │ │ ├── plexus_sense_template.PcbDoc │ │ └── plexus_sense_template.PrjPcb │ └── basic │ ├── hand_sense_template │ ├── CONNECTOR.SchDoc │ ├── LOGIC.SchDoc │ ├── SENSE.SchDoc │ ├── hand_sense_template.PCBDwf │ ├── hand_sense_template.PcbDoc │ └── hand_sense_template.PrjPcb │ └── sense_template │ ├── CONNECTOR.SchDoc │ ├── SENSE.SchDoc │ ├── sense_template.BomDoc │ ├── sense_template.PcbDoc │ └── sense_template.PrjPcb ├── mechanical ├── plexus_finger_link_sense_patch.step └── plexus_palm_sense_patch.step ├── plexus ├── README.md ├── install_plexus_venv.sh └── ros2 │ ├── README.md │ └── plexus_pkg │ ├── .gitignore │ ├── CMakeLists.txt │ ├── __init__.py │ ├── colcon_build.sh │ ├── launch │ ├── allegro_hand_launch.py │ ├── allegro_node_params.yaml │ ├── allegro_node_params_127r.yaml │ ├── dual_hand_launch.py │ └── sensor_patch_launch.py │ ├── msg │ └── PowerStatus.msg │ ├── package.xml │ ├── plexus_pkg │ ├── allegro_client.py │ ├── allegro_controller_node.py │ ├── allegro_driver.py │ ├── allegro_info_node.py │ ├── plexus_pb_v1 │ │ └── __init__.py │ └── sensor_patch.py │ ├── resource │ └── plexus_pkg │ ├── setup.cfg │ └── setup.py ├── setup.py └── udev ├── 99-metahand.rules ├── README.md └── install_devices.sh /.assets/arm_platform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/.assets/arm_platform.png -------------------------------------------------------------------------------- /.assets/platform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/.assets/platform.png -------------------------------------------------------------------------------- /.assets/platform_examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/.assets/platform_examples.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | res 2 | bags/** 3 | results/* 4 | .DS_Store 5 | 6 | todo.md 7 | 8 | # mesh files 9 | *.ply 10 | *.obj 11 | *core 12 | 13 | debug/* 14 | .vscode 15 | .hydra 16 | /tools/* 17 | outputs/* 18 | multirun/* 19 | *.code-workspace 20 | 21 | # Byte-compiled / optimized / DLL files 22 | __pycache__/ 23 | *.py[cod] 24 | *$py.class 25 | 26 | # C extensions 27 | *.so 28 | *.p 29 | *.tar 30 | 31 | scripts/ros2/ros_ws/ 32 | policies/ 33 | 34 | # Distribution / packaging 35 | .Python 36 | build/ 37 | develop-eggs/ 38 | ^dist/ 39 | downloads/ 40 | eggs/ 41 | .eggs/ 42 | lib/ 43 | lib64/ 44 | parts/ 45 | sdist/ 46 | var/ 47 | wheels/ 48 | pip-wheel-metadata/ 49 | share/python-wheels/ 50 | *.egg-info/ 51 | .installed.cfg 52 | *.egg 53 | MANIFEST 54 | 55 | # PyInstaller 56 | # Usually these files are written by a python script from a template 57 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 58 | *.manifest 59 | *.spec 60 | 61 | # Installer logs 62 | pip-log.txt 63 | pip-delete-this-directory.txt 64 | 65 | # Unit test / coverage reports 66 | htmlcov/ 67 | .tox/ 68 | .nox/ 69 | .coverage 70 | .coverage.* 71 | .cache 72 | nosetests.xml 73 | coverage.xml 74 | *.cover 75 | .hypothesis/ 76 | .pytest_cache/ 77 | 78 | # Translations 79 | *.mo 80 | *.pot 81 | 82 | # Django stuff: 83 | *.log 84 | local_settings.py 85 | db.sqlite3 86 | 87 | # Flask stuff: 88 | instance/ 89 | .webassets-cache 90 | 91 | # Scrapy stuff: 92 | .scrapy 93 | 94 | # Sphinx documentation 95 | docs/_build/ 96 | 97 | # PyBuilder 98 | target/ 99 | 100 | # Jupyter Notebook 101 | .ipynb_checkpoints 102 | 103 | # IPython 104 | profile_default/ 105 | ipython_config.py 106 | 107 | # pyenv 108 | .python-version 109 | 110 | # pipenv 111 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 112 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 113 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 114 | # install all needed dependencies. 115 | #Pipfile.lock 116 | 117 | # celery beat schedule file 118 | celerybeat-schedule 119 | 120 | # SageMath parsed files 121 | *.sage.py 122 | 123 | # Environments 124 | .env 125 | .venv 126 | /env/ 127 | venv/ 128 | ENV/ 129 | env.bak/ 130 | venv.bak/ 131 | 132 | # Spyder project settings 133 | .spyderproject 134 | .spyproject 135 | 136 | # Rope project settings 137 | .ropeproject 138 | 139 | # mkdocs documentation 140 | /site 141 | 142 | # mypy 143 | .mypy_cache/ 144 | .dmypy.json 145 | dmypy.json 146 | 147 | # Pyre type checker 148 | .pyre/ 149 | 150 | __MACOSX 151 | 152 | # Misc 153 | .nfs* 154 | logs/ 155 | 156 | wandb -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | This Code of Conduct also applies outside the project spaces when there is a 56 | reasonable belief that an individual's behavior may have a negative impact on 57 | the project or its community. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported by contacting the project team at . All 63 | complaints will be reviewed and investigated and will result in a response that 64 | is deemed necessary and appropriate to the circumstances. The project team is 65 | obligated to maintain confidentiality with regard to the reporter of an incident. 66 | Further details of specific enforcement policies may be posted separately. 67 | 68 | Project maintainers who do not follow or enforce the Code of Conduct in good 69 | faith may face temporary or permanent repercussions as determined by other 70 | members of the project's leadership. 71 | 72 | ## Attribution 73 | 74 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 75 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 76 | 77 | [homepage]: https://www.contributor-covenant.org 78 | 79 | For answers to common questions about this code of conduct, see 80 | https://www.contributor-covenant.org/faq -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Digit Plexus 2 | We want to make contributing to this project as easy and transparent as 3 | possible. 4 | 5 | ## Pull Requests 6 | We actively welcome your pull requests. 7 | 8 | 1. Fork the repo and create your branch from `main`. 9 | 2. If you've added code that should be tested, add tests. 10 | 3. If you've changed APIs, update the documentation. 11 | 4. Ensure the test suite passes. 12 | 5. Make sure your code lints. 13 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 14 | 15 | ## Contributor License Agreement ("CLA") 16 | In order to accept your pull request, we need you to submit a CLA. You only need 17 | to do this once to work on any of Meta's open source projects. 18 | 19 | Complete your CLA here: 20 | 21 | ## Issues 22 | We use GitHub issues to track public bugs. Please ensure your description is 23 | clear and has sufficient instructions to be able to reproduce the issue. 24 | 25 | Meta has a [bounty program](https://bugbounty.meta.com/) for the safe 26 | disclosure of security bugs. In those cases, please go through the process 27 | outlined on that page and do not file a public issue. 28 | 29 | ## License 30 | By contributing to Digit-Plexus, you agree that your contributions will be licensed 31 | under the LICENSE file in the root directory of this source tree. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Attribution-NonCommercial 4.0 International 3 | 4 | ======================================================================= 5 | 6 | Creative Commons Corporation ("Creative Commons") is not a law firm and 7 | does not provide legal services or legal advice. Distribution of 8 | Creative Commons public licenses does not create a lawyer-client or 9 | other relationship. Creative Commons makes its licenses and related 10 | information available on an "as-is" basis. Creative Commons gives no 11 | warranties regarding its licenses, any material licensed under their 12 | terms and conditions, or any related information. Creative Commons 13 | disclaims all liability for damages resulting from their use to the 14 | fullest extent possible. 15 | 16 | Using Creative Commons Public Licenses 17 | 18 | Creative Commons public licenses provide a standard set of terms and 19 | conditions that creators and other rights holders may use to share 20 | original works of authorship and other material subject to copyright 21 | and certain other rights specified in the public license below. The 22 | following considerations are for informational purposes only, are not 23 | exhaustive, and do not form part of our licenses. 24 | 25 | Considerations for licensors: Our public licenses are 26 | intended for use by those authorized to give the public 27 | permission to use material in ways otherwise restricted by 28 | copyright and certain other rights. Our licenses are 29 | irrevocable. Licensors should read and understand the terms 30 | and conditions of the license they choose before applying it. 31 | Licensors should also secure all rights necessary before 32 | applying our licenses so that the public can reuse the 33 | material as expected. Licensors should clearly mark any 34 | material not subject to the license. This includes other CC- 35 | licensed material, or material used under an exception or 36 | limitation to copyright. More considerations for licensors: 37 | wiki.creativecommons.org/Considerations_for_licensors 38 | 39 | Considerations for the public: By using one of our public 40 | licenses, a licensor grants the public permission to use the 41 | licensed material under specified terms and conditions. If 42 | the licensor's permission is not necessary for any reason--for 43 | example, because of any applicable exception or limitation to 44 | copyright--then that use is not regulated by the license. Our 45 | licenses grant only permissions under copyright and certain 46 | other rights that a licensor has authority to grant. Use of 47 | the licensed material may still be restricted for other 48 | reasons, including because others have copyright or other 49 | rights in the material. A licensor may make special requests, 50 | such as asking that all changes be marked or described. 51 | Although not required by our licenses, you are encouraged to 52 | respect those requests where reasonable. More_considerations 53 | for the public: 54 | wiki.creativecommons.org/Considerations_for_licensees 55 | 56 | ======================================================================= 57 | 58 | Creative Commons Attribution-NonCommercial 4.0 International Public 59 | License 60 | 61 | By exercising the Licensed Rights (defined below), You accept and agree 62 | to be bound by the terms and conditions of this Creative Commons 63 | Attribution-NonCommercial 4.0 International Public License ("Public 64 | License"). To the extent this Public License may be interpreted as a 65 | contract, You are granted the Licensed Rights in consideration of Your 66 | acceptance of these terms and conditions, and the Licensor grants You 67 | such rights in consideration of benefits the Licensor receives from 68 | making the Licensed Material available under these terms and 69 | conditions. 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. Copyright and Similar Rights means copyright and/or similar rights 88 | closely related to copyright including, without limitation, 89 | performance, broadcast, sound recording, and Sui Generis Database 90 | Rights, without regard to how the rights are labeled or 91 | categorized. For purposes of this Public License, the rights 92 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 93 | Rights. 94 | d. Effective Technological Measures means those measures that, in the 95 | absence of proper authority, may not be circumvented under laws 96 | fulfilling obligations under Article 11 of the WIPO Copyright 97 | Treaty adopted on December 20, 1996, and/or similar international 98 | agreements. 99 | 100 | e. Exceptions and Limitations means fair use, fair dealing, and/or 101 | any other exception or limitation to Copyright and Similar Rights 102 | that applies to Your use of the Licensed Material. 103 | 104 | f. Licensed Material means the artistic or literary work, database, 105 | or other material to which the Licensor applied this Public 106 | License. 107 | 108 | g. Licensed Rights means the rights granted to You subject to the 109 | terms and conditions of this Public License, which are limited to 110 | all Copyright and Similar Rights that apply to Your use of the 111 | Licensed Material and that the Licensor has authority to license. 112 | 113 | h. Licensor means the individual(s) or entity(ies) granting rights 114 | under this Public License. 115 | 116 | i. NonCommercial means not primarily intended for or directed towards 117 | commercial advantage or monetary compensation. For purposes of 118 | this Public License, the exchange of the Licensed Material for 119 | other material subject to Copyright and Similar Rights by digital 120 | file-sharing or similar means is NonCommercial provided there is 121 | no payment of monetary compensation in connection with the 122 | exchange. 123 | 124 | j. Share means to provide material to the public by any means or 125 | process that requires permission under the Licensed Rights, such 126 | as reproduction, public display, public performance, distribution, 127 | dissemination, communication, or importation, and to make material 128 | available to the public including in ways that members of the 129 | public may access the material from a place and at a time 130 | individually chosen by them. 131 | 132 | k. Sui Generis Database Rights means rights other than copyright 133 | resulting from Directive 96/9/EC of the European Parliament and of 134 | the Council of 11 March 1996 on the legal protection of databases, 135 | as amended and/or succeeded, as well as other essentially 136 | equivalent rights anywhere in the world. 137 | 138 | l. You means the individual or entity exercising the Licensed Rights 139 | under this Public License. Your has a corresponding meaning. 140 | 141 | Section 2 -- Scope. 142 | 143 | a. License grant. 144 | 145 | 1. Subject to the terms and conditions of this Public License, 146 | the Licensor hereby grants You a worldwide, royalty-free, 147 | non-sublicensable, non-exclusive, irrevocable license to 148 | exercise the Licensed Rights in the Licensed Material to: 149 | 150 | a. reproduce and Share the Licensed Material, in whole or 151 | in part, for NonCommercial purposes only; and 152 | 153 | b. produce, reproduce, and Share Adapted Material for 154 | NonCommercial purposes only. 155 | 156 | 2. Exceptions and Limitations. For the avoidance of doubt, where 157 | Exceptions and Limitations apply to Your use, this Public 158 | License does not apply, and You do not need to comply with 159 | its terms and conditions. 160 | 161 | 3. Term. The term of this Public License is specified in Section 162 | 6(a). 163 | 164 | 4. Media and formats; technical modifications allowed. The 165 | Licensor authorizes You to exercise the Licensed Rights in 166 | all media and formats whether now known or hereafter created, 167 | and to make technical modifications necessary to do so. The 168 | Licensor waives and/or agrees not to assert any right or 169 | authority to forbid You from making technical modifications 170 | necessary to exercise the Licensed Rights, including 171 | technical modifications necessary to circumvent Effective 172 | Technological Measures. For purposes of this Public License, 173 | simply making modifications authorized by this Section 2(a) 174 | (4) never produces Adapted Material. 175 | 176 | 5. Downstream recipients. 177 | 178 | a. Offer from the Licensor -- Licensed Material. Every 179 | recipient of the Licensed Material automatically 180 | receives an offer from the Licensor to exercise the 181 | Licensed Rights under the terms and conditions of this 182 | Public License. 183 | 184 | b. No downstream restrictions. You may not offer or impose 185 | any additional or different terms or conditions on, or 186 | apply any Effective Technological Measures to, the 187 | Licensed Material if doing so restricts exercise of the 188 | Licensed Rights by any recipient of the Licensed 189 | Material. 190 | 191 | 6. No endorsement. Nothing in this Public License constitutes or 192 | may be construed as permission to assert or imply that You 193 | are, or that Your use of the Licensed Material is, connected 194 | with, or sponsored, endorsed, or granted official status by, 195 | the Licensor or others designated to receive attribution as 196 | provided in Section 3(a)(1)(A)(i). 197 | 198 | b. Other rights. 199 | 200 | 1. Moral rights, such as the right of integrity, are not 201 | licensed under this Public License, nor are publicity, 202 | privacy, and/or other similar personality rights; however, to 203 | the extent possible, the Licensor waives and/or agrees not to 204 | assert any such rights held by the Licensor to the limited 205 | extent necessary to allow You to exercise the Licensed 206 | Rights, but not otherwise. 207 | 208 | 2. Patent and trademark rights are not licensed under this 209 | Public License. 210 | 211 | 3. To the extent possible, the Licensor waives any right to 212 | collect royalties from You for the exercise of the Licensed 213 | Rights, whether directly or through a collecting society 214 | under any voluntary or waivable statutory or compulsory 215 | licensing scheme. In all other cases the Licensor expressly 216 | reserves any right to collect such royalties, including when 217 | the Licensed Material is used other than for NonCommercial 218 | purposes. 219 | 220 | Section 3 -- License Conditions. 221 | 222 | Your exercise of the Licensed Rights is expressly made subject to the 223 | following conditions. 224 | 225 | a. Attribution. 226 | 227 | 1. If You Share the Licensed Material (including in modified 228 | form), You must: 229 | 230 | a. retain the following if it is supplied by the Licensor 231 | with the Licensed Material: 232 | 233 | i. identification of the creator(s) of the Licensed 234 | Material and any others designated to receive 235 | attribution, in any reasonable manner requested by 236 | the Licensor (including by pseudonym if 237 | designated); 238 | 239 | ii. a copyright notice; 240 | 241 | iii. a notice that refers to this Public License; 242 | 243 | iv. a notice that refers to the disclaimer of 244 | warranties; 245 | 246 | v. a URI or hyperlink to the Licensed Material to the 247 | extent reasonably practicable; 248 | 249 | b. indicate if You modified the Licensed Material and 250 | retain an indication of any previous modifications; and 251 | 252 | c. indicate the Licensed Material is licensed under this 253 | Public License, and include the text of, or the URI or 254 | hyperlink to, this Public License. 255 | 256 | 2. You may satisfy the conditions in Section 3(a)(1) in any 257 | reasonable manner based on the medium, means, and context in 258 | which You Share the Licensed Material. For example, it may be 259 | reasonable to satisfy the conditions by providing a URI or 260 | hyperlink to a resource that includes the required 261 | information. 262 | 263 | 3. If requested by the Licensor, You must remove any of the 264 | information required by Section 3(a)(1)(A) to the extent 265 | reasonably practicable. 266 | 267 | 4. If You Share Adapted Material You produce, the Adapter's 268 | License You apply must not prevent recipients of the Adapted 269 | Material from complying with this Public License. 270 | 271 | Section 4 -- Sui Generis Database Rights. 272 | 273 | Where the Licensed Rights include Sui Generis Database Rights that 274 | apply to Your use of the Licensed Material: 275 | 276 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 277 | to extract, reuse, reproduce, and Share all or a substantial 278 | portion of the contents of the database for NonCommercial purposes 279 | only; 280 | 281 | b. if You include all or a substantial portion of the database 282 | contents in a database in which You have Sui Generis Database 283 | Rights, then the database in which You have Sui Generis Database 284 | Rights (but not its individual contents) is Adapted Material; and 285 | 286 | c. You must comply with the conditions in Section 3(a) if You Share 287 | all or a substantial portion of the contents of the database. 288 | 289 | For the avoidance of doubt, this Section 4 supplements and does not 290 | replace Your obligations under this Public License where the Licensed 291 | Rights include other Copyright and Similar Rights. 292 | 293 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 294 | 295 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 296 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 297 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 298 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 299 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 300 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 301 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 302 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 303 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 304 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 305 | 306 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 307 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 308 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 309 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 310 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 311 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 312 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 313 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 314 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 315 | 316 | c. The disclaimer of warranties and limitation of liability provided 317 | above shall be interpreted in a manner that, to the extent 318 | possible, most closely approximates an absolute disclaimer and 319 | waiver of all liability. 320 | 321 | Section 6 -- Term and Termination. 322 | 323 | a. This Public License applies for the term of the Copyright and 324 | Similar Rights licensed here. However, if You fail to comply with 325 | this Public License, then Your rights under this Public License 326 | terminate automatically. 327 | 328 | b. Where Your right to use the Licensed Material has terminated under 329 | Section 6(a), it reinstates: 330 | 331 | 1. automatically as of the date the violation is cured, provided 332 | it is cured within 30 days of Your discovery of the 333 | violation; or 334 | 335 | 2. upon express reinstatement by the Licensor. 336 | 337 | For the avoidance of doubt, this Section 6(b) does not affect any 338 | right the Licensor may have to seek remedies for Your violations 339 | of this Public License. 340 | 341 | c. For the avoidance of doubt, the Licensor may also offer the 342 | Licensed Material under separate terms or conditions or stop 343 | distributing the Licensed Material at any time; however, doing so 344 | will not terminate this Public License. 345 | 346 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 347 | License. 348 | 349 | Section 7 -- Other Terms and Conditions. 350 | 351 | a. The Licensor shall not be bound by any additional or different 352 | terms or conditions communicated by You unless expressly agreed. 353 | 354 | b. Any arrangements, understandings, or agreements regarding the 355 | Licensed Material not stated herein are separate from and 356 | independent of the terms and conditions of this Public License. 357 | 358 | Section 8 -- Interpretation. 359 | 360 | a. For the avoidance of doubt, this Public License does not, and 361 | shall not be interpreted to, reduce, limit, restrict, or impose 362 | conditions on any use of the Licensed Material that could lawfully 363 | be made without permission under this Public License. 364 | 365 | b. To the extent possible, if any provision of this Public License is 366 | deemed unenforceable, it shall be automatically reformed to the 367 | minimum extent necessary to make it enforceable. If the provision 368 | cannot be reformed, it shall be severed from this Public License 369 | without affecting the enforceability of the remaining terms and 370 | conditions. 371 | 372 | c. No term or condition of this Public License will be waived and no 373 | failure to comply consented to unless expressly agreed to by the 374 | Licensor. 375 | 376 | d. Nothing in this Public License constitutes or may be interpreted 377 | as a limitation upon, or waiver of, any privileges and immunities 378 | that apply to the Licensor or You, including from the legal 379 | processes of any jurisdiction or authority. 380 | 381 | ======================================================================= 382 | 383 | Creative Commons is not a party to its public 384 | licenses. Notwithstanding, Creative Commons may elect to apply one of 385 | its public licenses to material it publishes and in those instances 386 | will be considered the “Licensor.” The text of the Creative Commons 387 | public licenses is dedicated to the public domain under the CC0 Public 388 | Domain Dedication. Except for the limited purpose of indicating that 389 | material is shared under a Creative Commons public license or as 390 | otherwise permitted by the Creative Commons policies published at 391 | creativecommons.org/policies, Creative Commons does not authorize the 392 | use of the trademark "Creative Commons" or any other trademark or logo 393 | of Creative Commons without its prior written consent including, 394 | without limitation, in connection with any unauthorized modifications 395 | to any of its public licenses or any other arrangements, 396 | understandings, or agreements concerning use of licensed material. For 397 | the avoidance of doubt, this paragraph does not form part of the 398 | public licenses. 399 | 400 | Creative Commons may be contacted at creativecommons.org. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Meta Digit Plexus 2 | ##### A robotics hardware platform for the integration sensors and end effectors into a common platform. 3 | 4 |

5 | drawing 6 |

7 | 8 |

9 | 10 |

11 | 12 | Digit Plexus aims to create a standardized platform that provides a hardware-software solution to integrate tactile sensors on any robot hand. The platform interfaces vision-based and skin-based tactile sensors like Digit, Digit 360, and [ReSkin](https://reskin.dev) across fingertips, fingers, and palm, into control boards to encode all data to a host computer. The software integration and hardware components of the platform allows for seamless data collection, control and analysis over a single cable. 13 | 14 | ## Standardized Platform 15 | 16 | We propose and implement variations of the Digit Plexus standardized architecture found [here](./docs/digit-plexus.pdf) 17 | 18 | The [advanced](./hardware/schematics/advanced/) variation of the architecture allows for a modular implementation to support any custom sense patch configuration where each link is connected via USB to the hand logic motherboard. 19 | 20 | Additionally, actions may be provided to a robotic end effector or hand via multiple methods such as: CAN, USB, I2C. 21 | 22 | #### Partnerships 23 | 24 | We have partnered with Wonik Robotic's to develop a next generation Allegro Hand based off of the Digit Plexus platform. For early access, interest may be expressed through this [form](https://digit.ml/plexus). 25 | 26 | 27 | ## Usage 28 | 29 | Design files for **basic** (rigid based) and **advanced** (flex) are found in the [hardware](./hardware/) folder of the repository. Furthermore, we provide the Altium Designer ECAD templates which can be used to create a custom sensor patch configuration for the hand, links or fingertips. 30 | 31 | ### Sense and Hand Patch 32 | 33 | Mechanical sense patch files for 3D printing or mold design are found in the [mechanical](./mechanical/) folder. Depending on the application, or the preferred sensing modality, you may use a similar technique to ReSkin (magnetic particulate infused silicone) or an alternative composition of silicone for forming the sensing surface interacting with the sense patch. We recommend attaching the sense patches to the base end effector with a 3M 300LSE double sided adhesive. 34 | 35 | ### Fingertip Sensing 36 | 37 | The Digit Plexus platform supports Digit tactile sensors as well as any alternative sensor based on a USB2.0 connection as shown [here](./docs/digit-plexus-digit-v1.pdf). 38 | 39 | 40 |

41 | 42 |

43 | 44 | 45 | ## 🛠️Installation and setup 46 | Digit Plexus contains a USB hub device which will enumerate all devices connected to the [base](./hardware/base). 47 | 48 | Currently, this supports the [Allegro Hand](https://www.allegrohand.com/) and the [next generation Allegro Hand](https://digit.ml/plexus.html) in partnership with Meta. 49 | 50 | Digit Plexus provides a new interface for controlling the Allegro Hand directly through a Python interface, as well provides a ROS2 integration. 51 | 52 | Installation and usage instructions are found [here](./plexus/README.md). 53 | 54 | ## Related Works using Digit Plexus plartform 55 | * [Neural feels with neural fields: Visuo-tactile perception for in-hand manipulation, Sudharshan Suresh et al.](https://suddhu.github.io/neural-feels/) 56 | * [Learning In-Hand Translation Using Tactile Skin With Shear and Normal Force Sensing, Jessica Yin et al.](https://jessicayin.github.io/tactile-skin-rl/) 57 | 58 | ## License 59 | This project is licensed under [LICENSE](LICENSE). 60 | 61 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Digit Plexus 3 | 4 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 5 | 6 | ## License 7 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /docs/digit-plexus-digit-v1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/docs/digit-plexus-digit-v1.pdf -------------------------------------------------------------------------------- /docs/digit-plexus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/docs/digit-plexus.pdf -------------------------------------------------------------------------------- /firmware/README.md: -------------------------------------------------------------------------------- 1 | # Digit Plexus 2 | 3 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 4 | 5 | ## License 6 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /firmware/can/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Digit Plexus 3 | 4 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 5 | 6 | ## License 7 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /firmware/can/digit_plexus_can_fw_v1_1_0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/firmware/can/digit_plexus_can_fw_v1_1_0.bin -------------------------------------------------------------------------------- /firmware/ctrl/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Digit Plexus 3 | 4 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 5 | 6 | ## License 7 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /firmware/ctrl/digit_plexus_ctrl_v1_2_usb.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/firmware/ctrl/digit_plexus_ctrl_v1_2_usb.bin -------------------------------------------------------------------------------- /firmware/usb/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Digit Plexus 3 | 4 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 5 | 6 | ## License 7 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /firmware/usb/digit_plexus_usb_hub_v1_1_1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/firmware/usb/digit_plexus_usb_hub_v1_1_1.bin -------------------------------------------------------------------------------- /hardware/README.md: -------------------------------------------------------------------------------- 1 | # Digit Plexus 2 | 3 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 4 | 5 | ## License 6 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/ALLEGRO_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/ALLEGRO_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/FINGER_CONNECTORS.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/FINGER_CONNECTORS.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/FINGER_MCU.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/FINGER_MCU.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/FINGER_USB_HUB.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/FINGER_USB_HUB.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/HAND_CAN_MCU.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/HAND_CAN_MCU.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/ISP_CONNECTORS.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/ISP_CONNECTORS.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/PALM_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/PALM_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/THUMB_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/THUMB_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USB_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USB_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USB_HUB.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USB_HUB.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USB_HUB_6CH.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USB_HUB_6CH.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USB_HUB_SUPPORT.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USB_HUB_SUPPORT.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USB_PD_POWER.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USB_PD_POWER.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USB_POWER.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USB_POWER.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/USD_PD.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/USD_PD.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/WALL_POWER.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/WALL_POWER.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/hand_logic.BomDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/hand_logic.BomDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/hand_logic.PCBDwf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/hand_logic.PCBDwf -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/hand_logic.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/hand_logic.PcbDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/hand_logic.PrjPcbStructure: -------------------------------------------------------------------------------- 1 | Record=TopLevelDocument|FileName=ALLEGRO_CONNECTOR.SchDoc|SheetNumber=5 2 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=FINGER_CONNECTORS.SchDoc|SheetNumber=1 3 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=FINGER_MCU.SchDoc|SheetNumber=8 4 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=FINGER_USB_HUB.SchDoc|SheetNumber=15 5 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=HAND_CAN_MCU.SchDoc|SheetNumber=7 6 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=ISP_CONNECTORS.SchDoc|SheetNumber=4 7 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=PALM_CONNECTOR.SchDoc|SheetNumber=2 8 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=THUMB_CONNECTOR.SchDoc|SheetNumber=3 9 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=USB_CONNECTOR.SchDoc|SheetNumber=9 10 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=USB_HUB.SchDoc|SheetNumber=10 11 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=USB_HUB_SUPPORT.SchDoc|SheetNumber=11 12 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=USB_PD_POWER.SchDoc|SheetNumber=14 13 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=USB_POWER.SchDoc|SheetNumber=12 14 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=USD_PD.SchDoc|SheetNumber=13 15 | Record=NoMainPathDocument|SourceDocument=ALLEGRO_CONNECTOR.SchDoc|FileName=WALL_POWER.SchDoc|SheetNumber=6 16 | -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_logic/hand_logic.PrjPcbVariants: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_logic/hand_logic.PrjPcbVariants -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_sense/CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/LOGIC.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_sense/LOGIC.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/SENSE.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_sense/SENSE.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/hand_sense.BomDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_sense/hand_sense.BomDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/hand_sense.PCBDwf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_sense/hand_sense.PCBDwf -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/hand_sense.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/hand_sense/hand_sense.PcbDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/hand_sense/hand_sense.PrjPcbStructure: -------------------------------------------------------------------------------- 1 | Record=TopLevelDocument|FileName=CONNECTOR.SchDoc|SheetNumber=2 2 | Record=NoMainPathDocument|SourceDocument=CONNECTOR.SchDoc|FileName=LOGIC.SchDoc|SheetNumber=3 3 | Record=NoMainPathDocument|SourceDocument=CONNECTOR.SchDoc|FileName=SENSE.SchDoc|SheetNumber=1 4 | -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/AUX_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/AUX_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/LOGIC.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/LOGIC.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/LOGIC_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/LOGIC_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/SPINE_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/SPINE_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/USB_CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/USB_CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/sense_logic.BomDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/sense_logic.BomDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/sense_logic.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_logic/sense_logic.PcbDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/sense_logic.PrjPcb: -------------------------------------------------------------------------------- 1 | [Design] 2 | Version=1.0 3 | HierarchyMode=0 4 | ChannelRoomNamingStyle=0 5 | ReleasesFolder= 6 | ChannelDesignatorFormatString=$Component_$RoomName 7 | ChannelRoomLevelSeperator=_ 8 | OpenOutputs=1 9 | ArchiveProject=0 10 | TimestampOutput=0 11 | SeparateFolders=0 12 | TemplateLocationPath= 13 | PinSwapBy_Netlabel=1 14 | PinSwapBy_Pin=1 15 | AllowPortNetNames=0 16 | AllowSheetEntryNetNames=1 17 | AppendSheetNumberToLocalNets=0 18 | NetlistSinglePinNets=0 19 | DefaultConfiguration=Sources 20 | UserID=0xFFFFFFFF 21 | DefaultPcbProtel=1 22 | DefaultPcbPcad=0 23 | ReorderDocumentsOnCompile=1 24 | NameNetsHierarchically=0 25 | PowerPortNamesTakePriority=0 26 | AutoSheetNumbering=1 27 | AutoCrossReferences=1 28 | NewIndexingOfSheetSymbols=1 29 | PushECOToAnnotationFile=1 30 | DItemRevisionGUID= 31 | ReportSuppressedErrorsInMessages=0 32 | FSMCodingStyle=eFMSDropDownList_OneProcess 33 | FSMEncodingStyle=eFMSDropDownList_OneHot 34 | IsProjectConflictPreventionWarningsEnabled=0 35 | ConstraintManagerFlow=0 36 | IsVirtualBomDocumentRemoved=0 37 | OutputPath= 38 | LogFolderPath= 39 | ManagedProjectGUID= 40 | IncludeDesignInRelease=0 41 | CrossRefSheetStyle=0 42 | CrossRefLocationStyle=0 43 | CrossRefPorts=3 44 | CrossRefCrossSheets=1 45 | CrossRefSheetEntries=0 46 | CrossRefFollowFromMainSettings=0 47 | 48 | [Preferences] 49 | PrefsVaultGUID= 50 | PrefsRevisionGUID= 51 | 52 | [Document1] 53 | DocumentPath=SPINE_CONNECTOR.SchDoc 54 | AnnotationEnabled=1 55 | AnnotateStartValue=1 56 | AnnotationIndexControlEnabled=0 57 | AnnotateSuffix= 58 | AnnotateScope=All 59 | AnnotateOrder=0 60 | DoLibraryUpdate=1 61 | DoDatabaseUpdate=1 62 | ClassGenCCAutoEnabled=1 63 | ClassGenCCAutoRoomEnabled=1 64 | ClassGenNCAutoScope=None 65 | DItemRevisionGUID= 66 | GenerateClassCluster=0 67 | DocumentUniqueId=OMAFKQXU 68 | 69 | [Document2] 70 | DocumentPath=AUX_CONNECTOR.SchDoc 71 | AnnotationEnabled=1 72 | AnnotateStartValue=1 73 | AnnotationIndexControlEnabled=0 74 | AnnotateSuffix= 75 | AnnotateScope=All 76 | AnnotateOrder=3 77 | DoLibraryUpdate=1 78 | DoDatabaseUpdate=1 79 | ClassGenCCAutoEnabled=1 80 | ClassGenCCAutoRoomEnabled=0 81 | ClassGenNCAutoScope=None 82 | DItemRevisionGUID= 83 | GenerateClassCluster=0 84 | DocumentUniqueId=OJDMUIUG 85 | 86 | [Document3] 87 | DocumentPath=USB_CONNECTOR.SchDoc 88 | AnnotationEnabled=1 89 | AnnotateStartValue=1 90 | AnnotationIndexControlEnabled=0 91 | AnnotateSuffix= 92 | AnnotateScope=All 93 | AnnotateOrder=4 94 | DoLibraryUpdate=1 95 | DoDatabaseUpdate=1 96 | ClassGenCCAutoEnabled=1 97 | ClassGenCCAutoRoomEnabled=1 98 | ClassGenNCAutoScope=None 99 | DItemRevisionGUID= 100 | GenerateClassCluster=0 101 | DocumentUniqueId=NGILZHZZ 102 | 103 | [Document4] 104 | DocumentPath=LOGIC_CONNECTOR.SchDoc 105 | AnnotationEnabled=1 106 | AnnotateStartValue=1 107 | AnnotationIndexControlEnabled=0 108 | AnnotateSuffix= 109 | AnnotateScope=All 110 | AnnotateOrder=1 111 | DoLibraryUpdate=1 112 | DoDatabaseUpdate=1 113 | ClassGenCCAutoEnabled=1 114 | ClassGenCCAutoRoomEnabled=1 115 | ClassGenNCAutoScope=None 116 | DItemRevisionGUID= 117 | GenerateClassCluster=0 118 | DocumentUniqueId=PTAZRBXM 119 | 120 | [Document5] 121 | DocumentPath=LOGIC.SchDoc 122 | AnnotationEnabled=1 123 | AnnotateStartValue=1 124 | AnnotationIndexControlEnabled=0 125 | AnnotateSuffix= 126 | AnnotateScope=All 127 | AnnotateOrder=2 128 | DoLibraryUpdate=1 129 | DoDatabaseUpdate=1 130 | ClassGenCCAutoEnabled=1 131 | ClassGenCCAutoRoomEnabled=1 132 | ClassGenNCAutoScope=None 133 | DItemRevisionGUID= 134 | GenerateClassCluster=0 135 | DocumentUniqueId=HKXVLAMF 136 | 137 | [Document6] 138 | DocumentPath=sense_logic.PcbDoc 139 | AnnotationEnabled=1 140 | AnnotateStartValue=1 141 | AnnotationIndexControlEnabled=0 142 | AnnotateSuffix= 143 | AnnotateScope=All 144 | AnnotateOrder=-1 145 | DoLibraryUpdate=1 146 | DoDatabaseUpdate=1 147 | ClassGenCCAutoEnabled=1 148 | ClassGenCCAutoRoomEnabled=1 149 | ClassGenNCAutoScope=None 150 | DItemRevisionGUID= 151 | GenerateClassCluster=0 152 | DocumentUniqueId=SQQNUXKD 153 | 154 | [Document7] 155 | DocumentPath=sense_logic.BomDoc 156 | AnnotationEnabled=1 157 | AnnotateStartValue=1 158 | AnnotationIndexControlEnabled=0 159 | AnnotateSuffix= 160 | AnnotateScope=All 161 | AnnotateOrder=-1 162 | DoLibraryUpdate=1 163 | DoDatabaseUpdate=1 164 | ClassGenCCAutoEnabled=1 165 | ClassGenCCAutoRoomEnabled=0 166 | ClassGenNCAutoScope=None 167 | DItemRevisionGUID= 168 | GenerateClassCluster=0 169 | DocumentUniqueId= 170 | 171 | [GeneratedDocument1] 172 | DocumentPath=Project Outputs for metahand_senselogic\Design Rule Check - metahand_sense_logic.html 173 | DItemRevisionGUID= 174 | 175 | [Configuration1] 176 | Name=Sources 177 | ParameterCount=0 178 | ConstraintFileCount=0 179 | ReleaseItemId= 180 | Variant=[No Variations] 181 | OutputJobsCount=0 182 | ContentTypeGUID=CB6F2064-E317-11DF-B822-12313F0024A2 183 | ConfigurationType=Source 184 | 185 | [Generic_SmartPDF] 186 | AutoOpenFile=0 187 | AutoOpenOutJob=-1 188 | 189 | [Generic_SmartPDFSettings] 190 | ProjectMode=-1 191 | ZoomPrecision=50 192 | AddNetsInformation=-1 193 | AddNetPins=-1 194 | AddNetNetLabels=-1 195 | AddNetPorts=-1 196 | ShowComponentParameters=0 197 | GlobalBookmarks=0 198 | ExportBOM=0 199 | TemplateFilename= 200 | TemplateStoreRelative=-1 201 | PCB_PrintColor=1 202 | SCH_PrintColor=0 203 | PrintQuality=-3 204 | SCH_ShowNoErc=-1 205 | SCH_ShowParameter=-1 206 | SCH_ShowProbes=-1 207 | SCH_ShowBlankets=-1 208 | SCH_NoERCSymbolsToShow="Thin Cross","Thick Cross","Small Cross",Checkbox,Triangle 209 | SCH_ShowNote=-1 210 | SCH_ShowNoteCollapsed=-1 211 | Wir_PrintColor=0 212 | Ldr_PrintColor=0 213 | SCH_ExpandLogicalToPhysical=-1 214 | SCH_VariantName=[No Variations] 215 | SCH_ExpandComponentDesignators=-1 216 | SCH_ExpandNetlabels=0 217 | SCH_ExpandPorts=0 218 | SCH_ExpandSheetNumber=0 219 | SCH_ExpandDocumentNumber=0 220 | SCH_HasExpandLogicalToPhysicalSheets=-1 221 | SaveSettingsToOutJob=0 222 | 223 | [OutputGroup1] 224 | Name=Netlist Outputs 225 | Description= 226 | TargetPrinter=Microsoft Print to PDF 227 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 228 | OutputType1=CadnetixNetlist 229 | OutputName1=Cadnetix Netlist 230 | OutputDocumentPath1= 231 | OutputVariantName1= 232 | OutputDefault1=0 233 | OutputType2=CalayNetlist 234 | OutputName2=Calay Netlist 235 | OutputDocumentPath2= 236 | OutputVariantName2= 237 | OutputDefault2=0 238 | OutputType3=EDIF 239 | OutputName3=EDIF for PCB 240 | OutputDocumentPath3= 241 | OutputVariantName3= 242 | OutputDefault3=0 243 | OutputType4=EESofNetlist 244 | OutputName4=EESof Netlist 245 | OutputDocumentPath4= 246 | OutputVariantName4= 247 | OutputDefault4=0 248 | OutputType5=IntergraphNetlist 249 | OutputName5=Intergraph Netlist 250 | OutputDocumentPath5= 251 | OutputVariantName5= 252 | OutputDefault5=0 253 | OutputType6=MentorBoardStationNetlist 254 | OutputName6=Mentor BoardStation Netlist 255 | OutputDocumentPath6= 256 | OutputVariantName6= 257 | OutputDefault6=0 258 | OutputType7=MultiWire 259 | OutputName7=MultiWire 260 | OutputDocumentPath7= 261 | OutputVariantName7= 262 | OutputDefault7=0 263 | OutputType8=OrCadPCB2Netlist 264 | OutputName8=Orcad/PCB2 Netlist 265 | OutputDocumentPath8= 266 | OutputVariantName8= 267 | OutputDefault8=0 268 | OutputType9=PADSNetlist 269 | OutputName9=PADS ASCII Netlist 270 | OutputDocumentPath9= 271 | OutputVariantName9= 272 | OutputDefault9=0 273 | OutputType10=Pcad 274 | OutputName10=Pcad for PCB 275 | OutputDocumentPath10= 276 | OutputVariantName10= 277 | OutputDefault10=0 278 | OutputType11=PCADNetlist 279 | OutputName11=PCAD Netlist 280 | OutputDocumentPath11= 281 | OutputVariantName11= 282 | OutputDefault11=0 283 | OutputType12=PCADnltNetlist 284 | OutputName12=PCADnlt Netlist 285 | OutputDocumentPath12= 286 | OutputVariantName12= 287 | OutputDefault12=0 288 | OutputType13=Protel2Netlist 289 | OutputName13=Protel2 Netlist 290 | OutputDocumentPath13= 291 | OutputVariantName13= 292 | OutputDefault13=0 293 | OutputType14=ProtelNetlist 294 | OutputName14=Protel 295 | OutputDocumentPath14= 296 | OutputVariantName14= 297 | OutputDefault14=0 298 | OutputType15=RacalNetlist 299 | OutputName15=Racal Netlist 300 | OutputDocumentPath15= 301 | OutputVariantName15= 302 | OutputDefault15=0 303 | OutputType16=RINFNetlist 304 | OutputName16=RINF Netlist 305 | OutputDocumentPath16= 306 | OutputVariantName16= 307 | OutputDefault16=0 308 | OutputType17=SciCardsNetlist 309 | OutputName17=SciCards Netlist 310 | OutputDocumentPath17= 311 | OutputVariantName17= 312 | OutputDefault17=0 313 | OutputType18=TangoNetlist 314 | OutputName18=Tango Netlist 315 | OutputDocumentPath18= 316 | OutputVariantName18= 317 | OutputDefault18=0 318 | OutputType19=TelesisNetlist 319 | OutputName19=Telesis Netlist 320 | OutputDocumentPath19= 321 | OutputVariantName19= 322 | OutputDefault19=0 323 | OutputType20=WireListNetlist 324 | OutputName20=WireList Netlist 325 | OutputDocumentPath20= 326 | OutputVariantName20= 327 | OutputDefault20=0 328 | OutputType21=XSpiceNetlist 329 | OutputName21=Mixed Sim Netlist 330 | OutputDocumentPath21= 331 | OutputVariantName21= 332 | OutputDefault21=0 333 | 334 | [OutputGroup2] 335 | Name=Simulator Outputs 336 | Description= 337 | TargetPrinter=Microsoft Print to PDF 338 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 339 | OutputType1=AdvSimNetlist 340 | OutputName1=Mixed Sim 341 | OutputDocumentPath1= 342 | OutputVariantName1= 343 | OutputDefault1=0 344 | 345 | [OutputGroup3] 346 | Name=Documentation Outputs 347 | Description= 348 | TargetPrinter=Microsoft Print to PDF 349 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 350 | OutputType1=Composite 351 | OutputName1=Composite Drawing 352 | OutputDocumentPath1= 353 | OutputVariantName1=[No Variations] 354 | OutputDefault1=0 355 | PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 356 | OutputType2=Harness Layout Drawing Print 357 | OutputName2=Harness Layout Drawing Prints 358 | OutputDocumentPath2= 359 | OutputVariantName2= 360 | OutputDefault2=0 361 | PageOptions2=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 362 | OutputType3=Harness Wiring Diagram Print 363 | OutputName3=Harness Wiring Diagram Prints 364 | OutputDocumentPath3= 365 | OutputVariantName3= 366 | OutputDefault3=0 367 | PageOptions3=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 368 | OutputType4=PCB 3D Print 369 | OutputName4=PCB 3D Print 370 | OutputDocumentPath4= 371 | OutputVariantName4=[No Variations] 372 | OutputDefault4=0 373 | PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 374 | OutputType5=PCB 3D Video 375 | OutputName5=PCB 3D Video 376 | OutputDocumentPath5= 377 | OutputVariantName5=[No Variations] 378 | OutputDefault5=0 379 | PageOptions5=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 380 | OutputType6=PCB Print 381 | OutputName6=PCB Prints 382 | OutputDocumentPath6= 383 | OutputVariantName6=[No Variations] 384 | OutputDefault6=0 385 | PageOptions6=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 386 | OutputType7=PCBDrawing 387 | OutputName7=Draftsman 388 | OutputDocumentPath7= 389 | OutputVariantName7=[No Variations] 390 | OutputDefault7=0 391 | PageOptions7=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 392 | OutputType8=PCBLIB Print 393 | OutputName8=PCBLIB Prints 394 | OutputDocumentPath8= 395 | OutputVariantName8=[No Variations] 396 | OutputDefault8=0 397 | PageOptions8=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 398 | OutputType9=PDF3D 399 | OutputName9=PDF3D 400 | OutputDocumentPath9= 401 | OutputVariantName9=[No Variations] 402 | OutputDefault9=0 403 | PageOptions9=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 404 | OutputType10=PDF3D MBA 405 | OutputName10=PDF3D MBA 406 | OutputDocumentPath10= 407 | OutputVariantName10= 408 | OutputDefault10=0 409 | PageOptions10=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 410 | OutputType11=Report Print 411 | OutputName11=Report Prints 412 | OutputDocumentPath11= 413 | OutputVariantName11= 414 | OutputDefault11=0 415 | PageOptions11=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 416 | OutputType12=Schematic Print 417 | OutputName12=Schematic Prints 418 | OutputDocumentPath12= 419 | OutputVariantName12= 420 | OutputDefault12=0 421 | PageOptions12=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 422 | OutputType13=SimView Print 423 | OutputName13=SimView Prints 424 | OutputDocumentPath13= 425 | OutputVariantName13= 426 | OutputDefault13=0 427 | PageOptions13=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 428 | 429 | [OutputGroup4] 430 | Name=Assembly Outputs 431 | Description= 432 | TargetPrinter=Microsoft Print to PDF 433 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 434 | OutputType1=Assembly 435 | OutputName1=Assembly Drawings 436 | OutputDocumentPath1= 437 | OutputVariantName1=[No Variations] 438 | OutputDefault1=0 439 | PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 440 | OutputType2=Pick Place 441 | OutputName2=Generates pick and place files 442 | OutputDocumentPath2= 443 | OutputVariantName2=[No Variations] 444 | OutputDefault2=0 445 | OutputType3=Test Points For Assembly 446 | OutputName3=Test Point Report 447 | OutputDocumentPath3= 448 | OutputVariantName3=[No Variations] 449 | OutputDefault3=0 450 | 451 | [OutputGroup5] 452 | Name=Fabrication Outputs 453 | Description= 454 | TargetPrinter=Microsoft Print to PDF 455 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 456 | OutputType1=Board Stack Report 457 | OutputName1=Report Board Stack 458 | OutputDocumentPath1= 459 | OutputVariantName1= 460 | OutputDefault1=0 461 | PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 462 | OutputType2=CompositeDrill 463 | OutputName2=Composite Drill Drawing 464 | OutputDocumentPath2= 465 | OutputVariantName2=[No Variations] 466 | OutputDefault2=0 467 | PageOptions2=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 468 | OutputType3=Drill 469 | OutputName3=Drill Drawing/Guides 470 | OutputDocumentPath3= 471 | OutputVariantName3=[No Variations] 472 | OutputDefault3=0 473 | PageOptions3=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 474 | OutputType4=Final 475 | OutputName4=Final Artwork Prints 476 | OutputDocumentPath4= 477 | OutputVariantName4=[No Variations] 478 | OutputDefault4=0 479 | PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 480 | OutputType5=Gerber 481 | OutputName5=Gerber Files 482 | OutputDocumentPath5= 483 | OutputVariantName5=[No Variations] 484 | OutputDefault5=0 485 | OutputType6=Gerber X2 486 | OutputName6=Gerber X2 Files 487 | OutputDocumentPath6= 488 | OutputVariantName6=[No Variations] 489 | OutputDefault6=0 490 | OutputType7=IPC2581 491 | OutputName7=IPC-2581 Files 492 | OutputDocumentPath7= 493 | OutputVariantName7=[No Variations] 494 | OutputDefault7=0 495 | OutputType8=Mask 496 | OutputName8=Solder/Paste Mask Prints 497 | OutputDocumentPath8= 498 | OutputVariantName8=[No Variations] 499 | OutputDefault8=0 500 | PageOptions8=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 501 | OutputType9=NC Drill 502 | OutputName9=NC Drill Files 503 | OutputDocumentPath9= 504 | OutputVariantName9= 505 | OutputDefault9=0 506 | OutputType10=ODB 507 | OutputName10=ODB++ Files 508 | OutputDocumentPath10= 509 | OutputVariantName10=[No Variations] 510 | OutputDefault10=0 511 | OutputType11=Plane 512 | OutputName11=Power-Plane Prints 513 | OutputDocumentPath11= 514 | OutputVariantName11=[No Variations] 515 | OutputDefault11=0 516 | PageOptions11=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 517 | OutputType12=Test Points 518 | OutputName12=Test Point Report 519 | OutputDocumentPath12= 520 | OutputVariantName12= 521 | OutputDefault12=0 522 | 523 | [OutputGroup6] 524 | Name=Report Outputs 525 | Description= 526 | TargetPrinter=Microsoft Print to PDF 527 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 528 | OutputType1=BOM_PartType 529 | OutputName1=Bill of Materials 530 | OutputDocumentPath1= 531 | OutputVariantName1=[No Variations] 532 | OutputDefault1=0 533 | PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 534 | Configuration1_Name1=ColumnNameFormat 535 | Configuration1_Item1=CaptionAsName 536 | Configuration1_Name2=ForceUpdateSettings 537 | Configuration1_Item2=False 538 | Configuration1_Name3=General 539 | Configuration1_Item3=OpenExported=False|AddToProject=False|ReportBOMViolationsInMessages=False|ForceFit=False|NotFitted=False|Database=False|DatabasePriority=False|IncludePcbData=False|IncludeVaultData=False|IncludeCloudData=False|IncludeDocumentData=False|IncludeAlternatives=True|ShowExportOptions=True|TemplateFilename=|TemplateVaultGuid=|TemplateItemGuid=|TemplateRevisionGuid=|BatchMode=5|FormWidth=1200|FormHeight=710|SupplierProdQty=15|SupplierAutoQty=True|SupplierUseCachedPricing=False|SupplierCurrency=USD|SolutionsPerItem=1|SuppliersPerSolution=1|ViewType=0|UseDirectApi=True|BomSetName= 540 | Configuration1_Name4=GroupOrder 541 | Configuration1_Item4= 542 | Configuration1_Name5=VisibleOrder 543 | Configuration1_Item5=Line #=54|Comment=146|Description=81|Designator=79|Revision ID=79|Revision State=114|Revision Status=99|Quantity=67|Manufacturer 1=101|Manufacturer Part Number 1=170|Manufacturer Lifecycle 1=147|Supplier 1=74|Supplier Part Number 1=143|Supplier Unit Price 1=127|Supplier Subtotal 1=120 544 | Configuration1_Name6=VisibleOrder_Base 545 | Configuration1_Item6=Line #=54|Comment=146|Description=81|Designator=79|Revision ID=79|Revision State=114|Revision Status=99|Quantity=67|Manufacturer 1=101|Manufacturer Part Number 1=170|Manufacturer Lifecycle 1=147|Supplier 1=74|Supplier Part Number 1=143|Supplier Unit Price 1=127|Supplier Subtotal 1=120 546 | Configuration1_Name7=VisibleOrder_Consolidated 547 | Configuration1_Item7=Line #=100|Comment=100|Description=100|Designator=100|Revision ID=100|Revision State=100|Revision Status=100|Quantity=100|Manufacturer 1=101|Manufacturer Part Number 1=170|Manufacturer Lifecycle 1=147|Supplier 1=74|Supplier Part Number 1=143|Supplier Unit Price 1=127|Supplier Subtotal 1=120 548 | Configuration1_Name8=VisibleOrder_Flat 549 | Configuration1_Item8=Line #=100|Comment=100|Description=100|Designator=100|Revision ID=100|Revision State=100|Revision Status=100|Manufacturer 1=101|Manufacturer Part Number 1=170|Manufacturer Lifecycle 1=147|Supplier 1=74|Supplier Part Number 1=143|Supplier Unit Price 1=127|Supplier Subtotal 1=120 550 | OutputType2=BOM_ReportCompare 551 | OutputName2=BOM Compare 552 | OutputDocumentPath2= 553 | OutputVariantName2=[No Variations] 554 | OutputDefault2=0 555 | PageOptions2=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 556 | OutputType3=ComponentCrossReference 557 | OutputName3=Component Cross Reference Report 558 | OutputDocumentPath3= 559 | OutputVariantName3=[No Variations] 560 | OutputDefault3=0 561 | OutputType4=Export Comments 562 | OutputName4=Export Comments 563 | OutputDocumentPath4= 564 | OutputVariantName4=[No Variations] 565 | OutputDefault4=0 566 | PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 567 | OutputType5=Project History 568 | OutputName5=Project History 569 | OutputDocumentPath5= 570 | OutputVariantName5=[No Variations] 571 | OutputDefault5=0 572 | PageOptions5=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 573 | OutputType6=ReportHierarchy 574 | OutputName6=Report Project Hierarchy 575 | OutputDocumentPath6= 576 | OutputVariantName6=[No Variations] 577 | OutputDefault6=0 578 | OutputType7=Script 579 | OutputName7=Script Output 580 | OutputDocumentPath7= 581 | OutputVariantName7=[No Variations] 582 | OutputDefault7=0 583 | OutputType8=SimpleBOM 584 | OutputName8=Simple BOM 585 | OutputDocumentPath8= 586 | OutputVariantName8=[No Variations] 587 | OutputDefault8=0 588 | OutputType9=SinglePinNetReporter 589 | OutputName9=Report Single Pin Nets 590 | OutputDocumentPath9= 591 | OutputVariantName9=[No Variations] 592 | OutputDefault9=0 593 | 594 | [OutputGroup7] 595 | Name=Other Outputs 596 | Description= 597 | TargetPrinter=Microsoft Print to PDF 598 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 599 | OutputType1=Text Print 600 | OutputName1=Text Print 601 | OutputDocumentPath1= 602 | OutputVariantName1= 603 | OutputDefault1=0 604 | PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 605 | 606 | [OutputGroup8] 607 | Name=Validation Outputs 608 | Description= 609 | TargetPrinter=Microsoft Print to PDF 610 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 611 | OutputType1=BOM_Violations 612 | OutputName1=BOM Checks Report 613 | OutputDocumentPath1= 614 | OutputVariantName1= 615 | OutputDefault1=0 616 | OutputType2=Component states check 617 | OutputName2=Server's components states check 618 | OutputDocumentPath2= 619 | OutputVariantName2= 620 | OutputDefault2=0 621 | OutputType3=Configuration compliance 622 | OutputName3=Environment configuration compliance check 623 | OutputDocumentPath3= 624 | OutputVariantName3= 625 | OutputDefault3=0 626 | OutputType4=Design Rules Check 627 | OutputName4=Design Rules Check 628 | OutputDocumentPath4= 629 | OutputVariantName4= 630 | OutputDefault4=0 631 | PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 632 | OutputType5=Differences Report 633 | OutputName5=Differences Report 634 | OutputDocumentPath5= 635 | OutputVariantName5= 636 | OutputDefault5=0 637 | PageOptions5=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 638 | OutputType6=Electrical Rules Check 639 | OutputName6=Electrical Rules Check 640 | OutputDocumentPath6= 641 | OutputVariantName6= 642 | OutputDefault6=0 643 | PageOptions6=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 644 | OutputType7=Footprint Comparison Report 645 | OutputName7=Footprint Comparison Report 646 | OutputDocumentPath7= 647 | OutputVariantName7= 648 | OutputDefault7=0 649 | 650 | [OutputGroup9] 651 | Name=Export Outputs 652 | Description= 653 | TargetPrinter=Microsoft Print to PDF 654 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 655 | OutputType1=AutoCAD dwg/dxf PCB 656 | OutputName1=AutoCAD dwg/dxf File PCB 657 | OutputDocumentPath1= 658 | OutputVariantName1= 659 | OutputDefault1=0 660 | OutputType2=AutoCAD dwg/dxf Schematic 661 | OutputName2=AutoCAD dwg/dxf File Schematic 662 | OutputDocumentPath2= 663 | OutputVariantName2= 664 | OutputDefault2=0 665 | OutputType3=ExportIDF 666 | OutputName3=Export IDF 667 | OutputDocumentPath3= 668 | OutputVariantName3= 669 | OutputDefault3=0 670 | OutputType4=ExportPARASOLID 671 | OutputName4=Export PARASOLID 672 | OutputDocumentPath4= 673 | OutputVariantName4=[No Variations] 674 | OutputDefault4=0 675 | OutputType5=ExportSTEP 676 | OutputName5=Export STEP 677 | OutputDocumentPath5= 678 | OutputVariantName5=[No Variations] 679 | OutputDefault5=0 680 | OutputType6=ExportVRML 681 | OutputName6=Export VRML 682 | OutputDocumentPath6= 683 | OutputVariantName6=[No Variations] 684 | OutputDefault6=0 685 | OutputType7=MBAExportPARASOLID 686 | OutputName7=Export PARASOLID 687 | OutputDocumentPath7= 688 | OutputVariantName7= 689 | OutputDefault7=0 690 | OutputType8=MBAExportSTEP 691 | OutputName8=Export STEP 692 | OutputDocumentPath8= 693 | OutputVariantName8= 694 | OutputDefault8=0 695 | OutputType9=Save As/Export PCB 696 | OutputName9=Save As/Export PCB 697 | OutputDocumentPath9= 698 | OutputVariantName9= 699 | OutputDefault9=0 700 | OutputType10=Save As/Export Schematic 701 | OutputName10=Save As/Export Schematic 702 | OutputDocumentPath10= 703 | OutputVariantName10= 704 | OutputDefault10=0 705 | OutputType11=Specctra Design PCB 706 | OutputName11=Specctra Design PCB 707 | OutputDocumentPath11= 708 | OutputVariantName11= 709 | OutputDefault11=0 710 | OutputType12=Web ReviewOutputName 711 | OutputName12=Web Review Data 712 | OutputDocumentPath12= 713 | OutputVariantName12= 714 | OutputDefault12=0 715 | 716 | [OutputGroup10] 717 | Name=PostProcess Outputs 718 | Description= 719 | TargetPrinter=Microsoft Print to PDF 720 | PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 721 | OutputType1=Copy Files 722 | OutputName1=Copy Files 723 | OutputDocumentPath1= 724 | OutputVariantName1= 725 | OutputDefault1=0 726 | 727 | [Modification Levels] 728 | Type1=1 729 | Type2=1 730 | Type3=1 731 | Type4=1 732 | Type5=1 733 | Type6=1 734 | Type7=1 735 | Type8=1 736 | Type9=1 737 | Type10=1 738 | Type11=1 739 | Type12=1 740 | Type13=1 741 | Type14=1 742 | Type15=1 743 | Type16=1 744 | Type17=1 745 | Type18=1 746 | Type19=1 747 | Type20=1 748 | Type21=1 749 | Type22=1 750 | Type23=1 751 | Type24=1 752 | Type25=1 753 | Type26=1 754 | Type27=1 755 | Type28=1 756 | Type29=1 757 | Type30=1 758 | Type31=1 759 | Type32=1 760 | Type33=1 761 | Type34=1 762 | Type35=1 763 | Type36=1 764 | Type37=1 765 | Type38=1 766 | Type39=1 767 | Type40=1 768 | Type41=1 769 | Type42=1 770 | Type43=1 771 | Type44=1 772 | Type45=1 773 | Type46=1 774 | Type47=1 775 | Type48=1 776 | Type49=1 777 | Type50=1 778 | Type51=1 779 | Type52=1 780 | Type53=1 781 | Type54=1 782 | Type55=1 783 | Type56=1 784 | Type57=1 785 | Type58=1 786 | Type59=1 787 | Type60=1 788 | Type61=1 789 | Type62=1 790 | Type63=1 791 | Type64=1 792 | Type65=1 793 | Type66=1 794 | Type67=1 795 | Type68=1 796 | Type69=1 797 | Type70=1 798 | Type71=1 799 | Type72=1 800 | Type73=1 801 | Type74=1 802 | Type75=1 803 | Type76=1 804 | Type77=1 805 | Type78=1 806 | Type79=1 807 | Type80=1 808 | Type81=1 809 | Type82=1 810 | Type83=1 811 | Type84=1 812 | Type85=1 813 | Type86=1 814 | Type87=1 815 | Type88=1 816 | Type89=1 817 | Type90=1 818 | Type91=1 819 | Type92=1 820 | Type93=1 821 | Type94=1 822 | Type95=1 823 | Type96=1 824 | Type97=1 825 | Type98=1 826 | Type99=1 827 | Type100=1 828 | Type101=1 829 | Type102=1 830 | Type103=1 831 | Type104=1 832 | Type105=1 833 | Type106=1 834 | Type107=1 835 | Type108=1 836 | Type109=1 837 | Type110=1 838 | Type111=1 839 | Type112=1 840 | Type113=1 841 | Type114=1 842 | Type115=1 843 | Type116=1 844 | Type117=1 845 | Type118=1 846 | Type119=1 847 | Type120=1 848 | Type121=1 849 | Type122=1 850 | Type123=1 851 | Type124=1 852 | Type125=1 853 | Type126=1 854 | Type127=1 855 | Type128=1 856 | Type129=1 857 | Type130=1 858 | Type131=1 859 | Type132=1 860 | Type133=1 861 | Type134=1 862 | Type135=1 863 | Type136=1 864 | Type137=1 865 | Type138=1 866 | Type139=1 867 | Type140=1 868 | Type141=1 869 | Type142=1 870 | Type143=1 871 | Type144=1 872 | Type145=1 873 | Type146=1 874 | Type147=1 875 | Type148=1 876 | Type149=1 877 | Type150=1 878 | 879 | [Difference Levels] 880 | Type1=1 881 | Type2=1 882 | Type3=1 883 | Type4=1 884 | Type5=1 885 | Type6=1 886 | Type7=1 887 | Type8=1 888 | Type9=1 889 | Type10=1 890 | Type11=1 891 | Type12=1 892 | Type13=1 893 | Type14=1 894 | Type15=1 895 | Type16=1 896 | Type17=1 897 | Type18=1 898 | Type19=1 899 | Type20=1 900 | Type21=1 901 | Type22=1 902 | Type23=1 903 | Type24=1 904 | Type25=1 905 | Type26=1 906 | Type27=1 907 | Type28=1 908 | Type29=1 909 | Type30=1 910 | Type31=1 911 | Type32=1 912 | Type33=1 913 | Type34=1 914 | Type35=1 915 | Type36=1 916 | Type37=1 917 | Type38=1 918 | Type39=1 919 | Type40=1 920 | Type41=1 921 | Type42=1 922 | Type43=1 923 | Type44=1 924 | Type45=1 925 | Type46=1 926 | Type47=1 927 | Type48=1 928 | Type49=1 929 | Type50=1 930 | Type51=1 931 | Type52=1 932 | Type53=1 933 | Type54=1 934 | Type55=1 935 | Type56=1 936 | Type57=1 937 | Type58=1 938 | Type59=1 939 | Type60=1 940 | Type61=1 941 | Type62=1 942 | Type63=1 943 | Type64=1 944 | Type65=1 945 | Type66=1 946 | Type67=1 947 | Type68=1 948 | Type69=1 949 | Type70=1 950 | Type71=1 951 | Type72=1 952 | Type73=1 953 | Type74=1 954 | Type75=1 955 | Type76=1 956 | Type77=1 957 | Type78=1 958 | Type79=1 959 | Type80=1 960 | Type81=1 961 | 962 | [Electrical Rules Check] 963 | Type1=1 964 | Type2=1 965 | Type3=2 966 | Type4=1 967 | Type5=2 968 | Type6=2 969 | Type7=0 970 | Type8=1 971 | Type9=1 972 | Type10=1 973 | Type11=2 974 | Type12=2 975 | Type13=2 976 | Type14=1 977 | Type15=1 978 | Type16=1 979 | Type17=1 980 | Type18=1 981 | Type19=1 982 | Type20=0 983 | Type21=0 984 | Type22=0 985 | Type23=0 986 | Type24=1 987 | Type25=2 988 | Type26=0 989 | Type27=2 990 | Type28=1 991 | Type29=1 992 | Type30=1 993 | Type31=1 994 | Type32=2 995 | Type33=0 996 | Type34=2 997 | Type35=1 998 | Type36=2 999 | Type37=1 1000 | Type38=2 1001 | Type39=2 1002 | Type40=2 1003 | Type41=0 1004 | Type42=2 1005 | Type43=1 1006 | Type44=0 1007 | Type45=0 1008 | Type46=0 1009 | Type47=0 1010 | Type48=0 1011 | Type49=0 1012 | Type50=2 1013 | Type51=0 1014 | Type52=0 1015 | Type53=1 1016 | Type54=1 1017 | Type55=1 1018 | Type56=2 1019 | Type57=1 1020 | Type58=1 1021 | Type59=2 1022 | Type60=0 1023 | Type61=0 1024 | Type62=0 1025 | Type63=0 1026 | Type64=0 1027 | Type65=2 1028 | Type66=3 1029 | Type67=2 1030 | Type68=2 1031 | Type69=0 1032 | Type70=2 1033 | Type71=2 1034 | Type72=2 1035 | Type73=2 1036 | Type74=1 1037 | Type75=2 1038 | Type76=1 1039 | Type77=1 1040 | Type78=1 1041 | Type79=1 1042 | Type80=2 1043 | Type81=3 1044 | Type82=3 1045 | Type83=3 1046 | Type84=3 1047 | Type85=3 1048 | Type86=2 1049 | Type87=2 1050 | Type88=2 1051 | Type89=1 1052 | Type90=1 1053 | Type91=3 1054 | Type92=3 1055 | Type93=2 1056 | Type94=2 1057 | Type95=2 1058 | Type96=2 1059 | Type97=2 1060 | Type98=0 1061 | Type99=1 1062 | Type100=2 1063 | Type101=0 1064 | Type102=2 1065 | Type103=2 1066 | Type104=1 1067 | Type105=2 1068 | Type106=2 1069 | Type107=2 1070 | Type108=2 1071 | Type109=1 1072 | Type110=1 1073 | Type111=1 1074 | Type112=1 1075 | Type113=1 1076 | Type114=2 1077 | Type115=2 1078 | Type116=2 1079 | Type117=3 1080 | Type118=3 1081 | Type119=3 1082 | MultiChannelAlternate=0 1083 | AlternateItemFail=3 1084 | Type122=2 1085 | Type123=1 1086 | Type124=1 1087 | Type125=1 1088 | Type126=1 1089 | Type127=1 1090 | Type128=2 1091 | Type129=2 1092 | Type130=2 1093 | Type131=2 1094 | Type132=2 1095 | Type133=2 1096 | Type134=2 1097 | Type135=2 1098 | Type136=2 1099 | Type137=2 1100 | Type138=1 1101 | Type139=1 1102 | Type140=1 1103 | Type141=1 1104 | Type142=1 1105 | Type143=1 1106 | Type144=1 1107 | Type145=1 1108 | Type146=1 1109 | Type147=2 1110 | Type148=2 1111 | Type149=2 1112 | Type150=2 1113 | Type151=2 1114 | Type152=1 1115 | Type153=1 1116 | 1117 | [ERC Connection Matrix] 1118 | L1=NNNNNNNNNNNWNNNWW 1119 | L2=NNWNNNNWWWNWNWNWN 1120 | L3=NWEENEEEENEWNEEWN 1121 | L4=NNENNNWEENNWNENWN 1122 | L5=NNNNNNNNNNNNNNNNN 1123 | L6=NNENNNNEENNWNENWN 1124 | L7=NNEWNNWEENNWNENWN 1125 | L8=NWEENEENEEENNEENN 1126 | L9=NWEENEEEENEWNEEWW 1127 | L10=NWNNNNNENNEWNNEWN 1128 | L11=NNENNNNEEENWNENWN 1129 | L12=WWWWNWWNWWWNWWWNN 1130 | L13=NNNNNNNNNNNWNNNWW 1131 | L14=NWEENEEEENEWNEEWW 1132 | L15=NNENNNNEEENWNENWW 1133 | L16=WWWWNWWNWWWNWWWNW 1134 | L17=WNNNNNNNWNNNWWWWN 1135 | 1136 | [Annotate] 1137 | SortOrder=3 1138 | SortLocation=0 1139 | ReplaceSubparts=0 1140 | MatchParameter1=Comment 1141 | MatchStrictly1=1 1142 | MatchParameter2=Library Reference 1143 | MatchStrictly2=1 1144 | PhysicalNamingFormat=$Component_$RoomName 1145 | GlobalIndexSortOrder=3 1146 | GlobalIndexSortLocation=0 1147 | 1148 | [PrjClassGen] 1149 | CompClassManualEnabled=0 1150 | CompClassManualRoomEnabled=0 1151 | NetClassAutoBusEnabled=1 1152 | NetClassAutoCompEnabled=0 1153 | NetClassAutoNamedHarnessEnabled=0 1154 | NetClassManualEnabled=1 1155 | NetClassSeparateForBusSections=0 1156 | 1157 | [LibraryUpdateOptions] 1158 | SelectedOnly=0 1159 | UpdateVariants=1 1160 | UpdateToLatestRevision=1 1161 | PartTypes=0 1162 | FullReplace=1 1163 | UpdateDesignatorLock=1 1164 | UpdatePartIDLock=1 1165 | PreserveParameterLocations=1 1166 | PreserveParameterVisibility=1 1167 | DoGraphics=1 1168 | DoParameters=1 1169 | DoModels=1 1170 | AddParameters=0 1171 | RemoveParameters=0 1172 | AddModels=1 1173 | RemoveModels=1 1174 | UpdateCurrentModels=1 1175 | 1176 | [DatabaseUpdateOptions] 1177 | SelectedOnly=0 1178 | UpdateVariants=1 1179 | UpdateToLatestRevision=1 1180 | PartTypes=0 1181 | 1182 | [Comparison Options] 1183 | ComparisonOptions0=Kind=Net|MinPercent=75|MinMatch=3|ShowMatch=0|UseName=-1|InclAllRules=0 1184 | ComparisonOptions1=Kind=Net Class|MinPercent=75|MinMatch=3|ShowMatch=0|UseName=-1|InclAllRules=0 1185 | ComparisonOptions2=Kind=Component Class|MinPercent=75|MinMatch=3|ShowMatch=0|UseName=-1|InclAllRules=0 1186 | ComparisonOptions3=Kind=Rule|MinPercent=75|MinMatch=3|ShowMatch=0|UseName=-1|InclAllRules=0 1187 | ComparisonOptions4=Kind=Differential Pair|MinPercent=50|MinMatch=1|ShowMatch=0|UseName=0|InclAllRules=0 1188 | ComparisonOptions5=Kind=Structure Class|MinPercent=75|MinMatch=3|ShowMatch=0|UseName=-1|InclAllRules=0 1189 | 1190 | [SmartPDF] 1191 | PageOptions=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 1192 | Configuration_Name1=OutputConfigurationParameter1 1193 | Configuration_Item1=DesignatorDisplayMode=Physical|PrintArea=DesignExtent|PrintAreaLowerLeftCornerX=0|PrintAreaLowerLeftCornerY=0|PrintAreaUpperRightCornerX=0|PrintAreaUpperRightCornerY=0|Record=PcbPrintView|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1194 | Configuration_Name2=OutputConfigurationParameter2 1195 | Configuration_Item2=IncludeBoardCutouts=False|IncludeBottomLayerComponents=True|IncludeMultiLayerComponents=True|IncludeTopLayerComponents=True|IncludeViewports=True|Index=0|Mirror=False|Name=Multilayer Composite Print|PadNumberFontSize=14|Record=PcbPrintOut|ShowHoles=False|ShowPadNets=False|ShowPadNumbers=False|SubstituteFonts=False|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1196 | Configuration_Name3=OutputConfigurationParameter3 1197 | Configuration_Item3=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=TopOverlay|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1198 | Configuration_Name4=OutputConfigurationParameter4 1199 | Configuration_Item4=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=TopLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1200 | Configuration_Name5=OutputConfigurationParameter5 1201 | Configuration_Item5=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=MidLayer1|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1202 | Configuration_Name6=OutputConfigurationParameter6 1203 | Configuration_Item6=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=MidLayer2|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1204 | Configuration_Name7=OutputConfigurationParameter7 1205 | Configuration_Item7=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=BottomLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1206 | Configuration_Name8=OutputConfigurationParameter8 1207 | Configuration_Item8=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=MultiLayer|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1208 | Configuration_Name9=OutputConfigurationParameter9 1209 | Configuration_Item9=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=BottomOverlay|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1210 | Configuration_Name10=OutputConfigurationParameter10 1211 | Configuration_Item10=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical1|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1212 | Configuration_Name11=OutputConfigurationParameter11 1213 | Configuration_Item11=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical5|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1214 | Configuration_Name12=OutputConfigurationParameter12 1215 | Configuration_Item12=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical13|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1216 | Configuration_Name13=OutputConfigurationParameter13 1217 | Configuration_Item13=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical15|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1218 | Configuration_Name14=OutputConfigurationParameter14 1219 | Configuration_Item14=CArc=Full|CFill=Full|Comment=Full|Coordinate=Full|CPad=Full|CRegion=Full|CText=Full|CTrack=Full|CVia=Full|Designator=Full|Dimension=Full|DLayer1=TopLayer|DLayer2=BottomLayer|DrillType=Regular|FArc=Full|FFill=Full|FPad=Full|FRegion=Full|FText=Full|FTrack=Full|FVia=Full|Layer=Mechanical16|Polygon=Full|PrintOutIndex=0|Record=PcbPrintLayer|DocumentPath=C:\Users\lambetam\Documents\GitHub\phalanx_fair\rehand\design\sense_logic\metahand_senselogic\metahand_sense_logic.PcbDoc 1220 | 1221 | -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_logic/sense_logic.PrjPcbStructure: -------------------------------------------------------------------------------- 1 | Record=TopLevelDocument|FileName=AUX_CONNECTOR.SchDoc|SheetNumber=2 2 | Record=NoMainPathDocument|SourceDocument=AUX_CONNECTOR.SchDoc|FileName=LOGIC.SchDoc|SheetNumber=5 3 | Record=NoMainPathDocument|SourceDocument=AUX_CONNECTOR.SchDoc|FileName=LOGIC_CONNECTOR.SchDoc|SheetNumber=4 4 | Record=NoMainPathDocument|SourceDocument=AUX_CONNECTOR.SchDoc|FileName=SPINE_CONNECTOR.SchDoc|SheetNumber=1 5 | Record=NoMainPathDocument|SourceDocument=AUX_CONNECTOR.SchDoc|FileName=USB_CONNECTOR.SchDoc|SheetNumber=3 6 | -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_patch/CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_patch/CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_patch/SENSE.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_patch/SENSE.SchDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_patch/sense_patch.BomDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_patch/sense_patch.BomDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_patch/sense_patch.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/ecad/basic/sense_patch/sense_patch.PcbDoc -------------------------------------------------------------------------------- /hardware/ecad/basic/sense_patch/sense_patch.PrjPcbStructure: -------------------------------------------------------------------------------- 1 | Record=TopLevelDocument|FileName=CONNECTOR.SchDoc|SheetNumber=1 2 | Record=NoMainPathDocument|SourceDocument=CONNECTOR.SchDoc|FileName=SENSE.SchDoc|SheetNumber=2 3 | -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_hand_logic_guidelines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_hand_logic_guidelines.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_hand_logic_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_hand_logic_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_hand_sense_guidelines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_hand_sense_guidelines.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_hand_sense_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_hand_sense_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_sense_logic_guidelines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_sense_logic_guidelines.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_sense_logic_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_sense_logic_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_sense_patch_guidelines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_sense_patch_guidelines.pdf -------------------------------------------------------------------------------- /hardware/schematics/advanced/plexus_sense_patch_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/advanced/plexus_sense_patch_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/basic/plexus_hand_logic_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/basic/plexus_hand_logic_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/basic/plexus_hand_sense_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/basic/plexus_hand_sense_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/basic/plexus_sense_patch_logic_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/basic/plexus_sense_patch_logic_sch.pdf -------------------------------------------------------------------------------- /hardware/schematics/basic/plexus_sense_patch_sch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/schematics/basic/plexus_sense_patch_sch.pdf -------------------------------------------------------------------------------- /hardware/templates/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/README.md -------------------------------------------------------------------------------- /hardware/templates/advanced/hand_sense_template/CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/hand_sense_template/CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/templates/advanced/hand_sense_template/SENSE.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/hand_sense_template/SENSE.SchDoc -------------------------------------------------------------------------------- /hardware/templates/advanced/hand_sense_template/SENSE_LOWER.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/hand_sense_template/SENSE_LOWER.SchDoc -------------------------------------------------------------------------------- /hardware/templates/advanced/hand_sense_template/plexus_hand_sense_template.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/hand_sense_template/plexus_hand_sense_template.PcbDoc -------------------------------------------------------------------------------- /hardware/templates/advanced/sense_template/CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/sense_template/CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/templates/advanced/sense_template/SENSE.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/sense_template/SENSE.SchDoc -------------------------------------------------------------------------------- /hardware/templates/advanced/sense_template/plexus_sense_template.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/advanced/sense_template/plexus_sense_template.PcbDoc -------------------------------------------------------------------------------- /hardware/templates/basic/hand_sense_template/CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/hand_sense_template/CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/templates/basic/hand_sense_template/LOGIC.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/hand_sense_template/LOGIC.SchDoc -------------------------------------------------------------------------------- /hardware/templates/basic/hand_sense_template/SENSE.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/hand_sense_template/SENSE.SchDoc -------------------------------------------------------------------------------- /hardware/templates/basic/hand_sense_template/hand_sense_template.PCBDwf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/hand_sense_template/hand_sense_template.PCBDwf -------------------------------------------------------------------------------- /hardware/templates/basic/hand_sense_template/hand_sense_template.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/hand_sense_template/hand_sense_template.PcbDoc -------------------------------------------------------------------------------- /hardware/templates/basic/sense_template/CONNECTOR.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/sense_template/CONNECTOR.SchDoc -------------------------------------------------------------------------------- /hardware/templates/basic/sense_template/SENSE.SchDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/sense_template/SENSE.SchDoc -------------------------------------------------------------------------------- /hardware/templates/basic/sense_template/sense_template.BomDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/sense_template/sense_template.BomDoc -------------------------------------------------------------------------------- /hardware/templates/basic/sense_template/sense_template.PcbDoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/hardware/templates/basic/sense_template/sense_template.PcbDoc -------------------------------------------------------------------------------- /plexus/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Digit Plexus 3 | This guide will help you set up the environment, build the ROS2 package Digit Plexus , and join the growing community of developers and researchers. 4 | 5 | ## 🛠 Virtual Environment Setup 6 | 7 | To install and activate the virtual environment for Digit Plexus, run the following commands: 8 | 9 | ``` 10 | cd digit-plexus 11 | ./plexus/install_plexus_venv.sh 12 | ``` 13 | This will handle the necessary dependencies and ensure your environment is ready for development. 14 | 15 | ## 🛠 Build ROS2 pkg 16 | ``` 17 | mkdir -p plexus_ws/src 18 | cd plexus_ws/src 19 | git clone https://github.com/facebookresearch/digit-plexus.git 20 | cd .. 21 | sh ./src/digit-plexus/plexus/ros2/plexus_pkg/colcon_build.sh 22 | ``` 23 | 24 | ## 🛠 Install Digit Plexus pkg 25 | ``` 26 | cd plexus_ws/src/digit-plexus/ 27 | pip install -e . 28 | ``` 29 | 30 | This creates the workspace, builds the source, and prepares everything for use with ROS2 nodes and topics. 31 | 32 | ## 🚀 Run Commands 33 | To launch the Digit Plexus package, use the following command: 34 | 35 | This launches the allegro hand with plexus. 36 | ```bash 37 | ros2 launch plexus_pkg allegro_hand_launch.py 38 | ``` 39 | 40 | For Sensor Patch 41 | ``` 42 | ros2 launch plexus_pkg sensor_patch_launch.py 43 | ``` 44 | -------------------------------------------------------------------------------- /plexus/install_plexus_venv.sh: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # All rights reserved. 3 | 4 | # This source code is licensed under the license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | #!/bin/bash -e 9 | shopt -s expand_aliases 10 | if type -P micromamba; then 11 | echo "micromamba detect, using micromamba inplace of mamba" 12 | alias conda=micromamba 13 | eval "$(micromamba shell hook --shell bash)" 14 | elif type -P mamba || type -P conda; then 15 | eval "$(conda shell.bash hook)" 16 | else 17 | echo please install mamba or micromamba 18 | exit 19 | fi 20 | 21 | 22 | # if ENV_NAME is not set, then set it to _plexus 23 | 24 | ENV_NAME=_plexus 25 | 26 | unset PYTHONPATH LD_LIBRARY_PATH 27 | 28 | # remove any exisiting env 29 | mamba remove -y -n $ENV_NAME --all || true #will fail in fresh install 30 | 31 | # create new env for ROS 32 | mamba create -y --name $ENV_NAME --override-channels --no-channel-priority -c tingfan -c conda-forge python=3.8 \ 33 | python-can compilers cmake pkg-config make ninja colcon-common-extensions \ 34 | ros-humble-ros-base ros-humble-foxglove-bridge ros-humble-realsense2-camera ros-humble-ros1-bridge ros-humble-allegro-hand-controllers \ 35 | ros-humble-rosbag2-storage-mcap ros-humble-compressed-image-transport ros-humble-allegro-hand-controllers ros-humble-xacro ros-humble-control-msgs \ 36 | ros-humble-joint-state-publisher libopencv=*=py* \ 37 | portaudio 38 | 39 | conda activate $ENV_NAME 40 | pip install termcolor tensorboardX gitpython pytest==8.0.1 pytest-md-report setuptools==58.2.0 pre-commit 41 | pip install sophuspy scipy matplotlib 42 | pip install cython omegaconf hydra-core digit-interface 43 | 44 | # Remove pyudev directory that causes OSError 45 | rm -fr $CONDA_PREFIX/lib/udev 46 | -------------------------------------------------------------------------------- /plexus/ros2/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Digit-Plexus 3 | 4 | See the [CONTRIBUTING](CONTRIBUTING.md) file for how to help out. 5 | 6 | ## License 7 | Digit-Plexus is Attribution-NonCommercial 4.0 International licensed, as found in the [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/.gitignore: -------------------------------------------------------------------------------- 1 | ros_ws 2 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | cmake_minimum_required(VERSION 3.5) 10 | project(plexus_pkg) 11 | find_package(ament_cmake REQUIRED) 12 | find_package(rosidl_default_generators REQUIRED) 13 | find_package(std_msgs) 14 | 15 | rosidl_generate_interfaces(${PROJECT_NAME} 16 | "msg/PowerStatus.msg" 17 | DEPENDENCIES builtin_interfaces std_msgs 18 | ) 19 | 20 | install(PROGRAMS 21 | plexus_pkg/allegro_info_node.py 22 | plexus_pkg/allegro_controller_node.py 23 | DESTINATION lib/${PROJECT_NAME} 24 | ) 25 | install(DIRECTORY 26 | DESTINATION lib/${PROJECT_NAME} 27 | ) 28 | 29 | install(DIRECTORY 30 | launch 31 | DESTINATION share/${PROJECT_NAME} 32 | ) 33 | 34 | 35 | ament_package() 36 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/colcon_build.sh: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | #!/bin/bash -e 10 | if [ "x$ROS_DISTRO" = "x" ]; then 11 | echo "please first initialize ROS env (e.g., conda activate _plexus)" 12 | exit 13 | fi 14 | 15 | if git rev-parse --git-dir >/dev/null 2>&1; then 16 | REPOROOT=$(git rev-parse --show-toplevel) 17 | else 18 | REPOROOT=$PWD/src/digit-plexus/ 19 | fi 20 | 21 | if [ $(basename $PWD) = "plexus_ws" ]; then 22 | colcon build --base-paths $REPOROOT/plexus/ros2 \ 23 | --packages-select plexus_pkg \ 24 | --cmake-args "-DPython3_EXECUTABLE=$(which python3)" --cmake-clean-cache \ 25 | --symlink-install --event-handlers console_direct+ 26 | else 27 | echo please invoke from plexus_ws 28 | fi 29 | 30 | echo "please" 31 | echo 32 | echo "source ./install/setup.$(basename $SHELL)" 33 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/launch/allegro_hand_launch.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | #!/usr/bin/env python3 9 | import os 10 | from pathlib import Path 11 | from launch import LaunchDescription 12 | from launch.actions import ( 13 | RegisterEventHandler, 14 | EmitEvent, 15 | LogInfo, 16 | OpaqueFunction, 17 | ) 18 | from launch.event_handlers import OnProcessExit 19 | from launch.events import Shutdown 20 | from launch_ros.actions import Node 21 | from plexus.ros2.plexus_pkg.plexus_pkg.allegro_driver import AllegroDriver 22 | import can 23 | from typing import Dict 24 | 25 | def get_allegro_configs() -> Dict[str, Path]: 26 | launch_root = os.path.dirname(os.path.abspath(__file__)) 27 | interfaces=can.detect_available_configs(interfaces="socketcan") 28 | configs = {} 29 | for iface in interfaces: 30 | allegro_driver = AllegroDriver(can_channel=iface["channel"]) 31 | allegro_serial = allegro_driver.get_serial().lower() 32 | allegro_config_serial = Path(f"{launch_root}/allegro_node_params_{allegro_serial}.yaml") 33 | allegro_config_default= Path(f"{launch_root}/allegro_node_params.yaml") 34 | 35 | if allegro_config_serial.exists(): 36 | print(f'using hand specific config - {allegro_config_serial.absolute()}') 37 | configs[iface["channel"]] = allegro_config_serial 38 | else: 39 | print(f'using default config - {allegro_config_default.absolute()}') 40 | configs[iface["channel"]] = allegro_config_default 41 | 42 | return configs 43 | 44 | 45 | def _generate_launch_description(context): 46 | configs = get_allegro_configs() 47 | nodes = [] 48 | for i, (can_interface, config) in enumerate(configs.items()): 49 | _ns = f"allegroHand{i}" if i > 0 else "allegroHand" 50 | allegro_controller_node = Node( 51 | namespace=_ns, 52 | package="plexus_pkg", 53 | executable="allegro_controller_node.py", 54 | name="allegro_controller", 55 | parameters=[config, {"can_interface": can_interface}], 56 | respawn=True 57 | ) 58 | nodes.append(allegro_controller_node) 59 | 60 | allegro_info_node = Node( 61 | namespace=_ns, 62 | package="plexus_pkg", 63 | executable="allegro_info_node.py", 64 | name="allegro_info", 65 | parameters=[config, {"can_interface": can_interface}], 66 | ) 67 | nodes.append(allegro_info_node) 68 | 69 | 70 | shutdown_action = RegisterEventHandler( 71 | OnProcessExit( 72 | target_action=allegro_controller_node, 73 | on_exit=[ 74 | LogInfo(msg="critical node failure"), 75 | EmitEvent(event=Shutdown( 76 | reason='critical node failure')) 77 | ] 78 | ) 79 | ) 80 | nodes.append(shutdown_action) 81 | return nodes 82 | 83 | def generate_launch_description(): 84 | return LaunchDescription([OpaqueFunction(function=_generate_launch_description)]) -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/launch/allegro_node_params.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | /allegro: 10 | ros__parameters: 11 | gains_pd/d/j00: 15.0 12 | gains_pd/d/j01: 20.0 13 | gains_pd/d/j02: 15.0 14 | gains_pd/d/j03: 15.0 15 | 16 | gains_pd/d/j10: 15.0 17 | gains_pd/d/j11: 20.0 18 | gains_pd/d/j12: 15.0 19 | gains_pd/d/j13: 15.0 20 | 21 | gains_pd/d/j20: 15.0 22 | gains_pd/d/j21: 20.0 23 | gains_pd/d/j22: 15.0 24 | gains_pd/d/j23: 15.0 25 | 26 | gains_pd/d/j30: 30.0 27 | gains_pd/d/j31: 20.0 28 | gains_pd/d/j32: 20.0 29 | gains_pd/d/j33: 15.0 30 | 31 | gains_pd/p/j00: 6000.0 32 | gains_pd/p/j01: 6000.0 33 | gains_pd/p/j02: 6000.0 34 | gains_pd/p/j03: 6000.0 35 | 36 | gains_pd/p/j10: 6000.0 37 | gains_pd/p/j11: 6000.0 38 | gains_pd/p/j12: 6000.0 39 | gains_pd/p/j13: 6000.0 40 | 41 | gains_pd/p/j20: 6000.0 42 | gains_pd/p/j21: 6000.0 43 | gains_pd/p/j22: 6000.0 44 | gains_pd/p/j23: 6000.0 45 | 46 | gains_pd/p/j30: 6000.0 47 | gains_pd/p/j31: 6000.0 48 | gains_pd/p/j32: 6000.0 49 | gains_pd/p/j33: 6000.0 50 | hand_info/manufacturer: manu 51 | hand_info/origin: origin 52 | hand_info/robot_name: metahand 53 | hand_info/serial: serial 54 | hand_info/version: 4.0 55 | hand_info/which_hand: Right 56 | initial_position/j00: 0.0 57 | initial_position/j01: -10.0 58 | initial_position/j02: 45.0 59 | initial_position/j03: 45.0 60 | initial_position/j10: 0.0 61 | initial_position/j11: -10.0 62 | initial_position/j12: 45.0 63 | initial_position/j13: 45.0 64 | initial_position/j20: 5.0 65 | initial_position/j21: -5.0 66 | initial_position/j22: 50.0 67 | initial_position/j23: 45.0 68 | initial_position/j30: 60.0 69 | initial_position/j31: 25.0 70 | initial_position/j32: 15.0 71 | initial_position/j33: 45.0 72 | 73 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/launch/allegro_node_params_127r.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | /allegroHand/allegro_controller: 10 | ros__parameters: 11 | gains_pd/0/d: 0.10 12 | gains_pd/0/p: 4.0 13 | gains_pd/1/d: 0.10 14 | gains_pd/1/p: 4.0 15 | gains_pd/10/d: 0.10 16 | gains_pd/10/p: 4.0 17 | gains_pd/11/d: 0.10 18 | gains_pd/11/p: 4.0 19 | gains_pd/12/d: 0.10 20 | gains_pd/12/p: 4.0 21 | gains_pd/13/d: 0.10 22 | gains_pd/13/p: 4.0 23 | gains_pd/14/d: 0.10 24 | gains_pd/14/p: 4.0 25 | gains_pd/15/d: 0.10 26 | gains_pd/15/p: 4.0 27 | gains_pd/2/d: 0.10 28 | gains_pd/2/p: 4.0 29 | gains_pd/3/d: 0.10 30 | gains_pd/3/p: 4.0 31 | gains_pd/4/d: 0.10 32 | gains_pd/4/p: 4.0 33 | gains_pd/5/d: 0.10 34 | gains_pd/5/p: 4.0 35 | gains_pd/6/d: 0.10 36 | gains_pd/6/p: 4.0 37 | gains_pd/7/d: 0.10 38 | gains_pd/7/p: 4.0 39 | gains_pd/8/d: 0.10 40 | gains_pd/8/p: 4.0 41 | gains_pd/9/d: 0.10 42 | gains_pd/9/p: 4.0 43 | position_offset/0: 0.0 44 | position_offset/1: 0.0 45 | position_offset/10: 0.0 46 | position_offset/11: 0.0 47 | position_offset/12: 0.0 48 | position_offset/13: 0.0 49 | position_offset/14: 0.0 50 | position_offset/10: 0.0 51 | position_offset/2: 0.0 52 | position_offset/3: 0.0 53 | position_offset/4: 0.0 54 | position_offset/5: 0.0 55 | position_offset/6: 0.0 56 | position_offset/7: 0.0 57 | position_offset/8: 0.0 58 | position_offset/9: 0.0 59 | qv_alpha: 0.7 60 | torque_limit: 0.7 61 | use_sim_time: false 62 | 63 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/launch/dual_hand_launch.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # All rights reserved. 3 | 4 | # This source code is licensed under the license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | #!/usr/bin/env python3 8 | import os 9 | import can 10 | 11 | from typing import Dict 12 | from pathlib import Path 13 | 14 | from launch import LaunchDescription 15 | from launch.actions import ( 16 | RegisterEventHandler, 17 | EmitEvent, 18 | LogInfo, 19 | OpaqueFunction, 20 | ) 21 | from launch.event_handlers import OnProcessExit 22 | from launch.events import Shutdown 23 | from launch_ros.actions import Node 24 | 25 | from plexus.ros2.plexus_pkg.plexus_pkg.allegro_driver import AllegroDriver 26 | 27 | 28 | 29 | def get_allegro_configs() -> Dict[str, Path]: 30 | launch_root = os.path.dirname(os.path.abspath(__file__)) 31 | interfaces = can.detect_available_configs(interfaces="socketcan") 32 | configs = {} 33 | 34 | for iface in interfaces: 35 | allegro_driver = AllegroDriver(can_channel=iface["channel"]) 36 | try: 37 | allegro_serial = allegro_driver.get_serial().lower() 38 | print("Read serial from ", iface, allegro_serial) 39 | except TimeoutError: 40 | print("Failed to read serial from ", iface) 41 | continue 42 | 43 | matched_hand_serial = allegro_driver.get_info().get("hand", None) 44 | 45 | if not matched_hand_serial: 46 | raise ValueError(f"Unknown Allegro Hand serial number: {allegro_serial}") 47 | 48 | allegro_config_serial = Path( 49 | f"{launch_root}/allegro_node_params_{allegro_serial}.yaml" 50 | ) 51 | allegro_config_default = Path(f"{launch_root}/allegro_node_params.yaml") 52 | 53 | config_path = ( 54 | allegro_config_serial 55 | if allegro_config_serial.exists() 56 | else allegro_config_default 57 | ) 58 | print(f"Using config for {matched_hand_serial} - {config_path.absolute()}") 59 | configs[iface["channel"]] = (config_path, matched_hand_serial) 60 | 61 | return configs 62 | 63 | 64 | def _generate_launch_description(context): 65 | configs = get_allegro_configs() 66 | nodes = [] 67 | 68 | for can_interface, (config, hand) in configs.items(): 69 | _ns = f"/hand/{hand}" 70 | 71 | allegro_controller_node = Node( 72 | namespace=_ns, 73 | package="plexus_pkg", 74 | executable="allegro_controller_node.py", 75 | name="allegro_controller", 76 | parameters=[config, {"can_interface": can_interface}], 77 | respawn=True, 78 | ) 79 | nodes.append(allegro_controller_node) 80 | 81 | allegro_info_node = Node( 82 | namespace=_ns, 83 | package="plexus_pkg", 84 | executable="allegro_info_node.py", 85 | name="allegro_info", 86 | parameters=[config, {"can_interface": can_interface}], 87 | ) 88 | nodes.append(allegro_info_node) 89 | 90 | shutdown_action = RegisterEventHandler( 91 | OnProcessExit( 92 | target_action=allegro_controller_node, 93 | on_exit=[ 94 | LogInfo(msg="Plexus critical node failure"), 95 | EmitEvent(event=Shutdown(reason="Plexus critical node failure")), 96 | ], 97 | ) 98 | ) 99 | nodes.append(shutdown_action) 100 | return nodes 101 | 102 | 103 | def generate_launch_description(): 104 | return LaunchDescription([OpaqueFunction(function=_generate_launch_description)]) 105 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/launch/sensor_patch_launch.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | import pathlib 9 | from ament_index_python.packages import get_package_share_directory 10 | from launch import LaunchDescription 11 | from launch_ros.actions import Node 12 | 13 | def generate_launch_description(): 14 | # Define the metahand node 15 | metahand_node = Node( 16 | package="plexus_pkg", 17 | executable="sensor_patch.py", 18 | name="plexus_hand", 19 | output="screen" 20 | ) 21 | 22 | # Return the LaunchDescription with the metahand node 23 | return LaunchDescription([metahand_node]) 24 | 25 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/msg/PowerStatus.msg: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # All rights reserved. 3 | 4 | # This source code is licensed under the license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | std_msgs/Header header 9 | float32 voltage 10 | float32 current 11 | float32 power 12 | 13 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | plexus_pkg 5 | 0.0.1 6 | A robotics hardware platform for the integration sensors and end effectors into a common platform. 7 | Chaithanya krishna 8 | CC BY-NC 4.0 9 | ament_cmake 10 | rosidl_default_generators 11 | rosidl_default_runtime 12 | rosidl_interface_packages 13 | 14 | ament_lint_auto 15 | ament_lint_common 16 | 17 | 18 | ament_cmake 19 | 20 | 21 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/plexus_pkg/allegro_client.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | # 6 | # -------------------------------------------------------- 7 | # Based on: 8 | # https://github.com/felixduvallet/allegro-hand-ros/blob/master/allegro_hand/src/allegro_hand/liballegro.py 9 | # -------------------------------------------------------- 10 | 11 | import traceback 12 | from typing import List, Tuple, Union 13 | 14 | from rcl_interfaces.msg import Parameter, ParameterType, ParameterValue 15 | from rclpy.node import Node 16 | from rclpy.parameter_service import GetParameters, SetParameters 17 | from sensor_msgs.msg import JointState 18 | from std_msgs.msg import String 19 | 20 | 21 | class AllegroRobot(Node): 22 | def __init__( 23 | self, hand_topic_prefix: str = "allegroHand", num_joints: int = 16 24 | ) -> None: 25 | """Simple python interface to the Allegro Hand. 26 | 27 | The AllegroClient is a simple python interface to an allegro 28 | robot hand. It enables you to command the hand directly through 29 | python library calls (joint positions, joint torques, or 'named' 30 | grasps). 31 | 32 | The constructors sets up publishers and subscribes to the joint states 33 | topic for the hand. 34 | 35 | Note on hand topic names: The default topic (allegroHand/foo) can be 36 | remapped to a different topic prefix (allegroHand_0/foo) in one of two 37 | ways: 38 | 1. pass in allegroHand_0 as the hand_topic_prefix 39 | 2. remap *each* topic on the command line 40 | (allegroHand/joint_cmd:=allegroHand_0/joint_cmd) 41 | The first method is probably easier. 42 | 43 | :param hand_topic_prefix: The prefix to use for *all* hand 44 | topics (publishing & subscribing). 45 | 46 | :param num_joints: Number of expected joints, used when 47 | commanding joint positions. 48 | 49 | """ 50 | super().__init__("hand_commander") 51 | 52 | # Topics (that can be remapped) for named graps 53 | # (ready/envelop/grasp/etc.), joint commands (position and 54 | # velocity), joint state (subscribing), and envelop torque. Note that 55 | # we can change the hand topic prefix (for example, to allegroHand_0) 56 | # instead of remapping it at the command line. 57 | hand_topic_prefix = hand_topic_prefix.rstrip("/") 58 | topic_grasp_command = "{}/lib_cmd".format(hand_topic_prefix) 59 | topic_joint_command = "{}/joint_cmd".format(hand_topic_prefix) 60 | topic_joint_state = "{}/joint_states".format(hand_topic_prefix) 61 | 62 | # Publishers for above topics. 63 | self.pub_grasp = self.create_publisher(String, topic_grasp_command, 10) 64 | self.pub_joint = self.create_publisher(JointState, topic_joint_command, 10) 65 | self.create_subscription( 66 | JointState, topic_joint_state, self._joint_state_callback, 10 67 | ) 68 | self._joint_state = None 69 | 70 | self._num_joints = num_joints 71 | 72 | self.get_logger().info( 73 | "Allegro Client start with hand topic: {}".format(hand_topic_prefix) 74 | ) 75 | 76 | # "Named" grasps are those provided by the bhand library. These can be 77 | # commanded directly and the hand will execute them. The keys are more 78 | # human-friendly names, the values are the expected names from the 79 | # allegro controller side. Multiple strings mapping to the same value 80 | # are allowed. 81 | self._named_grasps_mappings = { 82 | "home": "home", 83 | "off": "off", 84 | # "gravity_compensation": "gravcomp", 85 | # "gravity compensation": "gravcomp", 86 | # "gravity": "gravcomp", 87 | # "ready": "ready", 88 | # "three_finger_grasp": "grasp_3", 89 | # "three finger grasp": "grasp_3", 90 | # "four_finger_grasp": "grasp_4", 91 | # "four finger grasp": "grasp_4", 92 | # "index_pinch": "pinch_it", 93 | # "index pinch": "pinch_it", 94 | # "middle_pinch": "pinch_mt", 95 | # "middle pinch": "pinch_mt", 96 | # "envelop": "envelop", 97 | } 98 | self.joint_names = [f"allegro_joint_{i}.0" for i in range(self._num_joints)] 99 | 100 | def disconnect(self) -> None: 101 | """ 102 | Disconnect the allegro client from the hand by sending the 'off' 103 | command. This is principally a convenience binding. 104 | 105 | Note that we don't actually 'disconnect', so you could technically 106 | continue sending other commands after this. 107 | """ 108 | self.command_hand_configuration("off") 109 | 110 | def _joint_state_callback(self, data: JointState) -> None: 111 | self._joint_state = data 112 | 113 | def get_p_gain(self) -> List[float]: 114 | client = self.create_client( 115 | GetParameters, "/allegroHand/allegro_controller/get_parameters" 116 | ) 117 | ready = client.wait_for_service(timeout_sec=5.0) 118 | if not ready: 119 | raise RuntimeError("Wait for service timed out") 120 | 121 | request = GetParameters.Request() 122 | request.names = [f"gains_pd/{i}/p" for i in range(self.num_joints)] 123 | result = client.call(request) 124 | return [v.double_value for v in result.values] 125 | 126 | def set_p_gain(self, gain: List[float]) -> None: 127 | client = self.create_client( 128 | SetParameters, "/allegroHand/allegro_controller/set_parameters" 129 | ) 130 | ready = client.wait_for_service(timeout_sec=5.0) 131 | if not ready: 132 | raise RuntimeError("Wait for service timed out") 133 | 134 | request = SetParameters.Request() 135 | request.parameters = [ 136 | Parameter( 137 | name=f"gains_pd/{i}/p", 138 | value=ParameterValue( 139 | type=ParameterType.PARAMETER_DOUBLE, double_value=gain[i] 140 | ), 141 | ) 142 | for i in range(self.num_joints) 143 | ] 144 | result = client.call(request) 145 | assert all( 146 | [result.results[i].successful for i in range(self.num_joints)] 147 | ), "gain setting failed" 148 | 149 | def command_joint_position(self, desired_pose: List) -> bool: 150 | """ 151 | Command a specific desired hand pose. 152 | 153 | The desired pose must be the correct dimensionality (self._num_joints). 154 | Only the pose is commanded, and **no bound-checking happens here**: 155 | any commanded pose must be valid or Bad Things May Happen. (Generally, 156 | values between 0.0 and 1.5 are fine, but use this at your own risk.) 157 | 158 | :param desired_pose: The desired joint configurations. 159 | :return: True if pose is published, False otherwise. 160 | """ 161 | 162 | # Check that the desired pose can have len() applied to it, and that 163 | # the number of dimensions is the same as the number of hand joints. 164 | if ( 165 | not hasattr(desired_pose, "__len__") 166 | or len(desired_pose) != self._num_joints 167 | ): 168 | self.get_logger().warn( 169 | "Desired pose must be a {}-d array: got {}.".format( 170 | self._num_joints, desired_pose 171 | ) 172 | ) 173 | return False 174 | 175 | msg = JointState() # Create and publish 176 | msg.header.stamp = self.get_clock().now().to_msg() 177 | msg.name = self.joint_names 178 | try: 179 | msg.position.fromlist(list(desired_pose)) 180 | self.pub_joint.publish(msg) 181 | self.get_logger().debug("Published desired pose.") 182 | return True 183 | except Exception: 184 | self.get_logger().error(traceback.format_exc()) 185 | self.get_logger.warn( 186 | "Incorrect type for desired pose: {}.".format(desired_pose) 187 | ) 188 | return False 189 | 190 | def command_joint_torques(self, desired_torques: List) -> bool: 191 | """ 192 | Command a desired torque for each joint. 193 | 194 | The desired torque must be the correct dimensionality 195 | (self._num_joints). Similarly to poses, we do not sanity-check 196 | the inputs. As a rule of thumb, values between +- 0.5 are fine. 197 | 198 | :param desired_torques: The desired joint torques. 199 | :return: True if message is published, False otherwise. 200 | """ 201 | 202 | # Check that the desired torque vector can have len() applied to it, 203 | # and that the number of dimensions is the same as the number of 204 | # joints. This prevents passing singletons or incorrectly-shaped lists 205 | # to the message creation (which does no checking). 206 | if ( 207 | not hasattr(desired_torques, "__len__") 208 | or len(desired_torques) != self._num_joints 209 | ): 210 | self.get_logger().warn( 211 | "Desired torques must be a {}-d array: got {}.".format( 212 | self._num_joints, desired_torques 213 | ) 214 | ) 215 | return False 216 | 217 | msg = JointState() # Create and publish 218 | try: 219 | msg.header.stamp = self.get_clock().now().to_msg() 220 | msg.name = self.joint_names 221 | msg.effort = desired_torques 222 | self.pub_joint.publish(msg) 223 | self.get_logger().debug("Published desired torques.") 224 | return True 225 | except Exception: 226 | self.get_logger().error(traceback.format_exc()) 227 | self.get_logger().logwarn( 228 | "Incorrect type for desired torques: {}.".format(desired_torques) 229 | ) 230 | return False 231 | 232 | def poll_joint_position(self, wait: bool = False) -> Union[Tuple, None]: 233 | """Get the current joint positions of the hand. 234 | 235 | :param wait: If true, waits for a 'fresh' state reading. 236 | :return: Joint positions, or None if none have been received. 237 | """ 238 | if wait: # Clear joint state and wait for the next reading. 239 | self._joint_state = None 240 | rate = self.create_rate(1000) 241 | while not self._joint_state: 242 | rate.sleep() 243 | self.destroy_rate(rate) # type: ignore[unreachable] 244 | 245 | if self._joint_state: 246 | return ( # type: ignore[unreachable] 247 | self._joint_state.position, 248 | self._joint_state.effort, 249 | ) 250 | else: 251 | return None 252 | 253 | def command_hand_configuration(self, hand_config: str) -> bool: 254 | """ 255 | Command a named hand configuration (e.g., pinch_index, envelop, 256 | gravity_compensation). 257 | 258 | The internal hand configuration names are defined in the 259 | AllegroNodeGrasp controller file. More human-friendly names are used 260 | by defining them as 'shortcuts' in the _named_grasps_mapping variable. 261 | Multiple strings can map to the same commanded configuration. 262 | 263 | :param hand_config: A human-friendly string of the desired 264 | configuration. 265 | :return: True if the grasp was known and commanded, false otherwise. 266 | """ 267 | 268 | # Only use known named grasps. 269 | if hand_config in self._named_grasps_mappings: 270 | # Look up conversion of string -> msg 271 | msg = String() 272 | msg.data = self._named_grasps_mappings[hand_config] 273 | self.get_logger().debug("Commanding grasp: {}".format(msg.data)) 274 | self.pub_grasp.publish(msg) 275 | return True 276 | else: 277 | self.get_logger().warn( 278 | "Unable to command unknown grasp {}".format(hand_config) 279 | ) 280 | return False 281 | 282 | def list_hand_configurations(self) -> List[str]: 283 | """ 284 | :return: List of valid strings for named hand configurations (including 285 | duplicates). 286 | """ 287 | return [k for k in self._named_grasps_mappings] 288 | 289 | @property 290 | def num_joints(self) -> int: 291 | return self._num_joints 292 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/plexus_pkg/allegro_controller_node.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # All rights reserved. 5 | 6 | # This source code is licensed under the license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | 10 | 11 | from typing import List 12 | import numpy as np 13 | import argparse 14 | 15 | import rclpy 16 | from rclpy.utilities import remove_ros_args 17 | import rclpy.node 18 | import rclpy.executors 19 | from sensor_msgs.msg import JointState 20 | from std_msgs.msg import String 21 | from rclpy.qos import qos_profile_system_default 22 | from rcl_interfaces.msg import SetParametersResult, Parameter 23 | 24 | from plexus.ros2.plexus_pkg.plexus_pkg.allegro_driver import AllegroDriver 25 | 26 | class ROSAllegroController(rclpy.node.Node): 27 | def __init__(self) -> None: 28 | super().__init__('allegro_controller') 29 | 30 | self.declare_parameter('can_interface', 'can0') 31 | try: 32 | self.robot = AllegroDriver(can_channel=self.get_parameter('can_interface').value) 33 | except RuntimeError as e: 34 | self.get_logger().fatal(str(e)) 35 | raise e 36 | self.dt = 0.003 37 | self.dof = 16 38 | self.timeout = 30_000_000_000 39 | 40 | #controller gains 41 | for i in range(16): 42 | self.declare_parameter(f'gains_pd/{i}/p', 6.) 43 | self.declare_parameter(f'gains_pd/{i}/d', 0.15) 44 | self.declare_parameter(f'position_offset/{i}', 0.) 45 | self.declare_parameter(f'qv_alpha', 0.7) 46 | self.declare_parameter('torque_limit', 0.5) 47 | self.q_des = None 48 | 49 | # state 50 | self.joint_state_publisher = self.create_publisher(JointState, "joint_states", qos_profile_system_default) 51 | self.joint_target_sub = self.create_subscription(JointState, "joint_cmd", self.joint_cmd_cb, qos_profile_system_default) 52 | self.lib_cmd_sub = self.create_subscription(String, "lib_cmd", self.lib_cmd_cb, qos_profile_system_default) 53 | self.add_on_set_parameters_callback(self.param_cb) 54 | 55 | self.create_timer(self.dt, self.control_loop) 56 | 57 | self.q = None 58 | self.prev_q = None 59 | self.qv = None 60 | self.torque_des = None 61 | self.motor_status = None 62 | 63 | self.last_control = self.get_clock().now() 64 | 65 | def param_cb(self, param: List[Parameter]) -> SetParametersResult: 66 | for p in param: 67 | print(f'param update {p.name}: {p.value}') 68 | return SetParametersResult(successful=True) 69 | 70 | def lib_cmd_cb(self, msg: String) -> None: 71 | if msg.data == "home": 72 | q_home= np.zeros(16) 73 | q_home[12] = 0.4 74 | self._move_joint(q_home, torque_target=False) 75 | elif msg.data == "off": 76 | self._set_motor(False) 77 | 78 | def joint_cmd_cb(self, msg: JointState) -> None: 79 | if len(msg.position) > 0 and len(msg.effort) > 0: 80 | self.get_logger().error(f"received both position and effort commands, ignoring") 81 | return 82 | 83 | if len(msg.position) == 16: 84 | self._move_joint(msg.position, torque_target=False) 85 | elif len(msg.effort) == 16: 86 | self._move_joint(msg.effort, torque_target=True) 87 | else: 88 | self.get_logger().warning(f'invalid cmd: {msg}') 89 | 90 | def _set_motor(self, is_on: bool): 91 | if self.motor_status is None or self.motor_status != is_on: 92 | self.robot.set_motor(is_on) 93 | self.get_logger().info(f"motor switched {is_on}") 94 | self.motor_status = is_on 95 | 96 | def _move_joint(self, target_cmd, torque_target=False): 97 | if torque_target: 98 | if self.q_des is not None: 99 | self.get_logger().info(f"switching to torque mode") 100 | self.q_des = None 101 | self.torque_des = np.array(target_cmd) 102 | else: 103 | if self.torque_des is not None: 104 | self.get_logger().info(f"switching to position mode") 105 | self.q_des = np.array(target_cmd) 106 | self.torque_des = None 107 | self.cmd_updatetime = self.get_clock().now() 108 | self._set_motor(True) 109 | 110 | def control_loop(self) -> None: 111 | 112 | # timing 113 | start_control = self.get_clock().now() 114 | interval = start_control - self.last_control 115 | self.last_control = start_control 116 | 117 | # getting parameters 118 | self.kp = np.array([self.get_parameter(f'gains_pd/{i}/p').value for i in range(self.dof)]) 119 | self.kd = np.array([self.get_parameter(f'gains_pd/{i}/d').value for i in range(self.dof)]) 120 | self.position_offset= np.array([self.get_parameter(f'position_offset/{i}').value for i in range(self.dof)]) 121 | qv_alpha = self.get_parameter('qv_alpha').value 122 | 123 | if self.q is not None: 124 | self.prev_q = self.q 125 | 126 | self.q = self.robot.get_joint_pos() + self.position_offset 127 | 128 | #initialize 129 | if self.prev_q is None: 130 | self.prev_q = self.q 131 | 132 | #velocity estimate 133 | qv_findiff = (self.q - self.prev_q) / (interval.nanoseconds /1e9) 134 | if self.qv is None: 135 | self.qv = qv_findiff 136 | else: 137 | self.qv = (1-qv_alpha) * self.qv + qv_alpha * qv_findiff 138 | 139 | if self.q_des is None and self.torque_des is None: 140 | self._move_joint(self.q, torque_target=False) 141 | 142 | if self.torque_des is None: 143 | #PD 144 | err = self.q_des - self.q 145 | torque = self.kp * err - self.kd * self.qv 146 | else: 147 | torque = self.torque_des 148 | 149 | torque_limit = self.get_parameter('torque_limit').value 150 | torque = np.clip(torque, -torque_limit, torque_limit) 151 | self.robot.set_torque(torque) 152 | 153 | if (start_control - self.cmd_updatetime ).nanoseconds > self.timeout: 154 | self._set_motor(False) 155 | 156 | #publish 157 | msg = JointState() 158 | msg.header.stamp = self.get_clock().now().to_msg() 159 | msg.name = [f'allegro_joint_{i}.0' for i in range(16)] 160 | msg.position = self.q.tolist() 161 | msg.velocity = self.qv.tolist() 162 | msg.effort = torque.tolist() 163 | self.joint_state_publisher.publish(msg) 164 | 165 | # check timing 166 | if interval.nanoseconds/1e9 > 2.0 * self.dt: 167 | self.get_logger().warning(f'slow control loop {interval.nanoseconds/1e9} > {self.dt}', throttle_duration_sec=1) 168 | 169 | control_time = self.get_clock().now() - start_control 170 | if control_time.nanoseconds/1e9 > self.dt * 0.9: 171 | self.get_logger().warn(f"control time {control_time.nanoseconds/1e9} near/over {self.dt}", throttle_duration_sec=1) 172 | 173 | 174 | def main() -> None: 175 | rclpy.init() 176 | try: 177 | pdnode = ROSAllegroController() 178 | rclpy.spin(pdnode) 179 | except KeyboardInterrupt: 180 | pass 181 | except RuntimeError as e: 182 | print("ERROR") 183 | 184 | 185 | if __name__ == '__main__': 186 | main() 187 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/plexus_pkg/allegro_driver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | # Install 9 | # python -m pip install python-can 10 | 11 | # Protocol 12 | # http://wiki.wonikrobotics.com/AllegroHandWiki/images/e/eb/V4_AllegroHandUsersManual_1.1.pdf 13 | 14 | import argparse 15 | import math 16 | import struct 17 | import time 18 | from enum import Enum 19 | from typing import Any, List 20 | 21 | import can 22 | import numpy as np 23 | from numpy.typing import NDArray 24 | 25 | """ 26 | http://wiki.wonikrobotics.com/AllegroHandWiki/index.php/CAN_Protocol_v4.0 27 | 28 | 0x20 (position requests) 29 | (000.000976) can0 080 [0] remote request 30 | (000.000079) can0 084 [0] remote request 31 | (000.000040) can0 088 [0] remote request 32 | (000.000059) can0 08C [0] remote request 33 | (000.000044) can0 080 [8] CA FD BD FE 90 FF CE FF 34 | (000.000150) can0 084 [8] F9 FF CF FE 9A FF BE FF 35 | (000.000116) can0 088 [8] 18 00 D3 FE A7 FF D6 FF 36 | (000.000174) can0 08C [8] 34 0A EF FF AF 00 FC FF 37 | 0x80 (info) 38 | (000.000143) can0 200 [0] remote request 39 | (000.000173) can0 200 [7] 02 04 06 04 00 3C 05 40 | 0x38 (temp) 41 | (000.000241) can0 0E0 [0] remote request 42 | (000.000040) can0 0E4 [0] remote request 43 | (000.000039) can0 0E8 [0] remote request 44 | (000.000040) can0 0EC [0] remote request 45 | (000.000040) can0 0E0 [4] 2B 2A 29 25 46 | (000.000040) can0 0E4 [4] 29 2B 29 27 47 | (000.000138) can0 0E8 [4] 27 27 27 24 48 | (000.000081) can0 0EC [4] 30 26 24 F6 49 | 0x60 (set torque) 50 | (000.000209) can0 180 [8] 02 00 CB 00 42 00 25 00 51 | (000.000079) can0 184 [8] 01 00 B9 00 4A 00 33 00 52 | (000.000040) can0 188 [8] F1 FF C9 00 38 00 1F 00 53 | (000.000040) can0 18C [8] 58 02 05 00 8D FF FA FF 54 | """ 55 | 56 | 57 | class AllegroCommand(Enum): 58 | """ 59 | https://github.com/simlabrobotics/allegro_hand_ros_v4/blob/master/src/allegro_hand_driver/src/candrv/candef.h 60 | """ 61 | 62 | # Define CAN Command 63 | ID_CMD_SYSTEM_ON = 0x40 64 | ID_CMD_SYSTEM_OFF = 0x41 65 | ID_CMD_SET_TORQUE = 0x60 66 | ID_CMD_SET_TORQUE_1 = ID_CMD_SET_TORQUE + 0 67 | ID_CMD_SET_TORQUE_2 = ID_CMD_SET_TORQUE + 1 68 | ID_CMD_SET_TORQUE_3 = ID_CMD_SET_TORQUE + 2 69 | ID_CMD_SET_TORQUE_4 = ID_CMD_SET_TORQUE + 3 70 | ID_CMD_SET_POSE_1 = 0xE0 71 | ID_CMD_SET_POSE_2 = 0xE1 72 | ID_CMD_SET_POSE_3 = 0xE2 73 | ID_CMD_SET_POSE_4 = 0xE3 74 | ID_CMD_SET_PERIOD = 0x81 75 | ID_CMD_CONFIG = 0x68 76 | 77 | # Define CAN Data Reqeust (RTR) 78 | ID_RTR_HAND_INFO = 0x80 79 | ID_RTR_SERIAL = 0x88 80 | ID_RTR_FINGER_POSE = 0x20 81 | ID_RTR_FINGER_POSE_1 = ID_RTR_FINGER_POSE + 0 82 | ID_RTR_FINGER_POSE_2 = ID_RTR_FINGER_POSE + 1 83 | ID_RTR_FINGER_POSE_3 = ID_RTR_FINGER_POSE + 2 84 | ID_RTR_FINGER_POSE_4 = ID_RTR_FINGER_POSE + 3 85 | ID_RTR_IMU_DATA = 0x30 86 | ID_RTR_TEMPERATURE = 0x38 87 | ID_RTR_TEMPERATURE_1 = ID_RTR_TEMPERATURE + 0 88 | ID_RTR_TEMPERATURE_2 = ID_RTR_TEMPERATURE + 1 89 | ID_RTR_TEMPERATURE_3 = ID_RTR_TEMPERATURE + 2 90 | ID_RTR_TEMPERATURE_4 = ID_RTR_TEMPERATURE + 3 91 | 92 | @property 93 | def CAN_CMD_ID(self) -> int: 94 | return self.value << 2 95 | 96 | 97 | class AllegroDriver: 98 | def __init__(self, can_channel: str = "can0", drain: bool = True) -> None: 99 | try: 100 | self.bus = can.Bus( 101 | interface="socketcan", 102 | channel=can_channel, 103 | can_filters=[ 104 | { 105 | "can_id": AllegroCommand.ID_RTR_FINGER_POSE.CAN_CMD_ID, 106 | "can_mask": 0xFF0, # all finger pose 1111,1111,0000 107 | "extended": False, 108 | } # get position 109 | ], 110 | ) 111 | except OSError: 112 | self.bus = None 113 | raise RuntimeError( 114 | "CAN device not found, \ 115 | check if plexus USBC is plugged in, see trouble shooting here \ 116 | https://python-can.readthedocs.io/en/stable/interfaces/socketcan.html" 117 | ) 118 | 119 | self.misc_bus = can.Bus( 120 | interface="socketcan", 121 | channel=can_channel, 122 | can_filters=[ 123 | { 124 | "can_id": AllegroCommand.ID_RTR_HAND_INFO.CAN_CMD_ID, 125 | "can_mask": 0xFFC, 126 | "extended": False, 127 | }, # get info (0x80<<2) 128 | { 129 | "can_id": AllegroCommand.ID_RTR_TEMPERATURE.CAN_CMD_ID, 130 | "can_mask": 0xFF0, # all finger temp 1111, 1111, 0000 131 | "extended": False, 132 | }, # get temp (0x38<<2 - 0x3B <<2) 133 | { 134 | "can_id": AllegroCommand.ID_RTR_SERIAL.CAN_CMD_ID, 135 | "can_mask": 0xFFC, 136 | "extended": False, 137 | }, # get serial(0x88 <<2) 138 | ], 139 | ) 140 | 141 | # properly shutdown hand that's still running 142 | self.set_period() 143 | while drain: 144 | msg = self.bus.recv(timeout=0.005) 145 | if msg is not None: 146 | if msg.is_error_frame: 147 | raise RuntimeError("CAN receiving error frame, check allegro hand") 148 | elif not msg.is_rx: 149 | raise RuntimeError( 150 | "Another program sending can command, you might have another driver running" 151 | ) 152 | else: 153 | print(f"draining packet {msg}") 154 | else: 155 | break 156 | 157 | def shutdown(self) -> None: 158 | try: 159 | if self.bus: 160 | self.set_torque([0.0] * 16) 161 | self.set_motor(False) 162 | self.set_period(0, 0, 0, 0) 163 | except Exception as e: 164 | print(str(e)) 165 | finally: 166 | if self.bus: 167 | self.bus.shutdown() 168 | self.misc_bus.shutdown() 169 | 170 | def __del__(self) -> None: 171 | self.shutdown() 172 | 173 | def send_msg( 174 | self, 175 | msg_id: int, 176 | data: Any = None, 177 | bus: can.Bus = None, 178 | is_remote_frame: bool = False, 179 | ) -> None: 180 | msg = can.Message( 181 | arbitration_id=msg_id << 2, 182 | data=data, 183 | is_remote_frame=is_remote_frame, 184 | is_extended_id=False, 185 | ) 186 | 187 | if bus is None: 188 | bus = self.bus 189 | 190 | try: 191 | bus.send(msg) 192 | except can.exceptions.CanOperationError as e: 193 | print(e) 194 | raise RuntimeError( 195 | "can bus present, but not ready - did you turn on allegrohand" 196 | ) 197 | 198 | def send_rtr_request( 199 | self, bus: can.Bus, msg_id: int, timeout: float = 0.01 200 | ) -> can.Message: 201 | self.send_msg(msg_id, is_remote_frame=True, bus=bus) 202 | msg = bus.recv(timeout) 203 | if msg is None: 204 | raise TimeoutError() 205 | assert ( 206 | msg_id == msg.arbitration_id >> 2 207 | ), f"received remote frame \ 208 | allegro msg_id {hex(msg.arbitration_id>>2)}(can msg_id = {hex(msg.arbitration_id)}>>2) \ 209 | not match requested allegro msg_id {hex(msg_id)}" 210 | return msg 211 | 212 | def get_serial(self) -> str: 213 | msg = self.send_rtr_request(self.misc_bus, AllegroCommand.ID_RTR_SERIAL.value) 214 | return msg.data.decode().rstrip("\x00") 215 | 216 | def get_temp(self) -> List[int]: 217 | temp: List[int] = [] 218 | for finger in range(4): 219 | msg_id = AllegroCommand.ID_RTR_TEMPERATURE.value + finger 220 | msg = self.send_rtr_request(self.misc_bus, msg_id=msg_id) 221 | assert msg.arbitration_id >> 2 == msg_id, "received wrong packet" 222 | try: 223 | temp += struct.unpack("4B", msg.data) 224 | except struct.error as e: 225 | print(msg) 226 | raise e 227 | return temp 228 | 229 | def get_joint_pos(self) -> NDArray: 230 | temp: List[float] = [] 231 | for finger in range(4): 232 | msg = self.send_rtr_request( 233 | self.bus, msg_id=AllegroCommand.ID_RTR_FINGER_POSE.value + finger 234 | ) 235 | temp += struct.unpack("4h", msg.data) 236 | return np.array(temp) * math.pi / 180 * 333 / 65536 237 | 238 | def get_info(self) -> dict: 239 | msg = self.send_rtr_request( 240 | self.misc_bus, msg_id=AllegroCommand.ID_RTR_HAND_INFO.value 241 | ) 242 | hw_ver, fw_ver, is_left_hand, palm_temp, stat = struct.unpack("hhbBB", msg.data) 243 | return { 244 | "hw_ver": hex(hw_ver), 245 | "sw_ver": hex(fw_ver), 246 | "hand": "left" if is_left_hand else "right", 247 | "palm_temp": palm_temp, 248 | "stat": hex(stat), 249 | "motor": bool(stat & 0x1), 250 | "joint_temp_fault": bool(stat & 0x2), 251 | "joint_temp_throttle": bool(stat & 0x4), 252 | "joint_comm_fault": bool(stat & 0x8), 253 | "palm_temp_fault": bool(stat & 0x10), 254 | } 255 | 256 | def set_motor(self, is_on: bool) -> None: 257 | print(f"motor {is_on}") 258 | if is_on: 259 | self.send_msg(msg_id=AllegroCommand.ID_CMD_SYSTEM_ON.value) 260 | else: 261 | self.send_msg(msg_id=AllegroCommand.ID_CMD_SYSTEM_OFF.value) 262 | 263 | def set_torque(self, torqueN: List[float]) -> None: 264 | # https://github.com/0wu/ros-allegro/blob/ros2-main/ros-allegro/allegro_hand_driver/src/AllegroHandDrv.cpp#L70C1-L71C1 265 | # PWM Range (-1200, 1200) 266 | assert len(torqueN) == 16 267 | torquePWM = list(map(lambda x: int(min(max(-1.0, x), 1.0) * 1200.0), torqueN)) 268 | for finger in range(4): 269 | data = struct.pack("4h", *torquePWM[finger * 4 : finger * 4 + 4]) 270 | self.send_msg( 271 | msg_id=AllegroCommand.ID_CMD_SET_TORQUE.value + finger, data=data 272 | ) 273 | 274 | def set_period( 275 | self, joint_pos: int = 0, imu: int = 0, temp: int = 0, status: int = 0 276 | ) -> None: 277 | data = struct.pack("HHHH", joint_pos, imu, temp, status) 278 | self.send_msg(msg_id=AllegroCommand.ID_CMD_SET_PERIOD.value, data=data) 279 | 280 | 281 | def test_torque(can_channel: str) -> None: 282 | print("==== Testing {} ====".format(can_channel)) 283 | robot = AllegroDriver(can_channel=can_channel) 284 | t = time.perf_counter() 285 | for i in range(3): 286 | print(robot.get_temp()) 287 | print(time.perf_counter() - t) 288 | print(robot.get_serial()) 289 | 290 | robot.set_torque([0] * 16) 291 | robot.set_motor(True) 292 | for i in range(3): 293 | robot.set_torque( 294 | [ 295 | -0.0, 296 | ] 297 | * 16 298 | ) 299 | with np.printoptions( 300 | linewidth=100, 301 | formatter={"float": lambda x: np.format_float_positional(x, precision=2)}, 302 | ): 303 | print("hand status", robot.get_info()) 304 | print("joint position", robot.get_joint_pos()) 305 | time.sleep(0.003) 306 | 307 | 308 | def main() -> None: 309 | parser = argparse.ArgumentParser() 310 | parser.add_argument( 311 | "--can_channel", default=None, type=str, help="can channel, empty for all" 312 | ) 313 | args = parser.parse_args() 314 | 315 | if args.can_channel is None: 316 | interfaces = can.detect_available_configs(interfaces="socketcan") 317 | for iface in interfaces: 318 | test_torque(iface["channel"]) 319 | else: 320 | test_torque(args.can_channel) 321 | 322 | 323 | if __name__ == "__main__": 324 | main() 325 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/plexus_pkg/allegro_info_node.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # All rights reserved. 5 | 6 | # This source code is licensed under the license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | 10 | from typing import List 11 | import numpy as np 12 | import argparse 13 | import signal 14 | from multiprocessing import Process 15 | 16 | import rclpy 17 | from rclpy.utilities import remove_ros_args 18 | import rclpy.logging 19 | import rclpy.node 20 | import rclpy.executors 21 | from sensor_msgs.msg import JointState 22 | from std_msgs.msg import Float32MultiArray, String 23 | from rclpy.qos import qos_profile_system_default 24 | from rcl_interfaces.msg import SetParametersResult, Parameter 25 | from diagnostic_msgs.msg import DiagnosticStatus, DiagnosticArray, KeyValue 26 | 27 | from plexus.ros2.plexus_pkg.plexus_pkg.allegro_driver import AllegroDriver 28 | 29 | class ROSAllegroInfo(rclpy.node.Node): 30 | def __init__(self) -> None: 31 | super().__init__('allegro_info') 32 | self.status_publisher = self.create_publisher(DiagnosticArray, "status", qos_profile_system_default) 33 | self.temp_publisher = self.create_publisher(Float32MultiArray, "joint_temperature", qos_profile_system_default) 34 | self.declare_parameter('can_interface', 'can0') 35 | try: 36 | self.robot = AllegroDriver(can_channel=self.get_parameter('can_interface').value, drain=False) 37 | except RuntimeError as e: 38 | self.get_logger().fatal(str(e)) 39 | raise e 40 | 41 | self.create_timer(1, self.info_loop) 42 | 43 | def info_loop(self): 44 | info = self.robot.get_info() 45 | temp = self.robot.get_temp() 46 | 47 | diagmsg = DiagnosticArray() 48 | diagmsg.header.stamp = self.get_clock().now().to_msg() 49 | 50 | status = DiagnosticStatus() 51 | diagmsg.status.append(status) 52 | status.name = "status" 53 | status.values=[KeyValue(key=k, value=str(v)) for k, v in info.items()] 54 | 55 | status = DiagnosticStatus() 56 | status.name = 'joint_temp' 57 | diagmsg.status.append(status) 58 | status.values=[KeyValue(key=f'joint_temp_{i}', value=str(v)) for i, v in enumerate(temp)] 59 | 60 | self.status_publisher.publish(diagmsg) 61 | self.temp_publisher.publish(Float32MultiArray(data=temp)) 62 | 63 | 64 | def main() -> None: 65 | rclpy.init() 66 | infonode= ROSAllegroInfo() 67 | try: 68 | rclpy.spin(infonode) 69 | except KeyboardInterrupt as e: 70 | rclpy.logging.get_logger(__file__).info('Ctrl-C received, shutting down') 71 | 72 | if __name__ == '__main__': 73 | main() 74 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/plexus_pkg/plexus_pb_v1/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # Generated by the protocol buffer compiler. DO NOT EDIT! 7 | # sources: plexus.proto 8 | # plugin: python-betterproto 9 | 10 | from dataclasses import dataclass 11 | from typing import Optional 12 | 13 | import betterproto 14 | 15 | 16 | class Finger(betterproto.Enum): 17 | NONE = 0 18 | INDEX = 1 19 | MIDDLE = 2 20 | PINKY = 3 21 | THUMB = 4 22 | PALM = 5 23 | 24 | 25 | class ResetControlResetType(betterproto.Enum): 26 | NONE = 0 27 | SOFT_MAGNETIC = 1 28 | HARD_MAGNETIC = 2 29 | POWER_ON = 3 30 | POWER_OFF = 4 31 | POWER_CYCLE = 5 32 | 33 | 34 | @dataclass(eq=False, repr=False) 35 | class Mag(betterproto.Message): 36 | x: float = betterproto.float_field(1) 37 | y: float = betterproto.float_field(2) 38 | z: float = betterproto.float_field(3) 39 | temperature: float = betterproto.float_field(4) 40 | 41 | 42 | @dataclass(eq=False, repr=False) 43 | class Data(betterproto.Message): 44 | timestamp: int = betterproto.uint32_field(1) 45 | sample: int = betterproto.uint32_field(2) 46 | finger: "Finger" = betterproto.enum_field(3) 47 | link: int = betterproto.int32_field(4) 48 | sensor_id: int = betterproto.int32_field(5) 49 | mag: "Mag" = betterproto.message_field(6) 50 | 51 | 52 | @dataclass(eq=False, repr=False) 53 | class OdrControl(betterproto.Message): 54 | data_rate: int = betterproto.int32_field(1) 55 | data_mode: int = betterproto.int32_field(2) 56 | 57 | 58 | @dataclass(eq=False, repr=False) 59 | class AxisControl(betterproto.Message): 60 | x_enable: bool = betterproto.bool_field(1) 61 | y_enable: bool = betterproto.bool_field(2) 62 | z_enable: bool = betterproto.bool_field(3) 63 | 64 | 65 | @dataclass(eq=False, repr=False) 66 | class ResetControl(betterproto.Message): 67 | type: "ResetControlResetType" = betterproto.enum_field(1) 68 | 69 | 70 | @dataclass(eq=False, repr=False) 71 | class SensorStatus(betterproto.Message): 72 | finger: "Finger" = betterproto.enum_field(1) 73 | link: int = betterproto.int32_field(2) 74 | sensor_id: int = betterproto.int32_field(3) 75 | present: bool = betterproto.bool_field(4) 76 | 77 | 78 | @dataclass(eq=False, repr=False) 79 | class PowerStatus(betterproto.Message): 80 | timestamp: int = betterproto.uint32_field(1) 81 | voltage: float = betterproto.float_field(2) 82 | current: float = betterproto.float_field(3) 83 | power: float = betterproto.float_field(4) 84 | 85 | 86 | @dataclass(eq=False, repr=False) 87 | class Control(betterproto.Message): 88 | odr: Optional["OdrControl"] = betterproto.message_field( 89 | 1, optional=True, group="_odr" 90 | ) 91 | axis: Optional["AxisControl"] = betterproto.message_field( 92 | 2, optional=True, group="_axis" 93 | ) 94 | reset: Optional["ResetControl"] = betterproto.message_field( 95 | 3, optional=True, group="_reset" 96 | ) 97 | 98 | 99 | @dataclass(eq=False, repr=False) 100 | class Status(betterproto.Message): 101 | sensor_status: Optional["SensorStatus"] = betterproto.message_field( 102 | 1, optional=True, group="_sensor_status" 103 | ) 104 | power_status: Optional["PowerStatus"] = betterproto.message_field( 105 | 2, optional=True, group="_power_status" 106 | ) 107 | 108 | 109 | @dataclass(eq=False, repr=False) 110 | class Plexus(betterproto.Message): 111 | control: Optional["Control"] = betterproto.message_field( 112 | 1, optional=True, group="_control" 113 | ) 114 | data: Optional["Data"] = betterproto.message_field(2, optional=True, group="_data") 115 | status: Optional["Status"] = betterproto.message_field( 116 | 3, optional=True, group="_status" 117 | ) 118 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/plexus_pkg/sensor_patch.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | #!/usr/bin/env python 10 | import os 11 | import sys 12 | import threading 13 | import rclpy 14 | from sensor_msgs.msg import MagneticField 15 | from plexus.ros2.plexus_pkg.msg import PowerStatus 16 | from std_msgs.msg import Header 17 | from geometry_msgs.msg import Vector3 18 | from plexus.ros2.plexus_pkg.plexus_pkg.plexus import Plexus 19 | 20 | def main(port) -> None: 21 | # python -m serial.tools.list_ports -v 22 | 23 | plexus_obj = Plexus(port) 24 | node=rclpy.create_node('sensor_patch') 25 | threading.Thread(target=rclpy.spin, args=(node,), daemon=True).start() 26 | 27 | pubs = {} 28 | def pub(topic, msg): 29 | msg.header.stamp=node.get_clock().now().to_msg() 30 | if topic in pubs: 31 | pub = pubs[topic] 32 | else: 33 | pub = node.create_publisher(type(msg), topic, rclpy.qos.ReliabilityPolicy.RELIABLE) 34 | pubs[topic]=pub 35 | pub.publish(msg) 36 | 37 | while plexus_obj.is_open() and rclpy.ok(): 38 | data = plexus_obj.read() 39 | if data is None: 40 | node.get_logger().warn("plexus receive a None packet, serial port timeout") 41 | continue 42 | if data.data is not None: 43 | topic = f"reskin/finger{data.data.finger}/link{data.data.link}/sensor{data.data.sensor_id}" 44 | msg = MagneticField( 45 | magnetic_field = Vector3(x=data.data.mag.x, y=data.data.mag.y, z=data.data.mag.z) 46 | ) 47 | pub(topic, msg) 48 | 49 | elif data.status.power_status is not None: 50 | pub(f"plexus/power_status", PowerStatus( 51 | voltage=data.status.power_status.voltage, 52 | current=data.status.power_status.current, 53 | power=data.status.power_status.power, 54 | )) 55 | else: 56 | node.get_logger().warn(f"unknown message type {data}, please add in {__file__}") 57 | 58 | 59 | if __name__ == "__main__": 60 | rclpy.init(args=sys.argv) 61 | # Check if /dev/ttyACM0 exists 62 | 63 | default_device = '/dev/ttyPlexus' 64 | if os.path.exists(default_device): 65 | main(port=default_device) 66 | else: 67 | main(port='/dev/ttyACM0') 68 | sys.exit() 69 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/resource/plexus_pkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/facebookresearch/digit-plexus/7ad41b80626d52238171e26977212444cd78f44b/plexus/ros2/plexus_pkg/resource/plexus_pkg -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/setup.cfg: -------------------------------------------------------------------------------- 1 | [develop] 2 | script_dir=$base/lib/plexus_pkg 3 | [install] 4 | install_scripts=$base/lib/plexus_pkg 5 | -------------------------------------------------------------------------------- /plexus/ros2/plexus_pkg/setup.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # All rights reserved. 4 | 5 | # This source code is licensed under the license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | from setuptools import find_packages, setup 10 | 11 | package_name = 'plexus_pkg' 12 | 13 | setup( 14 | name=package_name, 15 | version='0.0.0', 16 | packages=find_packages(include=['plexus_pkg']), 17 | data_files=[ 18 | ('share/ament_index/resource_index/packages', 19 | ['resource/' + package_name]), 20 | ('share/' + package_name, ['package.xml']), 21 | ('share/' + package_name + '/launch', ['launch/allegro_hand_launch.py', 'launch/sensor_patch_launch.py', 'launch/tmr_hand_launch.py',]), 22 | ], 23 | install_requires=['setuptools'], 24 | zip_safe=True, 25 | maintainer='krishna', 26 | maintainer_email='chaitanyantr@gmail.com', 27 | description='TODO: Package description', 28 | license='TODO: License declaration', 29 | tests_require=['pytest'], 30 | entry_points={ 31 | 32 | }, 33 | ) -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import setuptools 8 | from setuptools import find_packages 9 | 10 | with open("README.md", "r") as fh: 11 | long_description = fh.read() 12 | 13 | setuptools.setup( 14 | name="digitplexus", 15 | version="0.0.1", 16 | packages=find_packages(include=['plexus/ros2/plexus_pkg']), 17 | author="Meta Research", 18 | description="", 19 | long_description=long_description, 20 | long_description_content_type="text/markdown", 21 | url="https://github.com/facebookresearch/digit-plexus", 22 | classifiers=[ 23 | "Programming Language :: Python :: 3", 24 | "Intended Audience :: Science/Research", 25 | "Topic :: Scientific/Engineering :: Artificial Intelligence", 26 | ], 27 | python_requires=">=3.8", 28 | install_requires=[ 29 | "pyserial==3.5", 30 | "cobs==1.2.0", 31 | ], 32 | ) -------------------------------------------------------------------------------- /udev/99-metahand.rules: -------------------------------------------------------------------------------- 1 | # Metahand CAN 2 | # Test - python '/home/tingfan/GUM/gum/devices/metahand/allegro_driver.py' 3 | ACTION=="add|change", SUBSYSTEM=="usb", ATTR{idVendor}=="2833", ATTR{idProduct}=="b010", RUN+="/sbin/modprobe gs_usb" 4 | 5 | ACTION=="add|change", SUBSYSTEMS=="usb", ATTRS{idVendor}=="2833", ATTRS{idProduct}=="b010", \ 6 | RUN+="/bin/sh -c 'echo 2833 b010 > /sys/bus/usb/drivers/gs_usb/new_id'" 7 | 8 | SUBSYSTEM=="net", ENV{INTERFACE}=="can0|can3|MetahandCAN*", ATTRS{bInterfaceNumber}=="00", \ 9 | RUN+="/sbin/ip link set $name type can bitrate 1000000", \ 10 | RUN+="/sbin/ip link set $name up" 11 | 12 | # Metahand CTRL 13 | SUBSYSTEMS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2833", ATTR{idProduct}=="b011", GROUP:="plugdev", MODE:="0666" 14 | SUBSYSTEM=="tty", ATTRS{idVendor}=="2833", ATTRS{idProduct}=="b011", MODE:="0666", GROUP:="plugdev" SYMLINK+="ttyMetahand" 15 | SUBSYSTEM=="tty", ATTRS{idVendor}=="2cd9", ATTRS{idProduct}=="0021", MODE:="0666", GROUP:="plugdev" SYMLINK+="ttyCambrionix" 16 | 17 | # Robotiq FT Force/Torque sensor 18 | SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", MODE:="0666", GROUP:="plugdev" SYMLINK+="ttyFT300" 19 | 20 | # Metahand HUB 21 | SUBSYSTEMS=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="2833", ATTR{idProduct}=="b012", GROUP:="plugdev", MODE:="0666" -------------------------------------------------------------------------------- /udev/README.md: -------------------------------------------------------------------------------- 1 | # Device Install 2 | Scripts necessary to install physical devices, configure permissions and attributes. 3 | 4 | ### Install `udev` Device Rules 5 | 6 | ``` 7 | sudo ./install_devices.sh 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /udev/install_devices.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | USER_ID="$(id -u)" 4 | USER=$(logname) 5 | 6 | if [ "$USER_ID" -ne 0 ]; then 7 | echo "Please run this as root." 8 | exit 1 9 | fi 10 | 11 | INSTALL_DIR=$(dirname "$0") 12 | RULES_DIR="$INSTALL_DIR/rules/*.rules" 13 | 14 | for udev_rule in $RULES_DIR; do 15 | rule=$(basename "$udev_rule") 16 | echo "Installing $rule" 17 | cp $udev_rule /etc/udev/rules.d/$rule 18 | done 19 | 20 | echo "Adding $LOGNAME to group plugdev, video" 21 | adduser $USER plugdev 22 | adduser $USER video 23 | 24 | echo "Reloading udev rules..." 25 | udevadm control --reload-rules 26 | udevadm trigger 27 | 28 | echo "Finished, please re-insert devices." --------------------------------------------------------------------------------